Installation
pnpm dlx shadcn@latest add https://asciicn.dev/r/progress-bar.jsonUsage
import { ProgressBar } from "@/components/asciicn/progress-bar";
export function Upload({ percent }: { percent: number }) {
return <ProgressBar label="Uploading report.pdf" value={percent} />;
}value runs from 0 to max, which is 100 unless you set it. The fill is a row of full blocks that ends in one of the eighth blocks ▏▎▍▌▋▊▉, so 37.5% of a 32-cell bar is exactly 12 cells: ████████████. The bar is as many whole cells as fit its container, measured in the glyph font, and it measures again when the container or the zoom changes.
Behind the fill runs a track of ░ (track="shade"), ·, ─ or nothing. A new value slides in eighth by eighth over 600ms.
Leave value out when you can't measure progress. A comet of ░▒▓█ sweeps the track instead:
<ProgressBar label="Indexing repository" />Examples
Usage card
parts stacks several values in one bar, each in its own colour, with a legend of █ swatches underneath. Boundaries between parts snap to whole cells, because a cell holds one glyph in one colour. The leading edge of the total keeps its eighth-cell precision.
Upload list
Three states at size="lg": a finished file in green, one at 46.25%, and an indeterminate step on a ─ track while the server transcodes.
Onboarding steps
segments cuts the bar into blocks with a blank cell between them. The value fills the blocks in order, so three of five tasks fill three blocks.
Props
| Prop | Type | Default |
|---|---|---|
| label* What is in progress. Shown above the bar and used as its accessible name. | Type: string | Default – |
| value Progress from 0 to max. Leave it out for an indeterminate bar. | Type: number | null | Default – |
| parts { label: string; value: number; color?: AsciiColor }, stacked left to right instead of value. | Type: ProgressPart[] | Default – |
| unit With parts: shown after each value in the legend, such as " GB". | Type: string | Default – |
| max The value that means done, or the capacity for parts. | Type: number | Default 100 |
| valueText Text for the readout and for screen readers. | Type: string | Default The percentage |
| hideLabel Hide the label and readout visually. Screen readers still get them. | Type: boolean | Default false |
| size Glyph cell height: 12, 16 or 20px. | Type: "sm" | "md" | "lg" | Default "md" |
| track Glyph along the empty track: ░, ·, ─ or nothing. | Type: "shade" | "dots" | "line" | "none" | Default "shade" |
| color Colour of the fill, a palette name or any CSS colour. | Type: AsciiColor | Default "ink" |
| segments Cut the bar into this many blocks a cell apart, for step meters. | Type: number | Default – |
| columns Fix the bar's width in cells instead of filling the container. | Type: number | Default As many as fit |
| animate Ease between values and grow in on mount. | Type: boolean | Default true |
| cell Glyph cell height in CSS pixels. Overrides size. | Type: number | Default – |
Notes
- The root has
role="progressbar", is named by the label and reportsaria-valuenowandaria-valuetext. An indeterminate bar leaves the value out, as assistive technology expects. The glyphs are hidden from screen readers. - The bar is DOM text in
--ascii-font, one line tall, so it stays sharp at any zoom and its height never changes. Before the first measurement it draws 32 cells. - With reduced motion, values jump instead of easing and the comet rests in the middle of the track.
- The comet redraws at 30fps and pauses when the bar is offscreen or the tab is hidden.