GitHub

Progress Bar

Linear progress indicator with determinate and indeterminate modes, sizes, color variants, and an optional label and percentage.

Stable .astro import EsaProgressBar from '@esa/ecology/esa-progress-bar.astro';

Preview

Uploading 68%
<ProgressBar value={68} label="Uploading" showValue={true} />

Variants

60%
60%
60%
60%
<ProgressBar value={60} variant="primary" />
<ProgressBar value={60} variant="success" />
<ProgressBar value={60} variant="warning" />
<ProgressBar value={60} variant="danger" />

Sizes

50%
50%
50%
50%
<ProgressBar value={50} size="xs" />
<ProgressBar value={50} size="sm" />
<ProgressBar value={50} size="md" />
<ProgressBar value={50} size="lg" />

Label & indeterminate

Add a label (and showValue for the percentage) above the track. Indeterminate mode runs a looping translate animation when the completion is unknown.

Processing 40%
Loading…
<ProgressBar value={40} label="Processing" showValue={true} variant="warning" />
<ProgressBar mode="indeterminate" label="Loading…" />

API

PropTypeDefaultDescription
value number 0 Progress, clamped to 0–100. Ignored in indeterminate mode.
mode 'determinate' | 'indeterminate' 'determinate' Determinate fill vs a looping indeterminate animation.
size 'xs' | 'sm' | 'md' | 'lg' 'md' Track height (2 / 4 / 8 / 12px).
variant 'primary' | 'success' | 'warning' | 'danger' 'primary' Fill color intent.
label string '' Optional text shown above the track; also used as the accessible label.
showValue boolean true Shows the percentage next to the label (determinate only).

Accessibility

  • Renders role="progressbar" with aria-valuemin="0" and aria-valuemax="100".
  • aria-valuenow is set in determinate mode and omitted while indeterminate.
  • aria-label falls back to "Progress" when no label is provided.

Theming surface

Every public token this component reads, extracted from its source at build time, split by blast radius: the hooks that belong to this component, then the shared and system tokens it consumes alongside everything else. The Resolves to column walks each token's real lineage — component → semantic → primitive → raw value — so you can see exactly where re-pointing it lands. A spoke re-skins by overriding these in its theme-<slug>.css; component internals are never edited. No hook for what you need? File it with /request-lego.

Type roles it names

This component does not set a size, weight, face or tracking of its own — it names a composite, and the composite carries all five. A composite is a class rather than a token, so none of it appears in the tables below; re-theme text by re-pointing the token family, not by editing the component.

RoleRe-pointReach
.typography-body-2xs
  • --typography-body-2xs-font-family 'DM Sans', sans-serif via --typography-font-family-sans → --font-family-dm-sans
  • --typography-body-2xs-font-size clamp(0.5rem, 0.44rem + 0.3vw, 0.625rem) via --font-size-050
  • --typography-body-2xs-font-weight 350 via --typography-font-weight-regular → --font-weight-350
  • --typography-body-2xs-letter-spacing 0.01em via --letter-spacing-default
  • --typography-body-2xs-line-height 1.6 via --line-height-normal
+6 more components esa-checkbox, esa-checkbox-group, esa-combobox, esa-input-tag, esa-radio-group, esa-textarea
.typography-body-md
  • --typography-body-md-font-family 'DM Sans', sans-serif via --typography-font-family-sans → --font-family-dm-sans
  • --typography-body-md-font-size clamp(0.75rem, 0.66rem + 0.44vw, 0.9375rem) via --font-size-200
  • --typography-body-md-font-weight 350 via --typography-font-weight-regular → --font-weight-350
  • --typography-body-md-letter-spacing 0.01em via --letter-spacing-default
  • --typography-body-md-line-height 1.6 via --line-height-normal
+28 more components esa-app-shell, esa-breadcrumbs, esa-card, esa-checkbox, esa-checkbox-group, esa-collapsible, esa-combobox, esa-command-palette, esa-confirm-dialog, esa-container, esa-danger-zone, esa-dialog, esa-dropdown-menu, esa-empty-state, esa-entity-search, esa-form-field, esa-header-nav, esa-input-tag, esa-nav-dropdown, esa-page-header, esa-popover, esa-radio-group, esa-select, esa-side-dialog, esa-snackbar-item, esa-switch-toggle, esa-tab-layout, esa-textarea
.typography-body-sm
  • --typography-body-sm-font-family 'DM Sans', sans-serif via --typography-font-family-sans → --font-family-dm-sans
  • --typography-body-sm-font-size clamp(0.6875rem, 0.61rem + 0.38vw, 0.875rem) via --font-size-150
  • --typography-body-sm-font-weight 350 via --typography-font-weight-regular → --font-weight-350
  • --typography-body-sm-letter-spacing 0.01em via --letter-spacing-default
  • --typography-body-sm-line-height 1.6 via --line-height-normal
+20 more components esa-alert-box, esa-breadcrumbs, esa-button-toggle, esa-card, esa-checkbox-group, esa-combobox, esa-command-palette, esa-date-picker, esa-empty-state, esa-file-upload, esa-form-field, esa-input-tag, esa-link-column, esa-loading-overlay, esa-radio-group, esa-search-panel, esa-select, esa-stat, esa-text-field, esa-textarea
.typography-body-xs
  • --typography-body-xs-font-family 'DM Sans', sans-serif via --typography-font-family-sans → --font-family-dm-sans
  • --typography-body-xs-font-size clamp(0.625rem, 0.56rem + 0.32vw, 0.75rem) via --font-size-100
  • --typography-body-xs-font-weight 350 via --typography-font-weight-regular → --font-weight-350
  • --typography-body-xs-letter-spacing 0.01em via --letter-spacing-default
  • --typography-body-xs-line-height 1.6 via --line-height-normal
+14 more components esa-breadcrumbs, esa-checkbox, esa-checkbox-group, esa-combobox, esa-command-palette, esa-empty-state, esa-entity-search, esa-field-error, esa-header-nav, esa-input-tag, esa-radio-group, esa-search-panel, esa-select, esa-textarea
.typography-label-2xs
  • --typography-label-2xs-font-family 'DM Sans', sans-serif via --typography-font-family-sans → --font-family-dm-sans
  • --typography-label-2xs-font-size clamp(0.5rem, 0.44rem + 0.3vw, 0.625rem) via --font-size-050
  • --typography-label-2xs-font-weight 500 via --typography-font-weight-medium → --font-weight-500
  • --typography-label-2xs-letter-spacing 0.01em via --letter-spacing-default
  • --typography-label-2xs-line-height 1.6 via --line-height-normal
+11 more components esa-button-toggle, esa-checkbox-group, esa-color-picker, esa-combobox, esa-date-picker, esa-form-field, esa-input-tag, esa-radio-group, esa-range-slider, esa-text-field, esa-textarea
.typography-label-md
  • --typography-label-md-font-family 'DM Sans', sans-serif via --typography-font-family-sans → --font-family-dm-sans
  • --typography-label-md-font-size clamp(0.75rem, 0.66rem + 0.44vw, 0.9375rem) via --font-size-200
  • --typography-label-md-font-weight 500 via --typography-font-weight-medium → --font-weight-500
  • --typography-label-md-letter-spacing 0.01em via --letter-spacing-default
  • --typography-label-md-line-height 1.6 via --line-height-normal
+33 more components esa-app-bar, esa-breadcrumbs, esa-button-group, esa-button-toggle, esa-card, esa-checkbox-group, esa-color-picker, esa-combobox, esa-command-palette, esa-confirm-dialog, esa-danger-zone, esa-date-picker, esa-dialog, esa-empty-state, esa-entity-search, esa-file-upload, esa-filter-container, esa-form-field, esa-header-nav, esa-input-tag, esa-link-column, esa-page-header, esa-pillbox, esa-popover, esa-radio-group, esa-range-slider, esa-select, esa-side-dialog, esa-sidebar-nav, esa-stat, esa-text-field, esa-textarea, esa-tooltip
.typography-label-sm
  • --typography-label-sm-font-family 'DM Sans', sans-serif via --typography-font-family-sans → --font-family-dm-sans
  • --typography-label-sm-font-size clamp(0.6875rem, 0.61rem + 0.38vw, 0.875rem) via --font-size-150
  • --typography-label-sm-font-weight 500 via --typography-font-weight-medium → --font-weight-500
  • --typography-label-sm-letter-spacing 0.01em via --letter-spacing-default
  • --typography-label-sm-line-height 1.6 via --line-height-normal
+3 more components esa-breadcrumbs, esa-search-panel, esa-sidebar-nav
.typography-label-xs
  • --typography-label-xs-font-family 'DM Sans', sans-serif via --typography-font-family-sans → --font-family-dm-sans
  • --typography-label-xs-font-size clamp(0.625rem, 0.56rem + 0.32vw, 0.75rem) via --font-size-100
  • --typography-label-xs-font-weight 500 via --typography-font-weight-medium → --font-weight-500
  • --typography-label-xs-letter-spacing 0.01em via --letter-spacing-default
  • --typography-label-xs-line-height 1.6 via --line-height-normal
+14 more components esa-breadcrumbs, esa-button-toggle, esa-checkbox-group, esa-color-picker, esa-combobox, esa-date-picker, esa-entity-search, esa-form-field, esa-input-tag, esa-radio-group, esa-range-slider, esa-select, esa-text-field, esa-textarea

Wired to this component

No other component reads these — re-point them and esa-progress-bar is the only thing that moves.

Token Tier Resolves to
--progress-bar-height-lg component 12px
--progress-bar-height-md component 8px
--progress-bar-height-sm component 4px
--progress-bar-height-xs component 2px

Shared tokens it reads

Owned by a family or by the semantic layer. Still overridable — but scope the override (esa-foo { --form-border-color: … }) unless you mean to move everything that reads it. Reach says what else that is.

Token Reach Resolves to
--animation-indeterminate semantic every component 1500ms via --duration-1500
--color-background-brand semantic every component #46a758 via --color-grass-9
--color-background-elevation-sunken semantic every component #f0f0f0 via --color-gray-3
--color-background-utility-danger semantic every component #ce2c31 via --color-red-11
--color-background-utility-success semantic every component #218358 via --color-green-11
--color-background-utility-warning semantic every component #ffc53d via --color-yellow-9
--color-content-default semantic every component #202020 via --color-gray-12
--color-content-default-secondary semantic every component #646464 via --color-gray-11
--radius-pill semantic every component 9999px via --radius-full
--spacing-100 primitive every component 0.25rem