biohazard-vfx/docs/stories/1.3.sticky-split-pattern-library.md
nicholai ed55376b9c
Some checks are pending
Build and Push to Docker Hub / Push Docker image to Docker Hub (push) Waiting to run
Build and Push Docker Image / build-and-push (push) Waiting to run
bmad-planning-complete
2025-09-24 10:54:01 -06:00

4.8 KiB
Raw Blame History

Status

Draft

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

{{agent_model_name_version}}

Debug Log References

Completion Notes List

File List

QA Results