Radial Intro
betaAn intro that spins a stack of avatars out along a spiral into a ring on staggered springs, then lets the ring orbit slowly with every face upright.
- Display
- 1 file
- 2 npm packages
- Accessibility notes
- Animates with motion
Loading the example…
pnpm dlx @dowel-ui/cli add radial-intronpm packages installed: class-variance-authority, motion.
import { RadialIntro } from "@/components/ui/radial-intro";Default
Sizes
No Orbit
In View
Playground
<RadialIntro>
| Prop | Type | Default |
|---|---|---|
items (required) | RadialIntroItem[] | — |
handleRefReceives | Ref<RadialIntroHandle> | — |
onSettledCalled once every avatar has landed. | () => void | — |
orbitAfter landing, rotate the ring slowly. Avatars stay upright. | boolean | true |
orbitDurationSeconds per orbit. | number | 40 |
pauseLabelThe orbit pause toggle's accessible name. | string | "Pause rotation" |
size | "sm" | "md" | "lg" | "md" |
staggerMilliseconds between one avatar setting off and the next. | number | 80 |
trigger
| "mount" | "inView" | "mount" |
childrenRendered in the centre of the ring, fading in once the avatars have spread. | ReactNode | — |
Plus every attribute of <div> except children.
A list (role="list") of images, each with its alt text; the names that float above an avatar on hover are aria-hidden duplicates of the alt. The track and the motion are decoration. Because the orbit runs indefinitely, an orbiting ring has a toggle button ("Pause rotation", aria-pressed) to stop it (WCAG 2.2.2), and the orbit also pauses while an avatar is hovered or the ring is off screen. The intro plays on mount or when first scrolled into view. Springs run through motion inside MotionConfig reducedMotion="user"; under reduced motion the finished ring renders at once and never orbits, and the pause toggle is not shown.
9/10
checks passed
- Tested — passes
- axe assertion — passes
- Keyboard tested — fails
- Storybook examples — passes
- Accessibility documented — passes
- Semantic tokens only — passes
- Motion from tokens — passes
- className merged — passes
- Visible focus — passes
- No fixed widths — passes