PageIndicator
A compound component used to display a row of dot-style navigation buttons that communicate the current position within a set of pages or slides.
Code example
import { useState } from 'react';
import { PageIndicator, PageIndicatorContainer } from '@yleisradio/yds-components-react';
export const PageIndicatorDemo = ({ count = 3 }: { count?: number }) => {
const [current, setCurrent] = useState(0);
return (
<PageIndicatorContainer aria-label="Slide navigation">
{Array.from({ length: count }, (_, i) => (
<PageIndicator
key={i}
isActive={current === i}
onClick={() => setCurrent(i)}
aria-label={`Slide ${i + 1}${current === i ? ', current' : ''}`}
/>
))}
</PageIndicatorContainer>
);
};
Why to Use
PageIndicator provides a consistent, accessible way to show a user's position within a paginated or slide-based sequence. The compound structure (PageIndicatorContainer + PageIndicator) separates grouping concerns from individual indicator state, keeping usage explicit and predictable.
When to Use
Use PageIndicator when users need to know their position within a finite, ordered set of pages or slides, and may need to navigate between them.
- Use in carousels and image galleries to show the current slide.
- Use in multi-step flows or onboarding sequences.
- Use when the page count is small (up to ~8 items).
- Don't use for primary site navigation — use NavigationTabs instead.
- Don't use for section-level tab switching — use SectionTabs instead.
- Don't use when the number of pages exceeds ~8, as the dots become difficult to distinguish.
Key PageIndicator Props
isActive
Marks the indicator as the currently active page. Sets the active visual state and adds aria-current="page" to the button. Defaults to false.
| Type | Example | Description |
|---|---|---|
boolean | Highlights the current page indicator. |
Code example
<PageIndicatorContainer>
<PageIndicator isActive aria-label="Page 1, current" />
<PageIndicator aria-label="Page 2" />
</PageIndicatorContainer>
Behavior
PageIndicatorContainerrenders a<div>withrole="group"to semantically group the buttons.- Each
PageIndicatorrenders a<button>element; all native button attributes (onClick,disabled, etc.) are forwarded. - When
isActiveistrue, the button receivesaria-current="page"and a distinct active visual style. - Only one indicator should have
isActiveat a time; state management is the responsibility of the consuming component.
Accessibility
- Each
PageIndicatormust have anaria-labeldescribing its page position and, when active, its current state (e.g."Page 1, current").
(WCAG 1.3.1 — Info and Relationships) PageIndicatorContainerusesrole="group"to associate the indicators semantically.
(WCAG 4.1.2 — Name, Role, Value)- The active indicator uses
aria-current="page"to communicate the current position to assistive technologies. - Ensure indicators are reachable and operable via keyboard (Tab, Enter/Space).
Implementation examples
Controlled carousel indicator
Code example
import { useState } from 'react';
import { PageIndicator, PageIndicatorContainer } from '@yleisradio/yds-components-react';
export const PageIndicatorDemo = ({ count = 3 }: { count?: number }) => {
const [current, setCurrent] = useState(0);
return (
<PageIndicatorContainer aria-label="Slide navigation">
{Array.from({ length: count }, (_, i) => (
<PageIndicator
key={i}
isActive={current === i}
onClick={() => setCurrent(i)}
aria-label={`Slide ${i + 1}${current === i ? ', current' : ''}`}
/>
))}
</PageIndicatorContainer>
);
};
API Reference
PageIndicatorContainer Props
The PageIndicatorContainer component accepts all standard HTML <div> attributes. It renders a role="group" wrapper — provide an aria-label to describe the group when needed.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | React.ReactNode | No | — | PageIndicator buttons to display. |
aria-label | string | No | — | Accessible label for the group (recommended). |
PageIndicator Props
The PageIndicator component accepts all standard HTML <button> attributes in addition to the following prop:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
isActive | boolean | No | false | Marks this indicator as the current page. Adds aria-current="page". |
aria-label | string | Yes* | — | Describes the page position. Required for accessibility. |
* Technically optional at the type level, but required for accessible usage.
Type Definitions
export type PageIndicatorContainerProps = HTMLAttributes<HTMLDivElement>;
export interface PageIndicatorDSProps {
isActive?: boolean;
}
export type PageIndicatorProps = HTMLAttributes<HTMLButtonElement> & PageIndicatorDSProps;
Related Components
- NavigationTabs – For primary top-level navigation between sections.
- SectionTabs – For switching between content sections within a page.