#324
Horizontal scroll section
Vertical scrolling inside a pinned frame slides a row of four step cards sideways, with a progress bar underneath. The page scrolls down; the content moves across.
Hand this to your AI. It names the exact library parts, timings and accessibility promises of this demo.
Build the "Horizontal scroll section" pattern (@codeatlasdev/ui demo #324, motion/scroll) in my app.
Call get_demo({ ids: ["#324"] }) first and keep its structure. It needs @codeatlasdev/[email protected].
Use: Onboarding steps, feature tours and case-study timelines where a sequence reads better left to right than stacked.
Keep these library parts, with the props and tokens the demo uses:
- MotionStage, MotionCtx from "@codeatlasdev/ui"
Behaviour to keep:
- `MotionStage` from `@codeatlasdev/ui` with `loop={5600}`: autoplay scrolls the container, a wheel or touch scroll takes over
- `.hs__pin` is `position: sticky;` and keeps the frame fixed while `block-size: 30rem;` on `.hs__track` provides the scroll distance
- The rail is `inline-size: 400%` (four slides of `25%`) and travels `-75%` on X, so the last slide ends exactly in view
- Native: `animation-timeline: --hs` over `scroll-timeline: --hs block` on the scroller (the pin is `overflow: hidden`, so `scroll()` would bind to it); `@keyframes slide` runs from `translateX(0)` to `translateX(-75%)`, inside `@supports (animation-timeline: scroll())`
- Fallback without support: a `scroll` listener writes `--p` and the rail uses `translateX(calc(var(--p) * -75%))`
- Under reduced motion `--p` is `1`: the last slide is shown and the container does not scroll by itself
Exact motion (do not approximate):
- transform: translateX: animation-timeline: --hs, linear
Reduced motion: the demo handles it; keep that branch.
Keyboard: operable; keep the focus order and key handling.
Change only the copy and the data. Use the theme tokens (--ca-*), never raw colours. Library parts
- MotionStage
@codeatlasdev/ui
How it is built
- `MotionStage` from `@codeatlasdev/ui` with `loop={5600}`: autoplay scrolls the container, a wheel or touch scroll takes over
- `.hs__pin` is `position: sticky;` and keeps the frame fixed while `block-size: 30rem;` on `.hs__track` provides the scroll distance
- The rail is `inline-size: 400%` (four slides of `25%`) and travels `-75%` on X, so the last slide ends exactly in view
- Native: `animation-timeline: --hs` over `scroll-timeline: --hs block` on the scroller (the pin is `overflow: hidden`, so `scroll()` would bind to it); `@keyframes slide` runs from `translateX(0)` to `translateX(-75%)`, inside `@supports (animation-timeline: scroll())`
- Fallback without support: a `scroll` listener writes `--p` and the rail uses `translateX(calc(var(--p) * -75%))`
- Under reduced motion `--p` is `1`: the last slide is shown and the container does not scroll by itself
Related
Loading source.