Skip to content
ShineUI
Install

ProgressBar

How far along.

<sui-progress-bar>FeedbackStable

About

Determinate bar or indeterminate sweep for work with a known or unknown total: an import, a budget meter, a sync. show-value adds a readout: the rounded percentage, or the value slot in the screen's own units. It is output, not a control, so it never takes focus.

Usage

<sui-progress-bar label="Importing bank feed" value="64" show-value></sui-progress-bar> <script type="module"> import { defineCustomElements } from "@shineui/core/loader"; import "@shineui/core/shineui.css"; defineCustomElements(); </script>
import { SuiProgressBar } from "@shineui/react"; import "@shineui/core/shineui.css"; export function Example() { return <SuiProgressBar label="Importing bank feed" value="64" showValue />; }
<script setup> import { SuiProgressBar } from "@shineui/vue"; import "@shineui/core/shineui.css"; </script> <template> <SuiProgressBar label="Importing bank feed" value="64" show-value /> </template>
import { Component } from "@angular/core"; import { SuiProgressBar } from "@shineui/angular"; @Component({ standalone: true, imports: [SuiProgressBar], template: `<sui-progress-bar label="Importing bank feed" value="64" show-value></sui-progress-bar>`, }) export class Example { }

Basic

A label, a navy fill and, with show-value, the rounded percentage. The track is role="progressbar" with min 0, max 100 and the value, named by the label; it never takes focus, because it is output, not a control.

<div style="max-width:420px"><sui-progress-bar label="Importing bank feed" value="64" show-value></sui-progress-bar></div>

Quiet by default

Without show-value the bar draws the label and the fill and says no number, which is the shape for a bar beside its own count or inline in a row. Add show-value where the percentage is the point.

<div style="display:flex;flex-direction:column;gap:12px;max-width:420px;"> <sui-progress-bar label="Subtasks closed" value="40"></sui-progress-bar> <sui-progress-bar label="Subtasks closed" value="40" show-value></sui-progress-bar> </div>

Accent and indeterminate

accent swaps the navy fill for orange, for a budget or attention meter. indeterminate sweeps while the total is unknown, drops aria-valuenow and hides any readout, so assistive tech says busy rather than a number that is not true; the sweep slows under reduced motion instead of stopping.

<div style="display:flex;flex-direction:column;gap:12px;max-width:420px;"> <sui-progress-bar label="Budget used, Marketing" value="87" accent show-value></sui-progress-bar> <sui-progress-bar label="Syncing" indeterminate></sui-progress-bar> </div>

Value slot

Fill the value slot to say the number in the units the screen is about. The slot replaces the percentage readout only: value, aria-valuenow and the drawn fill are unchanged, and it is drawn with the readout, so it needs show-value too.

$5,220 of $6,000 340 of 1,200
<div style="display:flex;flex-direction:column;gap:12px;max-width:420px;"> <sui-progress-bar label="Marketing budget" value="87" accent show-value><span slot="value">$5,220 of $6,000</span></sui-progress-bar> <sui-progress-bar label="Importing bank feed" value="28" show-value><span slot="value">340 of 1,200</span></sui-progress-bar> </div>

Height and captions

height is the track in px and the radius follows it. With no label and no readout the caption row is not rendered, which is the shape for a bar inline in a table row; name it with aria-label on the host so the progressbar role is not left unnamed.

<div style="display:flex;flex-direction:column;gap:14px;max-width:420px;"> <sui-progress-bar label="Default, 8px" value="52" show-value></sui-progress-bar> <sui-progress-bar label="Heavy, 14px" value="52" height="14" show-value></sui-progress-bar> <sui-progress-bar aria-label="Riverbend collection" value="52" height="4"></sui-progress-bar> </div>

Live value

value is a plain number prop, so progress is written from app state. It clamps to 0 through 100 and the readout rounds.

0 of 1,200
<div style="display:flex;flex-direction:column;gap:12px;max-width:420px;"> <sui-progress-bar id="pb-live" label="Importing bank feed" value="0" show-value><span slot="value" id="pb-count">0 of 1,200</span></sui-progress-bar> <div style="display:flex;gap:8px;flex-wrap:wrap;"> <sui-button id="pb-step" variant="outline" label="Advance"></sui-button> <sui-button id="pb-reset" variant="ghost" label="Reset"></sui-button> </div> </div>
// setup(root): properties and events setup(root) { const bar = root.querySelector('#pb-live'); const count = root.querySelector('#pb-count'); const total = 1200; let done = 0; const paint = () => { bar.value = (done / total) * 100; count.textContent = `${done.toLocaleString('en-US')} of 1,200`; }; root.querySelector('#pb-step').addEventListener('click', () => { done = Math.min(total, done + 180); paint(); }); root.querySelector('#pb-reset').addEventListener('click', () => { done = 0; paint(); }); }

API

<sui-progress-bar>

Properties

PropertyAttributeTypeDefaultDescription
accentaccentbooleanfalseAccent fill instead of brand, for a budget or attention meter.
heightheightnumber8Track height in px. The radius follows (height / 2).
indeterminateindeterminatebooleanfalseSweeps while the total is unknown and drops aria-valuenow, so assistive tech says busy rather than a number that is not true. The sweep slows under reduced motion instead of stopping, because a frozen sweep reads as a hang.
labellabelstringstring | undefinedLeft-hand caption above the track. Also the accessible name of the progressbar role; a bar with no caption takes its name from aria-label on the host instead.
showValueshow-valuebooleanfalseDraws the readout to the right of the label: the rounded percentage in the page's locale (47%, 47 % in German), or the value slot when it is filled. Off by default, so a bar inline in a row or beside its own count says nothing twice. Ignored while indeterminate.
valuevaluenumber0Completion, 0 to 100. Ignored while indeterminate.

Slots

SlotDescription
valueReplaces the percentage readout. Drawn only with show-value, and never while indeterminate.

Theming

Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.

See also