Skip to main content
In progress

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.

Do
  • 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
  • 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.

TypeExampleDescription
boolean
Highlights the current page indicator.
Code example
<PageIndicatorContainer>
<PageIndicator isActive aria-label="Page 1, current" />
<PageIndicator aria-label="Page 2" />
</PageIndicatorContainer>

Behavior

  • PageIndicatorContainer renders a <div> with role="group" to semantically group the buttons.
  • Each PageIndicator renders a <button> element; all native button attributes (onClick, disabled, etc.) are forwarded.
  • When isActive is true, the button receives aria-current="page" and a distinct active visual style.
  • Only one indicator should have isActive at a time; state management is the responsibility of the consuming component.

Accessibility

  • Each PageIndicator must have an aria-label describing its page position and, when active, its current state (e.g. "Page 1, current").
    (WCAG 1.3.1 — Info and Relationships)
  • PageIndicatorContainer uses role="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

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.

PropTypeRequiredDefaultDescription
childrenReact.ReactNodeNoPageIndicator buttons to display.
aria-labelstringNoAccessible label for the group (recommended).

PageIndicator Props

The PageIndicator component accepts all standard HTML <button> attributes in addition to the following prop:

PropTypeRequiredDefaultDescription
isActivebooleanNofalseMarks this indicator as the current page. Adds aria-current="page".
aria-labelstringYes*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;
  • NavigationTabs – For primary top-level navigation between sections.
  • SectionTabs – For switching between content sections within a page.