Pager Dots

About this component

Pager Dots

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.

Usage

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}`}
/>

Keyboard and gestures

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.

TabEnter or leave the dots. The whole set is one stop, landing on the active page.
Arrow keysMove to the previous or next page, wrapping at the ends. Up and down in a column.
Home / EndJump to the first or the last page.
Hover or keyboard focusPauses autoplay until the pointer or focus leaves.

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
count*number—Number of pages.
valuenumber—The active page, zero-based. Pair with `onValueChange` to control it.
defaultValuenumber0The page shown first when uncontrolled.
onValueChange(value: number) => void—Called with the new page whenever it changes: a click, a key, or autoplay advancing.
durationnumber—Milliseconds each page stays before autoplay moves on. Leave it out for a plain indicator.
playingboolean—Whether autoplay runs. Pair with `duration`; hover, focus, a hidden tab and scrolling away still pause it.
defaultPlayingbooleantrueWhether 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.
loopbooleantrueAutoplay wraps from the last page to the first. Off, it stops on the last page.
visiblenumber7Most 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"
disabledboolean—
aria-labelstring"Slides"Accessible name for the set of dots.
classNamestring—