Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Page Indicator

Dot-based position indicator for page-level navigation or onboarding flows. Active dot fills with accent-primary and scales up.

Components Page Indicator
navigation interactive
<arc-page-indicator>

Overview

PageIndicator renders a horizontal row of dots that communicate the user's position within a paged sequence — carousels, onboarding flows, slideshow presentations, or any content split into discrete steps. The active dot fills with accent-primary and scales up slightly, providing an immediate visual cue for the current position without requiring labels or numbers. The component supports both passive and interactive modes. In passive mode (`clickable` is false), the dots serve as read-only indicators driven by an external controller like a Carousel or swipe gesture handler. In interactive mode (`clickable` is true), each dot becomes a tap target that dispatches `arc-change` with the selected index, letting users jump directly to any page. PageIndicator is intentionally minimal — it handles position communication and optional direct navigation while leaving content transitions to the parent component. Pair it with Carousel for image galleries, StepperNav for wizard flows, or your own custom swipe container. The `count` prop sets the total number of dots and `value` controls which one is active, making it straightforward to synchronize with any paging state.

Guidelines

When to use

  • Use PageIndicator alongside a Carousel or swipe container for visual context
  • Enable clickable mode when users should be able to jump to any page directly
  • Keep the count reasonable — five to seven dots maximum for quick scanning
  • Position the indicator below or overlaid on the paged content
  • Synchronise the value prop with the parent component's active page state

When not to use

  • Do not use PageIndicator for progress — use Progress or Stepper instead
  • Do not display more than ten dots — the pattern breaks down at high counts
  • Do not use PageIndicator without a corresponding paged content area
  • Do not rely on PageIndicator as the only navigation mechanism — pair with swipe or buttons
  • Do not place multiple PageIndicators for the same content sequence

Features

  • Horizontal dot row for position indication
  • Active dot fills with accent-primary and scales up
  • Passive (read-only) and interactive (clickable) modes
  • `arc-change` event when a dot is clicked in interactive mode
  • Controlled count and value props for external synchronisation
  • Compact footprint suitable for overlay positioning
  • Keyboard accessible in clickable mode with arrow keys
  • Token-driven theming via CSS custom properties

Preview

Usage

This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.

<script type="module" src="@arclux/arc-ui"></script>

<arc-page-indicator count="5" value="2" clickable id="dots"></arc-page-indicator>

<script>
  document.querySelector('#dots').addEventListener('arc-change', (e) => {
    console.log('page:', e.detail.value);
  });
</script>
import { useState } from 'react';
import { PageIndicator } from '@arclux/arc-ui-react';

export function Gallery() {
  const [page, setPage] = useState(0);

  return (
    <PageIndicator
      count={5}
      value={page}
      clickable
      onArcChange={(e) => setPage(e.detail.value)}
    />
  );
}
<script setup>
import { ref } from 'vue';
import { PageIndicator } from '@arclux/arc-ui-vue';

const page = ref(0);

function onChange(e) {
  page.value = e.detail.value;
}
</script>

<template>
  <PageIndicator :count="5" :value="page" clickable @arc-change="onChange" />
</template>
<script>
  import { PageIndicator } from '@arclux/arc-ui-svelte';

  let page = 0;
</script>

<PageIndicator
  count={5}
  value={page}
  clickable
  on:arc-change={(e) => (page = e.detail.value)}
/>
import { Component } from '@angular/core';
import { PageIndicator } from '@arclux/arc-ui-angular';

@Component({
  imports: [PageIndicator],
  template: `
    <arc-page-indicator
      [count]="5"
      [value]="page"
      clickable
      (arc-change)="onChange($event)"
    />
  `,
})
export class GalleryComponent {
  page = 0;

  onChange(e: CustomEvent) {
    this.page = e.detail.value;
  }
}
import { createSignal } from 'solid-js';
import { PageIndicator } from '@arclux/arc-ui-solid';

export function Gallery() {
  const [page, setPage] = createSignal(0);

  return (
    <PageIndicator
      count={5}
      value={page()}
      clickable
      onArcChange={(e) => setPage(e.detail.value)}
    />
  );
}
import { useState } from 'preact/hooks';
import { PageIndicator } from '@arclux/arc-ui-preact';

export function Gallery() {
  const [page, setPage] = useState(0);

  return (
    <PageIndicator
      count={5}
      value={page}
      clickable
      onArcChange={(e) => setPage(e.detail.value)}
    />
  );
}

API

count number 0
Total number of dots to display.
value number 0
Zero-based index of the active dot.
clickable boolean false
When true, dots become interactive tap targets that dispatch arc-change on click.

Events

arc-change detail: { value: number }
Fired when a dot is clicked (clickable mode only) with detail: { value }.

See Also