Stories / Reel / Deck
Preview: Default
Story rail + full-screen viewer: segmented progress, auto-advance (5s), tap/click left-right or arrow keys, Space or press-and-hold to pause, Escape closes. Seen stories lose their ring.
Import
import { Stories } from '@marbleui/ui'Props
<Stories>
| Prop | Type | Default | Description |
|---|---|---|---|
| stories *required | Story[] | — | |
| className | string | — | |
| duration | number | 5000 |
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Button · React Aria Dialog · React Aria Modal · React Aria ModalOverlay. Follow the primitive's docs for the full keyboard map.
Usage notes
Row of avatar buttons that opens a full-screen, auto-advancing story viewer, for short visual updates from people or teams. For slides the reader moves through at their own pace, use Carousel.
<Stories
duration={6000}
stories={[
{ id: 'maya', author: 'Maya Chen', slides: [{ src: '/stories/launch.jpg', alt: 'Launch banner on the office wall', caption: 'We shipped v2' }] },
{ id: 'leo', author: 'Leo Martins', slides: [{ src: '/stories/offsite.jpg', alt: 'Team hiking at the offsite' }] },
]}
/>
- Each slide shows for
durationms (default 5000), then the viewer advances to the next slide or story and closes after the last one. - ←/→ change slides, Space or the Pause button pauses and resumes, Escape closes. Tapping the left third goes back and the rest goes forward. Press-and-hold pauses until release, and the release doesn’t change the slide; a story paused with Space stays paused after a tap.
- The dialog is labelled “{author}’s story, n of N” and each image uses its
alt; slide changes aren’t announced. - Seen rings live in component state only: they reset on remount and there’s no callback to persist them.
Example source · show· hide
import { demoImage } from '../lib/demo-images'
import { Stories } from './stories'
const people = ['Maya Chen', 'Charles Webb', 'Ada Park', 'Grace Hopper', 'Leo Martins']
const stories = people.map((p, i) => ({ id: String(i), author: p, slides: Array.from({ length: 2 + (i % 2) }, (_, k) => ({ src: demoImage(i + k, 540, 960), alt: `${p} story ${k + 1}`, caption: k === 0 ? `${p.split(' ')[0]} shipped something new` : undefined })) }))
export const styles = { Default: () => <Stories stories={stories} className="w-96" /> }Source: packages/ui/src/stories/stories.tsx
Catalog
- Category
- media
- Priority
- Extra
- Primitive
- custom