Skip to content
Liquidify
HomeDocsComponentsExamplesPlayground
⌘K
(opens in new tab)
Liquidify

Accessible React controls with a CSS and SVG material engine.

Product

ComponentsExamplesPlaygroundPackages

Learn

DocumentationGetting startedConceptsAI resources

Project

CommunityShowcaseVersionsGitHub

Independent open-source software. Not affiliated with or endorsed by Apple Inc.

LicenseBrand

Component catalog

Browse the public controls by interaction purpose. Every result links to generated API facts, accessibility behavior, source, and exhaustive stories.

PageControl

is the bare dot indicator for a paged collection — the row of neutral dots that shows how many pages exist, which one is current, and lets the user jump between them.

import { PageControl } from "@liquidify/react/page-control"

Overview

Basic Page Control

A focused starting point showing Page Control with its essential configuration.

API

PropTypeDefaultDescription
allowsContinuousInteractionboolean | undefinedtrueEnables press-drag scrubbing across the dot row (`UIPageControl`'s continuous interaction): the pressed pointer commits the dot it settles over, dot-to-dot, until release. When `false`, only a discrete dot tap (and the keyboard) can change the page, and `backgroundDisplay="interacting"` never reveals its plate — there is no scrub to reveal it for.
aria-labelstring | undefined—Required accessible name (the tablist renders no visible label).
aria-labelledbystring | undefined—Required accessible name via reference (alternative to `aria-label`).
backgroundDisplay"automatic" | "always" | "never" | "interacting" | undefinedautomaticWhether/when the frosted backing plate renders. `"always"` keeps it mounted; `"interacting"` mounts it only while the user is scrubbing (a held pointer that has travelled — a plain dot tap never reveals it); `"automatic"` / `"never"` never mount it. `"interacting"` therefore has no effect under `allowsContinuousInteraction={false}`, where no scrub exists. Maps SwiftUI `PageIndexViewStyle.BackgroundDisplayMode.interactive` (the plate reveals only during a live dot interaction) to the React value `"interacting"` — a deliberately different spelling from the removed `GlassMaterial` tier of the same era (D6, ADR-0010), which `material_scale.py` bans from `packages/*` source on an unrelated axis (the glass-surface material, not this presentational display enum). See spec.md `## Variants` for the full SwiftUI → React naming rationale.
classNamestring | undefined—Optional additional CSS class merged into the glass surface class. The supported per-instance customisation seam: override any `--lq-*` custom property from this class's CSS — the token cascade the engine reads (ADR-0004). No raw inline style is involved, so this stays ADR-0003 clean.
count
required
number—Total number of pages (`UIPageControl.numberOfPages`). Required.
defaultValuenumber | undefined0Uncontrolled seed for the current page index.
disabledboolean | undefinedfalseDisables the whole control.
hidesForSinglePageboolean | undefinedtrueHide the row when `count === 1` under `indexDisplay="automatic"`.
idstring | undefined—Base id for the deterministic per-dot ids (`${id}-tab-${i}`).
indexDisplay"automatic" | "always" | "never" | undefinedautomaticWhether the dot row renders.
onChange((index: number) => void) | undefined—Fires with the next 0-based index whenever the page changes.
refRef<HTMLDivElement> | undefined—Forwarded ref to the rendered element — the component's native root (or the merged child element on a component that opts into {@link SlottableProps}). Generic over `E` (charter `docs/api-conventions.md` §4 rule 1, default `HTMLElement`) so a component with a polymorphic root (Link's navigation / action mode union, Text's `as`) can instantiate the concrete element per variant instead of leaving every consumer with a widened `Ref<HTMLElement>`. A component that does not narrow simply inherits the `HTMLElement` default — source-compatible with every pre-existing non-generic `extends ControlProps`.
sizePageControlSize | undefinedregularSize of the dot row — the `regular · large` subset of the canonical {@link SizedControlProps.sizesize scale} (ADR-0018). Resolved to geometry via `data-size` attribute selectors in `styles.css`; the root stamps `data-size` **unconditionally** (the Button/Toggle pattern), so both values are always addressable in CSS and tests.
valuenumber | undefined—Controlled current page index (0-based).

Guidelines

Do
  • Use Page Control when its semantics match the content or action.
  • Keep labels concise, specific, and consistent with the surrounding interface.
  • Test the component with keyboard navigation, zoom, and both color schemes.
Don't
  • Do not use Page Control as a visual substitute for a different semantic element.
  • Do not rely on color or an icon alone to communicate essential meaning.
  • Do not override the component tokens with fixed values unless the product theme requires it.

Accessibility

PageControl supports the documented keyboard interactions below.

Keyboard
  • Press Tab to move focus to the control.
  • Use the control's documented activation keys without trapping focus.
  • Provide an accessible name whenever the visible label is absent.

Tokens

NameValue
--lq-color-fill-tertiaryComponent-defined value
--lq-color-label-primaryComponent-defined value
--lq-color-label-tertiaryComponent-defined value
--lq-duration-0ms80ms120ms150ms250ms350ms500ms
--lq-ease-Component-defined value
--lq-glass-440.71.15var(--lq-segmented-control-indicator-blur)calc(var(--lq-glass-material-blur) * 8)var(--lq-shadow-presentational)
--lq-hit-target-touch2.75rem
--lq-page-control-dotvar(--lq-space-8)var(--lq-space-12)
--lq-page-control-dot-activevar(--lq-space-12)var(--lq-space-16)
--lq-page-control-dot-gapvar(--lq-space-8)var(--lq-space-12)
--lq-page-control-padvar(--lq-space-4)var(--lq-space-8)
--lq-page-control-plate-padComponent-defined value
--lq-radius-pill9999rem
--lq-space-0.0625rem0.125rem0.25rem0.5rem0.75rem1rem1.25rem1.5rem2rem2.5rem3rem3.5rem

Key features

  • Liquid material

    Uses Liquidify surfaces and theme-aware design tokens.

  • Typed API

    Provides a typed React API with generated prop documentation.

  • Accessible by default

    Preserves semantic structure, focus visibility, and assistive-technology state.

Resources

  • Source
  • Markdown
  • JSON
  • Storybook
Components