CngxDotStepper
projects/ui/stepper/dot-stepper.component.ts
Import#
import { CngxDotStepper } from '@cngx/ui/stepper'
Description#
Dot stepper variant. Mobile-first sequential-flow indicator. Renders
one labelled <span role="img"> per step (a name-permitting role, so
each dot announces "Step N of M: label") inside a
<div role="group" aria-roledescription="Step indicator">. The active
dot carries aria-current="step" per the W3C APG step-indicator
pattern (NOT role="tablist" / role="tab" - those are reserved
for parallel content panels, not sequential flow).
Tap-to-select is intentionally NOT wired on individual dots: under
the APG pattern each dot is a label, not a button, and attaching
(click) to role="img" conflates two ARIA contracts. Navigation
is offered uniformly via three modalities owned by the host element:
arrow / Home / End keys, the composed CngxStepperSwipeNav dot-row
gesture, and the two-way [(activeStepIndex)] binding for
external buttons. Consumers wanting per-dot tap-to-jump compose the
parent <cngx-stepper> (whose mobile-collapse dots branch
renders each dot as a <button>).
Theming flows through new --cngx-dot-step-* custom properties whose
defaults cascade through var(--cngx-step-active-fill, ...), so the
Phase A active-fill chain reaches the dot variant without duplication.
Metadata#
Content Slots#
Host#
Dependencies#
CNGX_STEPPER_HOSTinject()presenterRelationships
Index#
Inputs
Derived State
HostBindings
HostListeners
Inputs#
Instance Properties#
unknownShared accname cascade (input → ariaLabels.stepperRegion → i18n.stepperLabel).
createStepperAccname({
ariaLabel: this.ariaLabel,
ariaLabelledBy: this.ariaLabelledBy,
config: this.config,
i18n: this.i18n,
})unknownResolved dot-body template cascade: per-instance *cngxDotStepperDot
directive > CNGX_STEPPER_CONFIG.templates.dotStepperDot > null
(built-in empty body). Pillar 1 - resolution is a computed, not
manual sync.
computed<TemplateRef<CngxDotStepperDotContext> | null>(
() => this.dotSlot()?.templateRef ?? this.config.templates?.dotStepperDot ?? null,
)unknownEmpty-state cascade mirroring <cngx-stepper>: per-instance
*cngxStepperEmpty > CNGX_STEPPER_CONFIG.templates.empty > null.
Gates the dot row so a step-less flow shows the placeholder
instead of an empty group.
computed<TemplateRef<void> | null>(
() => this.emptySlot()?.templateRef ?? this.config.templates?.empty ?? null,
)unknownShared per-step/aggregate state derivations - the single error source.
createStepperStateView({
presenter: this.presenter,
stepsOnly: this.stepNodes,
})Methods#
CngxDotStepperDotContextdotContextFor(node: CngxStepNode, index: number)Build the slot context for *cngxDotStepperDot.
dotState(node: CngxStepNode)Resolved data-state for the dot: 'error' whenever the unified error
view fires (covers commit rejection and the error aggregator, not just a
literal state === 'error'), otherwise the raw step status.
HostBindings#
| Binding | Expression |
|---|---|
[attr.tabindex] | stepNodes().length === 0 ? null : '0' |
[attr.aria-roledescription] | i18n.stepIndicatorRoleDescription |
[attr.aria-label] | resolvedAriaLabel() |
[attr.aria-labelledby] | ariaLabelledBy() |
[attr.aria-invalid] | stateView.hasAnyError() ? "true" : null |
HostListeners#
| Event | Handler |
|---|---|
(keydown) | keydown() |
Structural and thematic skin for <cngx-dot-stepper>.
Theme tokens cascade through var(--cngx-step-active-fill, ...) so the active-fill chain flows in without duplication.
Active dot uses --cngx-dot-step-active-fill; completed dots use:
--cngx-dot-step-completed-fill; upcoming dots use--cngx-dot-step-upcoming-bg. Material consumers see--mat-sys-primaryvia the stepper-theme extension.
Index#
*0.625rem*0.5rem*oklch(0.66 0.19 50)*oklch(0.5 0.15 145)*color-mix(in srgb, currentColor 18%, transparent)