#320
Staggered reveal on scroll
A feed of cards inside a scroll container: each row fades in and rises 24px as it enters, a short stagger between rows that arrive together.
Hand this to your AI. It names the exact library parts, timings and accessibility promises of this demo.
Build the "Staggered reveal on scroll" pattern (@codeatlasdev/ui demo #320, motion/scroll) in my app.
Call get_demo({ ids: ["#320"] }) first and keep its structure. It needs @codeatlasdev/[email protected].
Use: Lists, activity feeds, search results and dashboards that load more content as the user scrolls.
Keep these library parts, with the props and tokens the demo uses:
- Card, MotionStage, MotionCtx from "@codeatlasdev/ui"
Behaviour to keep:
- `MotionStage` from `@codeatlasdev/ui` with `loop={4600}`: autoplay scrolls the container itself, a wheel or touch scroll takes over
- `IntersectionObserver` with `root` set to the scroller and `threshold: 0.35`: a row is revealed once, when 35% of it is visible
- Hidden state is `opacity: 0;` with `transform: translateY(24px);`; the revealed state `.feed__row--in` sets `opacity: 1;` and `transform: translateY(0);`
- Returning to `root.scrollTop === 0` clears the revealed set, so a user scrolling down replays the stagger
- Stagger: the transitions share a delay of `calc(var(--i) * 80ms)`, where `--i` is the row index modulo 3 (`style="--i:{i % 3}"`)
- Autoplay scroll is driven by `requestAnimationFrame` over `2400` ms with an ease-in-out cubic
- Under reduced motion every row renders revealed (`m.reduced`) and nothing scrolls by itself
Exact motion (do not approximate):
- opacity, transform: translateY: 420ms, cubic-bezier(0.2, 0, 0, 1), stagger calc(var(--i) * 80ms)
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
- Card
@codeatlasdev/ui - MotionStage
@codeatlasdev/ui
How it is built
- `MotionStage` from `@codeatlasdev/ui` with `loop={4600}`: autoplay scrolls the container itself, a wheel or touch scroll takes over
- `IntersectionObserver` with `root` set to the scroller and `threshold: 0.35`: a row is revealed once, when 35% of it is visible
- Hidden state is `opacity: 0;` with `transform: translateY(24px);`; the revealed state `.feed__row--in` sets `opacity: 1;` and `transform: translateY(0);`
- Returning to `root.scrollTop === 0` clears the revealed set, so a user scrolling down replays the stagger
- Stagger: the transitions share a delay of `calc(var(--i) * 80ms)`, where `--i` is the row index modulo 3 (`style="--i:{i % 3}"`)
- Autoplay scroll is driven by `requestAnimationFrame` over `2400` ms with an ease-in-out cubic
- Under reduced motion every row renders revealed (`m.reduced`) and nothing scrolls by itself
Related
Loading source.