PaginationIndicator reports position within a set of pages, either as a compact “3 of 5” chip or as a row of dots. It owns nothing but the display: it holds no state, performs no navigation, and never takes focus. You give it a page count and the active index, and it renders the matching treatment.showPagination and paginationMode instead of adding a second indicator.import { PaginationIndicator, PaginationMode } from '@wearables-ui-toolkit/mrbd';
type Props = {
pages: ReadonlyArray<string>;
activeIndex: number;
};
export function ArticleFooter({ pages, activeIndex }: Props) {
return (
<div className="article-footer">
<PaginationIndicator
mode={PaginationMode.TEXT}
pageCount={pages.length}
currentPage={activeIndex}
/>
</div>
);
}
import { useCallback, useState } from 'react';
import {
PaginationIndicator,
PaginationMode,
Pager,
PagerPage,
} from '@wearables-ui-toolkit/mrbd';
const PHOTO_PAGES = ['first', 'second', 'third', 'fourth'];
export function PhotoPager() {
const [activeIndex, setActiveIndex] = useState(0);
const handlePageChange = useCallback((newIndex: number) => {
setActiveIndex(newIndex);
}, []);
return (
<div className="photo-pager">
<Pager currentPageIndex={activeIndex} onPageChange={handlePageChange}>
{PHOTO_PAGES.map(id => (
<PagerPage key={id}>
<PhotoPage id={id} />
</PagerPage>
))}
</Pager>
<PaginationIndicator
mode={PaginationMode.DOTS}
pageCount={PHOTO_PAGES.length}
currentPage={activeIndex}
/>
</div>
);
}
.photo-pager {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--uit-spacing-small);
height: 100%;
}
PaginationIndicatorProps, which extends HTMLAttributes<HTMLDivElement>.| Prop | Type | Default | Description |
|---|---|---|---|
mode | PaginationMode | PaginationMode.TEXT | Whether to render the numeric chip or the row of dots. |
pageCount | number | 0 | Total number of pages. |
currentPage | number | 0 | Zero-based index of the active page. |
className | string | '' | Added to the root element. |
style | CSSProperties | {} | Applied to the root element. In dot mode it is merged after the container’s own width and height, so it can override them. |
aria-*, data-*, role, and the rest — lands there too.PaginationMode| Member | Description |
|---|---|
TEXT | A compact chip reading “current of total”, such as 3 of 5. |
DOTS | A row of dots with the active page emphasized and a sliding window for larger sets. |
currentPage of 0 reads as 1 of 5. The text is held to a single line so the chip does not change height as the numbers change, and the chip is not clickable.pageCount of 0 or less renders nothing at all, so an empty set collapses cleanly. In dot mode the container still renders, keeping its reserved footprint, but contains no dots.currentPage moves outside it, so paging back and forth within the visible range leaves the dots where they are instead of re-centering on every change. The window is also clamped so it never runs past either end of the set.usePrefersReducedMotion where the paged surface lives and fall back to PaginationMode.TEXT, which has no dot motion.--uit-color-control-active and the remaining dots use --uit-color-background-track, so the current page stays the brightest mark on the additive-light display.currentPage for you. An index outside [0, pageCount - 1] produces a row with no active dot in dot mode and an out-of-range number in text mode, so validate the index where your paging state lives.role plus an aria-label, for instance — and it will be applied to the root element. Keep that text in sync with the page count and index you pass.DOTS for a small, fixed set and TEXT when the count is large or the exact position matters.pageCount and currentPage synchronized with the content so the visible position stays accurate.currentPage — the component adds the one for you in text mode.