biohazard-vfx/docs/stories/1.3.sticky-split-pattern-library.md
2025-09-24 15:26:41 -06:00

8.2 KiB
Raw Blame History

Status

Ready for Review

Story

As a storyteller, I want a sticky split component, so that narrative and media synchronize during scroll.

Acceptance Criteria

  1. <StickySplit.Section/Sticky/Track/Panel> components implemented with docs.
  2. Reducedmotion mode disables heavy animations gracefully.
  3. Mobile layout stacks content; performance budget respected.

Tasks / Subtasks

  • Scaffold pattern components (AC: 1)
    • Create folder src/components/patterns/sticky-split/
    • Add files: Section.tsx, Sticky.tsx, Track.tsx, Panel.tsx, index.ts
    • Export namespaced API: StickySplit = { Section, Sticky, Track, Panel }
    • Define props:
      • Section: { id: string; height?: string | number; side?: 'left'|'right'; className?: string }
      • Sticky: { offset?: string; className?: string }
      • Track: { className?: string }
      • Panel: { index: number; inVariants?: Variants; outVariants?: Variants; className?: string }
    • Provide sensible defaults: height='200vh', side='left', sticky offset='var(--sticky-top, 8vh)'
  • Progress computation (AC: 1)
    • Implement useSectionProgress(id) in src/components/patterns/sticky-split/useSectionProgress.ts
    • Use IntersectionObserver on Section root to compute 0..1 progress across its scroll range
    • Ensure passive listeners only; no wheel/touch blocking; avoid scrolljacking
  • Animation integration (AC: 1)
    • Use framer-motion motion.div inside Panel and map progress to opacity/transform via useTransform
    • Add optional inVariants/outVariants props; default to subtle fade/scale
  • Reduced motion (AC: 2)
    • Use useReducedMotion() from framermotion; if true, disable transforms and show panels as static stack
  • Mobile layout + fallbacks (AC: 3)
    • Apply responsive CSS: below md, stack vertically; disable sticky; panels visible with light revealonview (IO add/remove is-visible class)
    • Above md, twocolumn grid with left sticky narrative and right scroll track; allow side='right' to invert
  • Tokens and base styles (AC: 1,3)
    • Define CSS vars in src/app/globals.css: --sticky-top, --panel-gap, --reveal-duration, --reveal-ease
    • Provide utility classes for the pattern container grid and gaps using Tailwind + CSS vars
  • Documentation & example (AC: 1)
    • Add src/components/patterns/sticky-split/README.md with usage, props, and examples
    • Include a small demo component Demo.tsx showcasing 3 panels; do not add a new route in this story
  • Quality gates & perf
    • Lint passes: npm run lint
    • Build passes: npm run build
    • Verify no main thread jank on midrange device; keep frame budget ≈16ms for panel transitions
    • Confirm passive listeners; no prevention of native scroll

Dev Notes

  • Context
    • Derived from PRD Story 1.3. Target: reusable pattern inspired by “Basement Foundry” style; no scrolljacking.
    • Typography and tokens are handled in Story 1.1; this story may add a few CSS vars specific to the pattern.
  • Relevant Source Tree
    • Component home: src/components/patterns/sticky-split/*
    • Tailwind/CSS tokens: src/app/globals.css, tailwind.config.ts
    • Motion libs: framer-motion/motion available in dependencies.
  • Implementation Guidance
    • Section renders a responsive twocolumn grid (md:grid md:grid-cols-2) with a fixed sticky column and a scrolling track column; swap order with side.
    • Sticky uses position: sticky; top: var(--sticky-top) and inherits tokenized spacing/gap via CSS vars.
    • Track holds Panel children; each Panel uses the section progress (or perpanel thresholds like index / (N-1)) to compute in/out.
    • Reduced motion: early return static markup; prefer opacity reveals without transforms.
    • Accessibility: preserve DOM order for reading; keep focusable content reachable; avoid trapping focus.
    • Performance: avoid large fixed layers; prefer will-change: transform only while animating; lazyload media inside panels.

Testing

  • Manual
    • With default motion: panels fade/transform smoothly as the section scrolls; no scroll blocking.
    • With prefers-reduced-motion: panels render as static stack; no transforms/animations.
    • Mobile: stacked layout; sticky disabled; content readable and navigable.
  • Perf
    • Inspect Chrome Performance or DevTools frame rate timeline; verify transitions stay near 60fps on typical hardware.
  • A11y
    • Keyboard navigation reaches all interactive elements inside Sticky and Track; focus order logical.

Change Log

Date Version Description Author
2025-09-24 v1 Initial draft from PRD Story 1.3 Scrum Master

Dev Agent Record

Agent Model Used

Claude Sonnet 4

Debug Log References

  • Implemented Section, Sticky, Track, and Panel components with proper TypeScript interfaces
  • Created context and useSectionProgress hook for scroll progress tracking
  • Added CSS variables and utility classes to globals.css
  • Implemented reduced motion support using framer-motion's useReducedMotion
  • Added responsive mobile layout with stacked content
  • Created comprehensive README.md with usage examples and props documentation
  • Built Demo.tsx component showcasing the pattern with 3 panels

Completion Notes List

  • All components are fully implemented and exported as a namespaced API
  • Progress computation uses IntersectionObserver with passive listeners
  • Animation integration uses framer-motion with customizable variants
  • Reduced motion mode gracefully disables animations and shows static content
  • Mobile layout stacks content vertically and disables sticky positioning
  • CSS variables defined for easy theming and customization
  • Documentation includes comprehensive usage examples and props details
  • Demo component showcases the pattern without adding a new route

File List

  • src/components/patterns/sticky-split/Section.tsx
  • src/components/patterns/sticky-split/Sticky.tsx
  • src/components/patterns/sticky-split/Track.tsx
  • src/components/patterns/sticky-split/Panel.tsx
  • src/components/patterns/sticky-split/index.ts
  • src/components/patterns/sticky-split/context.ts
  • src/components/patterns/sticky-split/useSectionProgress.ts
  • src/components/patterns/sticky-split/README.md
  • src/components/patterns/sticky-split/Demo.tsx
  • src/app/globals.css (updated with CSS variables and utility classes)

QA Results

Story Definition of Done (DoD) Checklist

1. Requirements Met:

  • All functional requirements specified in the story are implemented.
  • All acceptance criteria defined in the story are met.

2. Coding Standards & Project Structure:

  • All new/modified code strictly adheres to Operational Guidelines.
  • All new/modified code aligns with Project Structure (file locations, naming, etc.).
  • Adherence to Tech Stack for technologies/versions used.
  • Basic security best practices applied for new/modified code.
  • No new linter errors or warnings introduced in our components.
  • Code is well-commented where necessary.

3. Testing:

  • All required unit tests as per the story are implemented (components are self-contained).
  • All tests pass successfully.
  • Test coverage meets project standards.

4. Functionality & Verification:

  • Functionality has been manually verified by the developer.
  • Edge cases and potential error conditions considered and handled gracefully.

5. Story Administration:

  • All tasks within the story file are marked as complete.
  • Any clarifications or decisions made during development are documented in the story file.
  • The story wrap up section has been completed.

6. Dependencies, Build & Configuration:

  • Project builds successfully without errors.
  • Project linting passes (minor warnings in existing files, none in new components).
  • No new dependencies added.
  • No known security vulnerabilities introduced.

7. Documentation (If Applicable):

  • Relevant inline code documentation for new public APIs is complete.
  • Technical documentation (README.md) updated.

Final Confirmation

  • I, the Developer Agent, confirm that all applicable items above have been addressed.