Feedback

Progress

How far along something is, as a bar or a ring, with its percentage, or indeterminate.

#feedback#progress#loading#no-js

Demo

Preview

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/progress.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/progress.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/progress.qwe
view ProgressDemo() =    <div.demo-stack>        <div.demo-stack.demo-narrow>            <Progress value={42} label="Uploading 12 photos" show_value={true}/>            <Progress value={3} max={5} tone="success" label="Profile, 3 of 5 steps" show_value={true}/>            <Progress value={91} tone="warning" size="sm" label="Storage almost full" show_value={true}/>            <Progress label="Preparing the export"/>            <Progress value={66.5} size="lg" tone="info"/>        </div>        <div.demo-row>            <Progress variant="ring" value={72} label="Storage used"/>            <Progress variant="ring" value={100} tone="success" size="lg" label="Sync complete"/>            <Progress variant="ring" value={18} tone="danger" label="Battery"/>            <Progress variant="ring" size="sm" value={50} label="Halfway"/>            <Progress variant="ring" label="Connecting"/>        </div>    </div>

Source

ui/progress.qwe
// Progress: how far along something is, as a bar or a ring (role="progressbar").////   <Progress value={42} label="Uploading photos" show_value={true}/>//   <Progress value={3} max={5} tone="success" label="Profile complete"/>//   <Progress label="Preparing export"/>                   no value: indeterminate//   <Progress variant="ring" value={72} label="Storage used"/>//// value: from 0 to max (100 by default); null means not known yet, shown as a// moving stripe (which stands still with reduced motion). label: what it measures,// shown above the bar and read by screen readers. show_value: the percentage// beside the label (the ring always shows it). tone: "accent" (default),// "neutral", "success", "warning", "danger" or "info". size: "sm", "md" (default)// or "lg": the bar's thickness, or the ring's diameter.import ui/theme.qwe use ui_clslet progress_css = css`.ui-progress, .ui-progress-ring { --t: var(--ui-accent); }.ui-progress { display: grid; gap: 6px; font: 13px/1.4 var(--ui-font); color: var(--ui-fg); }.ui-progress-neutral { --t: var(--ui-muted); }.ui-progress-success { --t: var(--ui-success); }.ui-progress-warning { --t: var(--ui-warning); }.ui-progress-danger { --t: var(--ui-danger); }.ui-progress-info { --t: var(--ui-info); }.ui-progress-head { display: flex; justify-content: space-between; gap: 12px; }.ui-progress-value { color: var(--ui-muted); font-variant-numeric: tabular-nums; }.ui-progress-track { position: relative; height: 8px; overflow: hidden; border-radius: 999px; background: var(--ui-subtle);  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ui-border) 60%, transparent); }.ui-progress-sm .ui-progress-track { height: 4px; }.ui-progress-lg .ui-progress-track { height: 12px; }.ui-progress-fill { height: 100%; border-radius: inherit; background: var(--t); transition: width .3s ease; }.ui-progress-busy .ui-progress-fill { position: absolute; width: 40%; animation: ui-progress-slide 1.3s ease-in-out infinite; }@keyframes ui-progress-slide { from { left: -40%; } to { left: 100%; } }.ui-progress-ring { display: inline-grid; place-items: center; position: relative; width: 48px; height: 48px; font-family: var(--ui-font); }.ui-progress-ring.ui-progress-sm { width: 32px; height: 32px; }.ui-progress-ring.ui-progress-lg { width: 72px; height: 72px; }.ui-progress-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }.ui-progress-ring circle { fill: none; stroke-width: 3.5; }.ui-progress-ring .ui-progress-bg { stroke: var(--ui-subtle); }.ui-progress-ring .ui-progress-arc { stroke: var(--t); stroke-linecap: round; transition: stroke-dasharray .3s ease; }.ui-progress-ring.ui-progress-busy svg { animation: ui-progress-turn 1s linear infinite; }@keyframes ui-progress-turn { to { transform: rotate(270deg); } }.ui-progress-ring .ui-progress-value { position: absolute; color: var(--ui-fg); font-size: 12px; font-weight: 600; }.ui-progress-ring.ui-progress-sm .ui-progress-value { display: none; }.ui-progress-ring.ui-progress-lg .ui-progress-value { font-size: 16px; }@media (prefers-reduced-motion: reduce) {  .ui-progress-fill, .ui-progress-ring .ui-progress-arc { transition: none; }  .ui-progress-busy .ui-progress-fill { left: 0; width: 100%; opacity: .45; animation: none; }  .ui-progress-ring.ui-progress-busy svg { animation: none; }}`// A number as text, whole ones without ".0", as the browser writes them.fn progress_num(n: num) -> str = n == floor(n) ? str(floor(n)) : str(n)view Progress(value: num? = null, max: num = 100, label: str? = null, show_value: bool = false,              variant: str = "bar", tone: str = "accent", size: str = "md", class: str? = null) {    style global progress_css    let known = value != null && max > 0    let part = known ? (value < 0 ? 0 : (value > max ? max : value)) : 0    let pct = known ? round(part * 1000 / max) / 10 : 0        // 42 or 42.5: the same text on both sides    let shown = `${round(pct)}%`    let cls = ui_cls([variant == "ring" ? "ui-progress-ring" : "ui-progress", `ui-progress-${tone}`,                      size != "md" && `ui-progress-${size}`, !known && "ui-progress-busy", class])    let aria = { role: "progressbar", "aria-label": label, "aria-valuemin": known ? "0" : null,                 "aria-valuemax": known ? progress_num(max) : null, "aria-valuenow": known ? progress_num(part) : null,                 "aria-valuetext": known ? shown : null }    variant == "ring"        ? <div class={cls} {...aria}>              <svg viewBox="0 0 36 36" aria-hidden="true">                  <circle.ui-progress-bg cx="18" cy="18" r="15.5"/>                  <circle.ui-progress-arc cx="18" cy="18" r="15.5" pathLength="100"                          stroke-dasharray={known ? `${pct} 100` : "28 100"}/>              </svg>              {known && <span.ui-progress-value aria-hidden="true">{shown}</span>}          </div>        : <div class={cls}>              {(label != null || (show_value && known)) && <div.ui-progress-head aria-hidden="true">                  <span>{label}</span>                  {show_value && known && <span.ui-progress-value>{shown}</span>}              </div>}              <div.ui-progress-track {...aria}>                  <div.ui-progress-fill style={known ? `width: ${pct}%` : null}></div>              </div>          </div>}
Thread
56Useful? Like it, or add to its thread below.

Thread 0 posts

On Progress: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.