Skip to main content
cngx-src documentation

CngxProgressBarStepper

ComponentPrimaryOnPushNo encapsulationv0.1.0WCAG AA

projects/ui/stepper/progress-bar-stepper.component.ts

Import#

import { CngxProgressBarStepper } from '@cngx/ui/stepper'

Description#

Progress-Bar stepper variant. Thin Level-4 organism composing CngxStepperPresenter via hostDirectives and rendering the existing <cngx-progress> primitive as the visual bar instead of reinventing <div role="progressbar">. Material consumers inherit Material progress styling through CngxProgress automatically.

completedPercent() is computed from presenter.activeStepIndex() and the count of step nodes in presenter.flatSteps(). Optional [showStepCount] adds a Step N of M caption sourced from CngxStepperI18n.textStepperFormat. Accname and aria-roledescription resolve through the same config + i18n cascades as <cngx-stepper>; a step-less flow renders the CNGX_STEPPER_CONFIG empty-template cascade instead of the bar.

https://cngxjs.github.io/cngx/examples/#/ui/stepper/progress-bar/onboarding-flow

Metadata#

Content Slots#

Host#

Dependencies#

CNGX_STEPPER_HOSTinject()presenter

Relationships

Index#

Inputs#

ariaLabel#string | undefined
input()
default undefined, { alias: 'aria-label' }
ariaLabelledBy#string | undefined
input()
default undefined, { alias: 'aria-labelledby' }
showStepCount#boolean
input()

Render a Step N of M caption below the bar. Off by default.

default false

Instance Properties#

config#unknown
ProtectedReadonly
injectStepperConfig()
i18n#unknown
ProtectedReadonly
injectStepperI18n()
resolvedAriaLabel#unknown
ProtectedReadonly

Shared accname cascade (input → ariaLabels.stepperRegion → i18n.stepperLabel).

createStepperAccname({
  ariaLabel: this.ariaLabel,
  ariaLabelledBy: this.ariaLabelledBy,
  config: this.config,
  i18n: this.i18n,
})
resolvedEmptyTemplate#unknown
ProtectedReadonly

Empty-state cascade mirroring <cngx-stepper>: per-instance *cngxStepperEmpty > CNGX_STEPPER_CONFIG.templates.empty > null. Gates the whole bar so a step-less flow shows the placeholder instead of a full bar captioned Step 0 of 0.

computed<TemplateRef<void> | null>(
  () => this.emptySlot()?.templateRef ?? this.config.templates?.empty ?? null,
)
stateView#unknown
ProtectedReadonly

Shared per-step/aggregate state derivations - the single error source.

createStepperStateView({
  presenter: this.presenter,
  stepsOnly: this.presenter.stepsOnly,
})

HostBindings#

BindingExpression
[attr.aria-roledescription]stepperRoleDescription()
[attr.aria-label]resolvedAriaLabel()
[attr.aria-labelledby]ariaLabelledBy()
[attr.data-state]stateView.hasAnyError() ? "error" : null
[attr.aria-invalid]stateView.hasAnyError() ? "true" : null

Structural skin for <cngx-progress-bar-stepper>.\ Theming flows through the embedded <cngx-progress> primitive's --cngx-progress-* custom properties, so this file only owns the layout (stacked bar + optional caption).

Material consumers using @cngx/themes/material/feedback-theme inherit Material progress palette automatically; no per-variant Material theme bridge is needed.

Material theme coverage across variants

import { ChangeDetectionStrategy, Component, ViewEncapsulation, signal } from '@angular/core';

import { CngxStep } from '@cngx/common/stepper';
import { CngxDotStepper, CngxProgressBarStepper, CngxTextStepper } from '@cngx/ui/stepper';

/**
 * The three indicator-only stepper variants under one Material 3 palette.
 *
 * `CngxProgressBarStepper`, `CngxDotStepper`, and `CngxTextStepper` each
 * honour the Material bridge: the progress bar inherits palette through
 * `CngxProgress`, the dot variant picks up the `--cngx-dot-step-*`
 * overrides, and the text variant follows the surrounding typography. The
 * stylesheet builds a real M3 theme in SCSS - `mat.theme` emits the
 * `--mat-sys-*` tokens and the published `@cngx/themes/material/stepper-theme`
 * bridge mixin maps the `--cngx-step-*` / `--cngx-dot-step-*` tokens onto
 * them, so nothing is hand-copied.
 */
@Component({
  selector: 'app-root',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  imports: [CngxProgressBarStepper, CngxDotStepper, CngxTextStepper, CngxStep],
  styleUrl: './variants-coverage.component.scss',
  template: `
    <div class="coverage">
      <section>
        <h3>CngxProgressBarStepper</h3>
        <cngx-progress-bar-stepper [(activeStepIndex)]="active" [showStepCount]="true" aria-label="Progress bar">
          <div cngxStep label="Customer"></div>
          <div cngxStep label="Payment"></div>
          <div cngxStep label="Review"></div>
        </cngx-progress-bar-stepper>
      </section>
      <section>
        <h3>CngxDotStepper</h3>
        <cngx-dot-stepper [(activeStepIndex)]="active" aria-label="Dots" tabindex="0">
          <div cngxStep label="Customer"></div>
          <div cngxStep label="Payment"></div>
          <div cngxStep label="Review"></div>
        </cngx-dot-stepper>
      </section>
      <section>
        <h3>CngxTextStepper</h3>
        <cngx-text-stepper [(activeStepIndex)]="active" [showCurrentLabel]="true">
          <div cngxStep label="Customer"></div>
          <div cngxStep label="Payment"></div>
          <div cngxStep label="Review"></div>
        </cngx-text-stepper>
      </section>
      <div class="coverage__toolbar">
        <button type="button" (click)="prev()">Previous</button>
        <button type="button" (click)="next()">Next</button>
        <span>Active step: {{ active() }}</span>
      </div>
    </div>
  `,
})
export class VariantsCoverageExample {
  protected readonly active = signal(1);

  protected next(): void {
    this.active.update((i) => Math.min(i + 1, 2));
  }

  protected prev(): void {
    this.active.update((i) => Math.max(i - 1, 0));
  }
}
export { VariantsCoverageExample as AppComponent };