Fix concentration glow clipping at container edges
Add padding to the inner combatant list container so the box-shadow glow from the concentration-damage animation renders fully on all sides, preventing clipping by the scrollable parent's implicit overflow-x. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
# Specification Quality Checklist: Fix Concentration Shake Glow Clipping
|
||||
|
||||
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
||||
**Created**: 2026-03-11
|
||||
**Feature**: [spec.md](../spec.md)
|
||||
|
||||
## Content Quality
|
||||
|
||||
- [x] No implementation details (languages, frameworks, APIs)
|
||||
- [x] Focused on user value and business needs
|
||||
- [x] Written for non-technical stakeholders
|
||||
- [x] All mandatory sections completed
|
||||
|
||||
## Requirement Completeness
|
||||
|
||||
- [x] No [NEEDS CLARIFICATION] markers remain
|
||||
- [x] Requirements are testable and unambiguous
|
||||
- [x] Success criteria are measurable
|
||||
- [x] Success criteria are technology-agnostic (no implementation details)
|
||||
- [x] All acceptance scenarios are defined
|
||||
- [x] Edge cases are identified
|
||||
- [x] Scope is clearly bounded
|
||||
- [x] Dependencies and assumptions identified
|
||||
|
||||
## Feature Readiness
|
||||
|
||||
- [x] All functional requirements have clear acceptance criteria
|
||||
- [x] User scenarios cover primary flows
|
||||
- [x] Feature meets measurable outcomes defined in Success Criteria
|
||||
- [x] No implementation details leak into specification
|
||||
|
||||
## Notes
|
||||
|
||||
- All items pass. The spec is a focused bug fix with clear acceptance criteria and well-defined scope.
|
||||
- The Assumptions section mentions CSS techniques as examples of what might cause the issue, which is acceptable context without prescribing a solution.
|
||||
3
specs/033-fix-concentration-glow-clip/data-model.md
Normal file
3
specs/033-fix-concentration-glow-clip/data-model.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Data Model: Fix Concentration Glow Clipping
|
||||
|
||||
No data model changes required. This is a CSS-only visual bug fix. The existing domain model, state transitions, and component props remain unchanged.
|
||||
69
specs/033-fix-concentration-glow-clip/plan.md
Normal file
69
specs/033-fix-concentration-glow-clip/plan.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Implementation Plan: Fix Concentration Shake Glow Clipping
|
||||
|
||||
**Branch**: `033-fix-concentration-glow-clip` | **Date**: 2026-03-11 | **Spec**: [spec.md](spec.md)
|
||||
**Input**: Feature specification from `/specs/033-fix-concentration-glow-clip/spec.md`
|
||||
|
||||
## Summary
|
||||
|
||||
The concentration-damage glow animation (`box-shadow`) is clipped on left and right edges because the scrollable combatant list container's `overflow-y: auto` implicitly sets `overflow-x: auto` per CSS spec, creating a clipping context. The fix adds horizontal padding to the inner container so the glow has room to render within the overflow area.
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: TypeScript 5.8, CSS (Tailwind CSS v4)
|
||||
**Primary Dependencies**: React 19, Tailwind CSS v4
|
||||
**Storage**: N/A (no persistence changes)
|
||||
**Testing**: Vitest (visual verification — CSS-only fix)
|
||||
**Target Platform**: Web (modern browsers, 320px+ viewports)
|
||||
**Project Type**: Web application
|
||||
**Performance Goals**: 60fps animation, zero layout shift
|
||||
**Constraints**: No horizontal scrollbar, no layout shift, mobile-compatible
|
||||
**Scale/Scope**: Single CSS class change in one file
|
||||
|
||||
## Constitution Check
|
||||
|
||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||
|
||||
| Principle | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| I. Deterministic Domain Core | PASS | No domain changes |
|
||||
| II. Layered Architecture | PASS | Change is in adapter layer (web/UI) only |
|
||||
| III. Clarification-First | PASS | Root cause is clear, fix is straightforward |
|
||||
| IV. Escalation Gates | PASS | Fix matches spec scope exactly |
|
||||
| V. MVP Baseline Language | PASS | N/A for bug fix |
|
||||
| VI. No Gameplay Rules | PASS | N/A — visual fix only |
|
||||
|
||||
**Post-design re-check**: All gates still pass. No architectural changes introduced.
|
||||
|
||||
## Root Cause
|
||||
|
||||
1. The combatant list lives inside `<div className="flex-1 overflow-y-auto min-h-0">` (App.tsx:157)
|
||||
2. CSS spec: when `overflow-y` is non-`visible`, `overflow-x` computes to `auto` (not `visible`)
|
||||
3. The `concentration-glow` animation applies `box-shadow: 0 0 4px 2px #c084fc` (~6px outward spread)
|
||||
4. The implicit `overflow-x: auto` clips this box-shadow on left and right edges
|
||||
|
||||
## Fix Approach
|
||||
|
||||
Add horizontal padding (`px-2`, 8px) to the inner `<div className="flex flex-col pb-2">` at App.tsx:158. This gives the box-shadow room to render within the container's content area, avoiding clipping. `box-shadow` is paint-only and does not affect layout, so no scrollbar or shift will result.
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/033-fix-concentration-glow-clip/
|
||||
├── spec.md
|
||||
├── plan.md # This file
|
||||
├── research.md # Root cause analysis and fix strategy
|
||||
├── data-model.md # No data model changes
|
||||
├── quickstart.md # Verification steps
|
||||
└── tasks.md # Task breakdown (generated by /speckit.tasks)
|
||||
```
|
||||
|
||||
### Source Code (affected files)
|
||||
|
||||
```text
|
||||
apps/web/src/
|
||||
└── App.tsx # Line ~158: add px-2 to inner combatant list container
|
||||
```
|
||||
|
||||
**Structure Decision**: Existing monorepo structure. Only one file in the adapter layer (apps/web) is modified. No new files, no structural changes.
|
||||
20
specs/033-fix-concentration-glow-clip/quickstart.md
Normal file
20
specs/033-fix-concentration-glow-clip/quickstart.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Quickstart: Fix Concentration Glow Clipping
|
||||
|
||||
## What Changed
|
||||
|
||||
The scrollable combatant list container clips the `box-shadow` glow effect from the concentration-damage animation. The fix adds horizontal padding to the inner container so the glow has room to render.
|
||||
|
||||
## Files to Modify
|
||||
|
||||
1. **`apps/web/src/App.tsx`** — Add horizontal padding to the inner `<div>` inside the scrollable combatant list area (line ~158)
|
||||
|
||||
## How to Verify
|
||||
|
||||
1. Run `pnpm --filter web dev`
|
||||
2. Add a combatant to an encounter
|
||||
3. Toggle concentration on the combatant
|
||||
4. Reduce the combatant's HP (deal damage)
|
||||
5. Observe the purple glow animation — it should be fully visible on left and right edges
|
||||
6. Test at mobile widths (320px+) — no horizontal scrollbar should appear
|
||||
7. Add multiple concentrating combatants, deal damage to all simultaneously — each row's glow should be independently visible without overlap artifacts
|
||||
8. With a long encounter list (6+ combatants), scroll so a concentrating combatant is at the top or bottom edge of the visible area, deal damage — glow should still be fully visible
|
||||
35
specs/033-fix-concentration-glow-clip/research.md
Normal file
35
specs/033-fix-concentration-glow-clip/research.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Research: Fix Concentration Glow Clipping
|
||||
|
||||
## Root Cause Analysis
|
||||
|
||||
### Decision: The glow is clipped by the scrollable parent container's implicit overflow-x
|
||||
|
||||
**Rationale**: The combatant list is wrapped in a `<div className="flex-1 overflow-y-auto min-h-0">` (App.tsx:157). Per the CSS specification, when one overflow axis is set to a non-`visible` value (here `overflow-y: auto`), the other axis (`overflow-x`) computes to `auto` rather than remaining `visible`. This creates a clipping context that cuts off the `box-shadow` from the `concentration-glow` animation on the left and right edges.
|
||||
|
||||
The glow is defined as:
|
||||
```css
|
||||
box-shadow: 0 0 4px 2px #c084fc;
|
||||
```
|
||||
This extends ~6px outward from the combatant row element. The parent's implicit `overflow-x: auto` clips this outward extension.
|
||||
|
||||
**Alternatives considered**:
|
||||
- `border-radius` on the row causing clipping — rejected; `border-radius` shapes `box-shadow` but does not clip it
|
||||
- `translate` in the shake animation pushing the element off-screen — rejected; max displacement is only 3px and returns to 0
|
||||
|
||||
## Fix Strategy
|
||||
|
||||
### Decision: Add horizontal padding to the scrollable container to accommodate the glow spread
|
||||
|
||||
**Rationale**: The simplest fix is to add left/right padding to the scrollable container (or its inner flex-col child) so the `box-shadow` has room to render within the overflow area without being clipped. This avoids changing the overflow behavior (which is needed for vertical scrolling) and avoids restructuring the component hierarchy.
|
||||
|
||||
The glow spread is `4px blur + 2px spread = ~6px` outward. Adding `px-2` (8px) padding to the inner `<div className="flex flex-col pb-2">` at App.tsx:158 would provide enough space.
|
||||
|
||||
**Alternatives considered**:
|
||||
1. **Change `overflow-y-auto` to `overflow-y-scroll` + `overflow-x-visible`** — rejected; CSS spec still forces `overflow-x` to `auto` when `overflow-y` is non-`visible`
|
||||
2. **Use `outline` instead of `box-shadow`** — viable but changes the visual appearance; `outline` doesn't respect `border-radius` in all browsers
|
||||
3. **Use `inset box-shadow`** — would avoid overflow clipping but changes the visual effect from an outer glow to an inner glow
|
||||
4. **Negative margin + padding trick on the scrollable container** — more complex, same net effect as simple padding
|
||||
|
||||
### Decision: Verify no horizontal scrollbar is introduced
|
||||
|
||||
**Rationale**: Adding padding to the inner container should not cause a horizontal scrollbar since the content still fits within the parent. The `box-shadow` renders in the padding area but does not affect layout (box-shadow is a paint-only effect, not a layout-affecting property). No additional `overflow-x: hidden` should be needed.
|
||||
68
specs/033-fix-concentration-glow-clip/spec.md
Normal file
68
specs/033-fix-concentration-glow-clip/spec.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Feature Specification: Fix Concentration Shake Glow Clipping
|
||||
|
||||
**Feature Branch**: `033-fix-concentration-glow-clip`
|
||||
**Created**: 2026-03-11
|
||||
**Status**: Draft
|
||||
**Input**: User description: "Fix concentration shake glow clipped at container edges"
|
||||
|
||||
## User Scenarios & Testing *(mandatory)*
|
||||
|
||||
### User Story 1 - Concentration Damage Glow Visible (Priority: P1)
|
||||
|
||||
As a game master viewing the encounter tracker, when a concentrating creature takes damage and the shake + glow animation plays, I see the full glow effect without any visual clipping on the left or right edges.
|
||||
|
||||
**Why this priority**: This is the core bug being fixed. The glow animation is the primary visual feedback for concentration damage events, and clipping undermines its purpose.
|
||||
|
||||
**Independent Test**: Can be tested by dealing damage to a concentrating creature and visually verifying the glow extends fully without being cut off at container boundaries.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** a creature is concentrating on a spell, **When** the creature takes damage and the shake + glow animation triggers, **Then** the glow effect is fully visible on both the left and right sides throughout the entire animation duration
|
||||
2. **Given** a creature is concentrating and the encounter list has its default layout, **When** damage triggers the animation, **Then** no part of the glow is clipped or hidden by overflow constraints
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 - No Layout Side Effects (Priority: P1)
|
||||
|
||||
As a user on any device, the glow fix does not introduce horizontal scrollbars, layout shifts, or visual artifacts outside the animation area.
|
||||
|
||||
**Why this priority**: A fix that trades one visual bug for another (e.g., scroll jank) would be a regression. This is equally critical as the glow fix itself.
|
||||
|
||||
**Independent Test**: Can be tested by triggering the animation repeatedly on both desktop and mobile viewports and confirming no horizontal scrollbar appears and no elements shift position.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** the encounter tracker is displayed at desktop width, **When** the shake + glow animation plays, **Then** no horizontal scrollbar appears on the page or encounter container
|
||||
2. **Given** the encounter tracker is displayed at mobile width (320px - 480px), **When** the shake + glow animation plays, **Then** no layout shift occurs and the animation renders correctly within the viewport
|
||||
|
||||
---
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- What happens when multiple concentrating creatures take damage simultaneously? The glow on each row must remain independently visible without overlap artifacts.
|
||||
- What happens when the creature row is at the very top or bottom of a scrollable encounter list? The glow must still be fully visible.
|
||||
- What happens on very narrow viewports (below 320px)? The glow should degrade gracefully without causing overflow.
|
||||
|
||||
## Requirements *(mandatory)*
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- **FR-001**: The concentration damage glow effect MUST be fully visible on both left and right edges of the combatant row throughout the shake animation
|
||||
- **FR-002**: The glow fix MUST NOT introduce a horizontal scrollbar on the page or any parent container
|
||||
- **FR-003**: The glow fix MUST NOT cause any layout shift or repositioning of other elements during or after the animation
|
||||
- **FR-004**: The shake + glow animation MUST render correctly on mobile-width screens (320px and above)
|
||||
- **FR-005**: The glow effect MUST remain visually correct when multiple combatant rows animate simultaneously
|
||||
|
||||
## Success Criteria *(mandatory)*
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-001**: The glow effect is visually complete (no clipping) on 100% of concentration damage events across all supported viewport widths (320px and above)
|
||||
- **SC-002**: Zero horizontal scrollbar appearances caused by the glow animation at any viewport width
|
||||
- **SC-003**: Zero measurable layout shift (CLS = 0) introduced by the animation fix
|
||||
|
||||
## Assumptions
|
||||
|
||||
- The existing shake animation behavior and timing are correct and should be preserved; only the glow clipping needs to be fixed.
|
||||
- The glow effect uses CSS techniques (e.g., box-shadow, outline, or pseudo-elements) that may be clipped by `overflow: hidden` or similar properties on ancestor containers.
|
||||
- "Mobile-width screens" refers to viewports of 320px width and above, consistent with standard mobile device support.
|
||||
115
specs/033-fix-concentration-glow-clip/tasks.md
Normal file
115
specs/033-fix-concentration-glow-clip/tasks.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Tasks: Fix Concentration Shake Glow Clipping
|
||||
|
||||
**Input**: Design documents from `/specs/033-fix-concentration-glow-clip/`
|
||||
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, quickstart.md
|
||||
|
||||
**Tests**: No test tasks — this is a CSS-only visual fix. Verification is done via manual inspection per quickstart.md.
|
||||
|
||||
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
|
||||
|
||||
## Format: `[ID] [P?] [Story] Description`
|
||||
|
||||
- **[P]**: Can run in parallel (different files, no dependencies)
|
||||
- **[Story]**: Which user story this task belongs to (e.g., US1, US2)
|
||||
- Include exact file paths in descriptions
|
||||
|
||||
## Phase 1: Setup
|
||||
|
||||
**Purpose**: No setup needed — existing project, no new dependencies or configuration changes.
|
||||
|
||||
*(No tasks in this phase)*
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational (Blocking Prerequisites)
|
||||
|
||||
**Purpose**: No foundational work needed — the fix modifies existing CSS layout only.
|
||||
|
||||
*(No tasks in this phase)*
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 - Concentration Damage Glow Visible (Priority: P1) MVP
|
||||
|
||||
**Goal**: The concentration-damage glow effect is fully visible on both left and right edges without clipping.
|
||||
|
||||
**Independent Test**: Deal damage to a concentrating creature and verify the purple glow extends fully on all sides without being cut off at container edges.
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [x] T001 [US1] Add horizontal padding (`px-2`) to the inner combatant list container `<div className="flex flex-col pb-2">` in `apps/web/src/App.tsx` (line ~158) so the `box-shadow` glow renders within the overflow area instead of being clipped
|
||||
|
||||
**Checkpoint**: At this point, the glow should be fully visible on left and right edges.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 - No Layout Side Effects (Priority: P1)
|
||||
|
||||
**Goal**: The padding fix does not introduce horizontal scrollbars, layout shifts, or visual artifacts.
|
||||
|
||||
**Independent Test**: Trigger the animation at desktop and mobile widths (320px+), confirm no horizontal scrollbar appears and no elements shift position.
|
||||
|
||||
### Implementation for User Story 2
|
||||
|
||||
- [x] T002 [US2] Verify at desktop and mobile viewports (320px+) that the padding added in T001 does not cause a horizontal scrollbar or layout shift in `apps/web/src/App.tsx`; also verify that multiple concentrating rows animating simultaneously display independent glows without overlap artifacts; adjust padding value if needed
|
||||
|
||||
**Checkpoint**: Animation renders correctly at all viewport widths with no side effects.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Polish & Cross-Cutting Concerns
|
||||
|
||||
**Purpose**: Final validation and quality gates.
|
||||
|
||||
- [x] T003 Run `pnpm check` to ensure all quality gates pass (lint, typecheck, tests, coverage)
|
||||
- [x] T004 Run quickstart.md validation steps from `specs/033-fix-concentration-glow-clip/quickstart.md`
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
### Phase Dependencies
|
||||
|
||||
- **Phase 3 (US1)**: No prerequisites — single file change
|
||||
- **Phase 4 (US2)**: Depends on T001 completion (verifies T001 doesn't regress)
|
||||
- **Phase 5 (Polish)**: Depends on T001 and T002 completion
|
||||
|
||||
### User Story Dependencies
|
||||
|
||||
- **User Story 1 (P1)**: Independent — core fix
|
||||
- **User Story 2 (P1)**: Depends on US1 — verification of no side effects
|
||||
|
||||
### Within Each User Story
|
||||
|
||||
- US1: Single task (T001)
|
||||
- US2: Single verification task (T002) dependent on T001
|
||||
|
||||
### Parallel Opportunities
|
||||
|
||||
- No parallel opportunities — this is a 1-file, 1-line fix with sequential verification
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP First (User Story 1 Only)
|
||||
|
||||
1. Complete T001: Add padding to inner container
|
||||
2. **STOP and VALIDATE**: Visually verify glow is no longer clipped
|
||||
3. Complete T002: Verify no layout side effects
|
||||
4. Complete T003-T004: Quality gates and quickstart validation
|
||||
|
||||
### Incremental Delivery
|
||||
|
||||
1. T001 → Glow fix applied
|
||||
2. T002 → No regressions confirmed
|
||||
3. T003-T004 → Quality gates pass, ready to merge
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- This is a minimal CSS-only fix: one Tailwind class addition to one file
|
||||
- The root cause is CSS spec behavior: `overflow-y: auto` forces `overflow-x: auto`, clipping `box-shadow`
|
||||
- `box-shadow` is paint-only and does not affect layout, so padding accommodates the glow without shifting content
|
||||
- If `px-2` (8px) is insufficient for the 6px glow spread, increase to `px-3` (12px)
|
||||
Reference in New Issue
Block a user