Theme
Version
GitHub PyPI Discord
On this page

Progress

Use CProgress for completion of an ongoing task. It renders the native progress element, so determinate values, unknown duration, direction, and assistive-technology semantics stay browser-owned.

Progress at a glance

Progress at a glance
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class ProgressAtAGlance(Component):
    template = """
      <section class="progress-glance">
        <c-CGroup justify="between">
          <div><p>Research dive 08</p><h2>Mapping the reef shelf</h2></div>
          <strong>68%</strong>
        </c-CGroup>
        <c-CProgress label="Mapping the reef shelf" c-value="68" shape="pill" />
        <p>Sonar pass 17 of 25 ยท 42 minutes remaining</p>
      </section>
    """
    css = """
      :where(.progress-glance) {
        display: grid;
        gap: 0.75rem;
        max-inline-size: 38rem;
        padding: 1.25rem;
        border: 1px solid light-dark(#9fc5d4, #406572);
        border-radius: 0.85rem;
        background: light-dark(#f0fbff, #11252c);
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }

      :where(.progress-glance h2, .progress-glance p) {
        margin: 0;
      }

      :where(.progress-glance > p, .progress-glance [data-citry-ui-part="group"] p) {
        color: light-dark(#416a78, #a7cbd7);
        font-size: 0.78rem;
      }
    """


preview = ProgressAtAGlance()

preview  # noqa: B018

Show known completion

Pass a finite value from zero through max. The default maximum is 100.

Compare determinate values
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class DeterminateProgress(Component):
    template = """
      <c-CStack class_="progress-values">
        <div>
          <c-CGroup justify="between"><span>Preparing vessel</span><strong>15%</strong></c-CGroup>
          <c-CProgress label="Preparing vessel" c-value="15" />
        </div>
        <div>
          <c-CGroup justify="between"><span>Descending</span><strong>50%</strong></c-CGroup>
          <c-CProgress label="Descending" c-value="50" />
        </div>
        <div>
          <c-CGroup justify="between"><span>Survey complete</span><strong>100%</strong></c-CGroup>
          <c-CProgress label="Survey complete" c-value="100" intent="success" />
        </div>
      </c-CStack>
    """
    css = """
      :where(.progress-values) {
        max-inline-size: 34rem;
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }

      :where(.progress-values > div) {
        display: grid;
        gap: 0.4rem;
      }
    """


preview = DeterminateProgress()

preview  # noqa: B018
<c-CProgress label="Mapping the reef shelf" c-value="68" />

Show unknown duration

Omit value, or pass None, while work is active but its remaining duration is unknown. This removes the native value attribute.

Show indeterminate work
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class IndeterminateProgress(Component):
    template = """
      <section class="progress-unknown">
        <h2>Contacting the deep-sea relay</h2>
        <c-CProgress label="Contacting the deep-sea relay" shape="pill" />
        <p>The operation is active, but its remaining duration is unknown.</p>
      </section>
    """
    css = """
      :where(.progress-unknown) {
        display: grid;
        gap: 0.75rem;
        max-inline-size: 32rem;
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }

      :where(.progress-unknown h2, .progress-unknown p) {
        margin: 0;
      }

      :where(.progress-unknown p) {
        color: GrayText;
        font-size: 0.8rem;
      }
    """


preview = IndeterminateProgress()

preview  # noqa: B018

Reduced-motion preferences replace continuous motion with a static patterned track.

Use custom units

Set a positive max and supply value_text when the value is better explained as items, bytes, stages, or another unit.

Use a custom range and value text
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class CustomRangeProgress(Component):
    template = """
      <section class="progress-range">
        <c-CGroup justify="between"><h2>Sample crates cataloged</h2><strong>6 / 10</strong></c-CGroup>
        <c-CProgress
          label="Sample crates cataloged"
          c-value="6"
          c-max="10"
          value_text="6 of 10 sample crates"
          intent="success"
        />
      </section>
    """
    css = """
      :where(.progress-range) {
        display: grid;
        gap: 0.75rem;
        max-inline-size: 32rem;
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }

      :where(.progress-range h2) {
        margin: 0;
        font-size: 0.95rem;
      }
    """


preview = CustomRangeProgress()

preview  # noqa: B018

Choose a palette

Intent changes the range color. Keep the task label and surrounding text clear without color.

Compare Progress intents
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class ProgressIntents(Component):
    template = """
      <c-CStack class_="progress-intents" gap="sm">
        <c-for each="item in items">
          <div><span>{{ item[1] }}</span><c-CProgress c-label="item[1]" c-value="62" c-intent="item[0]" /></div>
        </c-for>
      </c-CStack>
    """

    class Kwargs:
        pass

    class Slots:
        pass

    def template_data(
        self,
        kwargs: Kwargs,  # noqa: ARG002
        slots: Slots,  # noqa: ARG002
    ) -> dict[str, object]:
        return {
            "items": (
                ("neutral", "Equipment check"),
                ("primary", "Survey pass"),
                ("success", "Samples secured"),
                ("warn", "Current increasing"),
                ("danger", "Pressure limit"),
            )
        }

    css = """
      :where(.progress-intents) {
        max-inline-size: 32rem;
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }

      :where(.progress-intents > div) {
        display: grid;
        gap: 0.3rem;
      }

      :where(.progress-intents span) {
        font-size: 0.8rem;
      }
    """


preview = ProgressIntents()

preview  # noqa: B018

Choose thickness and shape

Sizes set track thickness. Shape selects square, rounded, or pill geometry.

Compare Progress sizes and shapes
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class ProgressSizesAndShapes(Component):
    template = """
      <c-CStack class_="progress-sizes">
        <c-CProgress label="Small square progress" c-value="35" size="sm" shape="square" />
        <c-CProgress label="Medium rounded progress" c-value="55" />
        <c-CProgress label="Large pill progress" c-value="75" size="lg" shape="pill" />
      </c-CStack>
    """
    css = """
      :where(.progress-sizes) {
        max-inline-size: 34rem;
        color: CanvasText;
      }
    """


preview = ProgressSizesAndShapes()

preview  # noqa: B018

Control progress in the browser

Client inputs are passed through $c-props="{...}". A number controls determinate completion; null switches to indeterminate; omission returns to the server fallback.

Control Progress in the browser
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class ControlledProgress(Component):
    template = """
      <section class="progress-controlled" x-data="{value: 28}">
        <c-CGroup justify="between"><h2>Transect upload</h2><output x-text="`${value}%`"></output></c-CGroup>
        <c-CProgress label="Transect upload" $c-props="{value}" shape="pill" />
        <label>Completion <input type="range" min="0" max="100" x-model.number="value" /></label>
      </section>
    """
    css = """
      :where(.progress-controlled) {
        display: grid;
        gap: 0.85rem;
        max-inline-size: 34rem;
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }

      :where(.progress-controlled h2) {
        margin: 0;
        font-size: 1rem;
      }

      :where(.progress-controlled label) {
        display: grid;
        gap: 0.35rem;
        font-size: 0.8rem;
      }

      :where(.progress-controlled input) {
        inline-size: 100%;
      }
    """


preview = ControlledProgress()

preview  # noqa: B018

Describe a busy region

When Progress describes another region, the application owns aria-busy on that region and connects it to Progress. Clear busy state when the work finishes.

Connect Progress to a busy region
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class BusyRegionProgress(Component):
    template = """
      <section class="progress-busy" aria-busy="true" aria-describedby="reef-progress">
        <h2>Reconstructing the reef map</h2>
        <p>Existing survey results remain visible while the new contour layer loads.</p>
        <c-CProgress
          label="Reconstructing the reef map"
          c-value="74"
          c-attrs="{'id': 'reef-progress'}"
        />
      </section>
    """
    css = """
      :where(.progress-busy) {
        display: grid;
        gap: 0.75rem;
        max-inline-size: 34rem;
        padding: 1rem;
        border: 1px solid light-dark(#b5d0d9, #436571);
        border-radius: 0.75rem;
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }

      :where(.progress-busy h2, .progress-busy p) {
        margin: 0;
      }
    """


preview = BusyRegionProgress()

preview  # noqa: B018

Customize Progress

Override public track, range, height, and radius variables on an ancestor or one native Progress root.

Customize Progress with public CSS
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class ProgressCustomization(Component):
    template = """
      <c-CStack class_="progress-themes">
        <div class="progress-themes__coral"><c-CProgress label="Coral lab" c-value="58" shape="pill" /></div>
        <div class="progress-themes__abyss"><c-CProgress label="Abyss lab" c-value="58" shape="pill" /></div>
      </c-CStack>
    """
    css = """
      :where(.progress-themes > div) {
        padding: 1.25rem;
        border-radius: 0.75rem;
      }

      :where(.progress-themes__coral) {
        --cui-progress-track-color: #f8ddd6;
        --cui-progress-range-color: #b9382f;
        --cui-progress-height: 0.75rem;
        background: #fff6f2;
      }

      :where(.progress-themes__abyss) {
        color-scheme: dark;
        --cui-progress-track-color: #1f3b48;
        --cui-progress-range-color: #63d4e8;
        --cui-progress-height: 0.75rem;
        background: #0b1b24;
      }
    """


preview = ProgressCustomization()

preview  # noqa: B018

Choose the right indicator

Progress represents task completion. Use CSpinner for a compact unknown wait without a linear track, and native meter for a scalar measurement that is not task completion.

Progress has no focus, keyboard behavior, form value, live announcement, or automatic busy-region mutation.

API reference

Inputs

CProgress server inputs

Server inputs are passed in a template through <c-CProgress ... /> or in Python through CProgress(...).

InputTypeDefaultEffect
labelstrrequiredSets the required nonempty native accessible name and fallback text.
valuefloat | int | NoneNoneSets determinate completion from zero through max; None omits the native value attribute for indeterminate progress.
maxfloat | int100Sets the positive native task maximum.
value_textstr | NoneNoneSets optional aria-valuetext when units are not naturally understood as a percentage.
intent"neutral" | "primary" | "success" | "warn" | "danger" (CProgressIntent)"primary"Selects the visual range palette; surrounding text still carries meaning.
size"sm" | "md" | "lg" (CProgressSize)"md"Sets track thickness.
shape"square" | "rounded" | "pill" (CProgressShape)"rounded"Sets native track and range radius.
class_str | Mapping[str, bool] | Sequence[CClassValue] | None (CClassValue)NoneAdds native root classes and merges them with attrs.
stylestr | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] | None (CStyleValue)NoneAdds native root inline styles and merges them with attrs.
attrsMapping[str, object] | NoneNoneAdds copied trusted nonconflicting native, ARIA relationship, data, and targeted Alpine attributes to the native progress root.

CProgress client inputs

Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CProgress />.

InputTypeOmitted behaviorEffect
valuenumber | nullUses the server fallback.Controls native determinate value; null removes the attribute for indeterminate state; omission returns to server fallback.
labelstringUses the server fallback.Controls the nonempty native accessible name; omission returns to server fallback.
valueTextstring | nullUses the server fallback.Controls aria-valuetext; null removes it; omission returns to server fallback.
intent"neutral" | "primary" | "success" | "warn" | "danger"Uses the server fallback.Controls the public visual palette reflection.
size"sm" | "md" | "lg"Uses the server fallback.Controls the public thickness reflection.
shape"square" | "rounded" | "pill"Uses the server fallback.Controls the public radius reflection.

Slots

-

Events

-

Methods

-

CSS

CSS variables to theme the components. Set them on an ancestor or the component itself.

CProgress CSS variables

Apply these variables to CProgress or one of its ancestors.

VariableTypePurposeDefault
--cui-progress-track-colorcolorUnfilled native track.Scheme-aware neutral color.
--cui-progress-range-colorcolorCompleted range and indeterminate accent.Intent-derived color.
--cui-progress-heightlengthNative track thickness.Size-derived length.
--cui-progress-radiuslengthNative track and range radius.Shape-derived length.

Attributes

HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.

CProgress attributes

AttributeElementTypeMeaning
valueNative rootnumber or absentPresent only for determinate progress and controlled by the effective value.
maxNative rootpositive numberReflects the server-owned task maximum.
aria-labelNative rootnonempty stringCarries the required accessible task name.
aria-valuetextNative rootstring or absentCarries optional application-authored value phrasing.
data-stateNative root"determinate" | "indeterminate"Reflects whether the native value attribute is present.
data-intentNative root"neutral" | "primary" | "success" | "warn" | "danger"Reflects the effective visual palette.
data-sizeNative root"sm" | "md" | "lg"Reflects effective thickness.
data-shapeNative root"square" | "rounded" | "pill"Reflects effective radius.

Selectors

Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.

CProgress selectors

SelectorElementPurpose
[data-citry-ui-part="progress"]Native progress rootStable public root and attrs destination.

Interfaces

Aliases and data shapes referenced above.

Input type aliases

InterfaceDefinition
CClassValuestr | Mapping[str, bool] | Sequence[CClassValue]
CStyleValuestr | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue]
CProgressIntentLiteral["neutral", "primary", "success", "warn", "danger"]
CProgressSizeLiteral["sm", "md", "lg"]
CProgressShapeLiteral["square", "rounded", "pill"]

Translation keys

Catalog keys used by this family. An explicit component input or slot listed in Override takes precedence over the catalog for that instance.

CProgress translation keys

KeyPurposeVariablesOverrideBrowser updates
citry-ui-progress-value-textProvides readable fallback text for determinate progress.label: str; value: str; max: strNonei18n.bind() tracks locale and reactive value changes.