Linear Progress
Linear progress is a simple progress bar that can be used to show the progress of a task such as downloading a file, uploading an image, etc.
Features
- Supports minimum and maximum values
- Supports indeterminate progress bars
Installation
Install the progress package:
npm install @zag-js/progress @zag-js/react # or yarn add @zag-js/progress @zag-js/react
npm install @zag-js/progress @zag-js/solid # or yarn add @zag-js/progress @zag-js/solid
npm install @zag-js/progress @zag-js/vue # or yarn add @zag-js/progress @zag-js/vue
npm install @zag-js/progress @zag-js/svelte # or yarn add @zag-js/progress @zag-js/svelte
Anatomy
Check the progress anatomy and part names.
Each part includes a
data-partattribute to help identify them in the DOM.
Usage
Import the progress package:
import * as progress from "@zag-js/progress"
The progress package exports two key functions:
machine- State machine logic.connect- Maps machine state to JSX props and event handlers.
Pass a unique
idtouseMachineso generated element ids stay predictable.
Then use the framework integration helpers:
import * as progress from "@zag-js/progress" import { normalizeProps, useMachine } from "@zag-js/react" import { useId } from "react" function Progress() { const service = useMachine(progress.machine, { id: useId() }) const api = progress.connect(service, normalizeProps) return ( <div {...api.getRootProps()}> <div {...api.getLabelProps()}>Upload progress</div> <div {...api.getTrackProps()}> <div {...api.getRangeProps()} /> </div> </div> ) }
import * as progress from "@zag-js/progress" import { normalizeProps, useMachine } from "@zag-js/solid" import { createMemo, createUniqueId } from "solid-js" function Progress() { const service = useMachine(progress.machine, { id: useId() }) const api = createMemo(() => progress.connect(service, normalizeProps)) return ( <div {...api().getRootProps()}> <div {...api().getLabelProps()}>Upload progress</div> <div {...api().getTrackProps()}> <div {...api().getRangeProps()} /> </div> </div> ) }
<script setup> import * as progress from "@zag-js/progress" import { normalizeProps, useMachine } from "@zag-js/vue" import { computed } from "vue" const service = useMachine(progress.machine, { id: "1" }) const api = computed(() => progress.connect(service, normalizeProps)) </script> <template> <div v-bind="api.getRootProps()"> <div v-bind="api.getLabelProps()">Upload progress</div> <div v-bind="api.getTrackProps()"> <div v-bind="api.getRangeProps()" /> </div> </div> </template>
<script lang="ts"> import * as progress from "@zag-js/progress" import { normalizeProps, useMachine } from "@zag-js/svelte" const id = $props.id() const service = useMachine(progress.machine, { id }) const api = $derived(progress.connect(service, normalizeProps)) </script> <div {...api.getRootProps()}> <div {...api.getLabelProps()}>Upload progress</div> <div {...api.getTrackProps()}> <div {...api.getRangeProps()}></div> </div> </div>
Setting the value
Use defaultValue for uncontrolled state, or value for controlled state.
const service = useMachine(progress.machine, { value: 50, })
Subsequently, you can use the api.setValue method to set the value of the
progress bar.
api.setValue(50)
Listening for value changes
Use onValueChange to react to progress updates.
const service = useMachine(progress.machine, { onValueChange(details) { // details => { value: number | null } console.log(details.value) }, })
Setting the minimum and maximum values
By default, the progress bar has a minimum value of 0 and a maximum value of
100. You can change these values by passing the min and max options to the
machine.
const service = useMachine(progress.machine, { min: 0, max: 1000, })
Vertical orientation
Set orientation to vertical for a vertical progress bar.
const service = useMachine(progress.machine, { orientation: "vertical", })
Using the indeterminate state
The progress component is determinate by default, with the value and max set to
50 and 100 respectively.
Set value to null to indicate an indeterminate value for operations whose
progress can't be determined (e.g., attempting to reconnect to a server).
const service = useMachine(progress.machine, { value: null, })
Customizing value text
Progress bars can only be interpreted by sighted users. To include a text
description to support assistive technologies like screen readers, use the
valueText part.
const service = useMachine(progress.machine, { translations: { value: ({ value, max }) => value == null ? "Loading..." : `${value} of ${max} items loaded`, }, })
Then you need to render the valueText part in your component.
<div {...api.getValueTextProps()}>{api.valueAsString}</div>
Localizing percentage formatting
Use locale and formatOptions to customize number formatting.
const service = useMachine(progress.machine, { locale: "fr-FR", formatOptions: { style: "percent", maximumFractionDigits: 1 }, })
Styling guide
Each part includes a data-part attribute you can target in CSS.
[data-scope="progress"][data-part="root"] { /* Styles for the root part */ } [data-scope="progress"][data-part="track"] { /* Styles for the track part */ } [data-scope="progress"][data-part="range"] { /* Styles for the range part */ }
Indeterminate state
To style the indeterminate state, you can use the [data-state=indeterminate]
selector.
[data-scope="progress"][data-part="root"][data-state="indeterminate"] { /* Styles for the root indeterminate state */ } [data-scope="progress"][data-part="track"][data-state="indeterminate"] { /* Styles for the root indeterminate state */ } [data-scope="progress"][data-part="range"][data-state="indeterminate"] { /* Styles for the root indeterminate state */ }
Methods and Properties
Machine Context
The progress machine exposes the following context properties:
idsPartial<{ root: string; track: string; label: string; circle: string; }>The ids of the elements in the progress bar. Useful for composition.valuenumberThe controlled value of the progress bar.defaultValuenumberThe initial value of the progress bar when rendered. Use when you don't need to control the value of the progress bar.minnumberThe minimum allowed value of the progress bar.maxnumberThe maximum allowed value of the progress bar.translationsIntlTranslationsThe localized messages to use.onValueChange(details: ValueChangeDetails) => voidCallback fired when the value changes.formatOptionsIntl.NumberFormatOptionsThe options to use for formatting the value.localestringThe locale to use for formatting the value.dir"ltr" | "rtl"The document's text/writing direction.idstringThe unique identifier of the machine.getRootNode() => ShadowRoot | Node | DocumentA root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.orientation"horizontal" | "vertical"The orientation of the element.
Machine API
The progress api exposes the following methods:
valuenumberThe current value of the progress bar.valueAsStringstringThe current value of the progress bar as a string.setValue(value: number) => voidSets the current value of the progress bar.setToMaxVoidFunctionSets the current value of the progress bar to the max value.setToMinVoidFunctionSets the current value of the progress bar to the min value.percentnumberThe percentage of the progress bar's value.percentAsStringstringThe percentage of the progress bar's value as a string.minnumberThe minimum allowed value of the progress bar.maxnumberThe maximum allowed value of the progress bar.indeterminatebooleanWhether the progress bar is indeterminate.