Slide dots for carousels and stories: the active dot stretches into a pill on a spring, and with a duration the pill fills as its page plays, then autoplay moves on. Autoplay pauses under the pointer, on keyboard focus, on a hidden tab and offscreen, and toggling it never restarts the fill. Long sets slide a window along the dots and shrink the ones at its edges, the way story apps do. It is a tablist: one tab stop, arrow keys, Home and End. Row or column, three sizes, and a bare tone that takes the text color for use over a photo.
The import and the props worth knowing about, in one place.
import { PagerDots } from "@/components/beste/component/pager-dots";
// A plain indicator driven by your carousel
<PagerDots count={5} value={slide} onValueChange={setSlide} />
// Stories: each page plays for 5 seconds, then moves on
<PagerDots
count={12}
duration={5000}
value={slide}
onValueChange={setSlide}
onCycleEnd={(index) => console.log("finished", index)}
/>
// Over a photo: bare, white, with its own pause switch
<PagerDots
count={8}
duration={4000}
playing={playing}
tone="ghost"
className="text-white"
getControls={(index) => `slide-${index}`}
/>Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.
| Tab | Enter or leave the dots. The whole set is one stop, landing on the active page. |
|---|---|
| Arrow keys | Move to the previous or next page, wrapping at the ends. Up and down in a column. |
| Home / End | Jump to the first or the last page. |
| Hover or keyboard focus | Pauses autoplay until the pointer or focus leaves. |
Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
count* | number | — | Number of pages. |
value | number | — | The active page, zero-based. Pair with `onValueChange` to control it. |
defaultValue | number | 0 | The page shown first when uncontrolled. |
onValueChange | (value: number) => void | — | Called with the new page whenever it changes: a click, a key, or autoplay advancing. |
duration | number | — | Milliseconds each page stays before autoplay moves on. Leave it out for a plain indicator. |
playing | boolean | — | Whether autoplay runs. Pair with `duration`; hover, focus, a hidden tab and scrolling away still pause it. |
defaultPlaying | boolean | true | Whether autoplay starts running when uncontrolled. Reduced motion starts it paused. |
onCycleEnd | (value: number) => void | — | Called when a page's timer runs out, just before autoplay moves on. |
loop | boolean | true | Autoplay wraps from the last page to the first. Off, it stops on the last page. |
visible | number | 7 | Most dots on screen at once. Longer sets slide a window along and shrink the dots at its edges. |
orientation | "horizontal" | "vertical" | "horizontal" | |
getLabel | (index: number, count: number) => string | — | Accessible name of each dot. Defaults to "Slide 3 of 12". |
getControls | (index: number) => string | undefined | — | Id of the panel each dot shows, for `aria-controls`. |
tone | "muted" | "outline" | "ghost" | "muted" | Surface behind the dots: filled, hairline outline, or bare for use over a photo. |
size | "sm" | "default" | "lg" | "default" | |
disabled | boolean | — | |
aria-label | string | "Slides" | Accessible name for the set of dots. |
className | string | — |