ProgressRing
Circular progress in four sizes, with its percentage or a value of your own in the middle, or turning while not known.
Demo
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_ring.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/progress_ring.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/progress_ring.qwe
view ProgressRingDemo() = <div.demo-stack> <div.demo-row style="gap: 24px"> <ProgressRing value={8} size="sm" label="Uploading"/> <ProgressRing value={42} label="Storage used"/> <ProgressRing value={3} max={5} value_text="3/5" size="lg" tone="success" label="Lessons done"/> <ProgressRing value={91} size="xl" tone="warning" thickness={8} label="Monthly quota" show_label={true}/> </div> <div.demo-row style="gap: 24px"> <ProgressRing value={100} tone="success" label="Backup complete" show_label={true}/> <ProgressRing value={0} label="Not started" show_label={true}/> <ProgressRing size="sm" label="Syncing" show_label={true}/> <ProgressRing size="lg" tone="neutral" label="Preparing export" show_label={true}/> </div> </div>Source
ui/progress_ring.qwe
// ProgressRing: how far along something is, as a ring with the percentage in it,// or a turning arc while that is not known yet (role="progressbar").//// <ProgressRing value={72} label="Storage used"/>// <ProgressRing value={3} max={5} value_text="3/5" size="lg" label="Lessons done" show_label={true}/>// <ProgressRing label="Uploading" size="sm"/> no value: indeterminate//// value: from 0 to max (100 by default); null means not known yet, shown as an arc// that turns (and stands still with reduced motion). label: what it measures, read// by screen readers; show_label also writes it beside the ring (below it with// size="xl"). show_value: the percentage in the middle (true; sizes from md up);// value_text: other text there ("3/5", "12 GB"). size: "sm" (32px), "md" (48px,// default), "lg" (72px) or "xl" (112px). thickness: the ring's width, out of the// ring's 100 (10). tone: "accent" (default), "neutral", "success", "warning",// "danger" or "info".import ui/theme.qwe use ui_clslet progress_ring_css = css`.ui-pr { display: inline-flex; align-items: center; gap: 10px; vertical-align: middle; font: 13px/1.4 var(--ui-font); color: var(--ui-fg); --t: var(--ui-accent); --s: 48px; }.ui-pr-neutral { --t: var(--ui-muted); }.ui-pr-success { --t: var(--ui-success); }.ui-pr-warning { --t: var(--ui-warning); }.ui-pr-danger { --t: var(--ui-danger); }.ui-pr-info { --t: var(--ui-info); }.ui-pr-sm { --s: 32px; }.ui-pr-lg { --s: 72px; }.ui-pr-xl { --s: 112px; flex-direction: column; gap: 8px; }.ui-pr-ring { position: relative; display: grid; place-items: center; flex: none; width: var(--s); height: var(--s); }.ui-pr-ring svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }.ui-pr-ring circle { fill: none; }.ui-pr-track { stroke: var(--ui-subtle); }.ui-pr-arc { stroke: var(--t); stroke-linecap: round; transition: stroke-dasharray .35s ease; }.ui-pr-busy svg { animation: ui-pr-turn 1s linear infinite; }@keyframes ui-pr-turn { from { transform: rotate(-90deg); } to { transform: rotate(270deg); } }.ui-pr-value { position: relative; font-size: calc(var(--s) * .22); font-weight: 650; font-variant-numeric: tabular-nums; }.ui-pr-sm .ui-pr-value { display: none; }.ui-pr-xl .ui-pr-value { font-size: 26px; }.ui-pr-label { color: var(--ui-muted); }@media (prefers-reduced-motion: reduce) { .ui-pr-arc { transition: none; } .ui-pr-busy svg { animation: ui-pr-pulse 2s ease-in-out infinite; }}@keyframes ui-pr-pulse { 50% { opacity: .45; } }`// A number as text, whole ones without ".0", to one decimal at most.fn progress_ring_num(n: num) -> str { let r = round(n * 10) / 10 r == floor(r) ? str(floor(r)) : str(r)}view ProgressRing(value: num? = null, max: num = 100, label: str = "Progress", show_label: bool = false, show_value: bool = true, value_text: str? = null, size: str = "md", thickness: num = 10, tone: str = "accent", class: str? = null) { style global progress_ring_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 let shown = value_text ?? `${round(pct)}%` let w = thickness < 2 ? 2 : (thickness > 30 ? 30 : thickness) let r = progress_ring_num(50 - w / 2) <div class={ui_cls(["ui-pr", `ui-pr-${tone}`, size != "md" && `ui-pr-${size}`, !known && "ui-pr-busy", class])} role="progressbar" aria-label={label} aria-valuemin={known ? "0" : null} aria-valuemax={known ? progress_ring_num(max) : null} aria-valuenow={known ? progress_ring_num(part) : null} aria-valuetext={known ? shown : null}> <span.ui-pr-ring> <svg viewBox="0 0 100 100" aria-hidden="true"> <circle.ui-pr-track cx="50" cy="50" r={r} stroke-width={progress_ring_num(w)}/> {(!known || pct > 0) && <circle.ui-pr-arc cx="50" cy="50" r={r} stroke-width={progress_ring_num(w)} pathLength="100" stroke-dasharray={known ? `${progress_ring_num(pct)} 100` : "28 100"}/>} </svg> {known && show_value && <span.ui-pr-value aria-hidden="true">{shown}</span>} </span> {show_label && <span.ui-pr-label aria-hidden="true">{label}</span>} </div>}Related
MeterA measurement within a range, coloured green, amber or red by whether it is where it should be, as segments or one bar.4 views · 7 downloadsProgressHow far along something is, as a bar or a ring, with its percentage, or indeterminate.5 views · 6 downloadsUploadProgressOne file's upload: name, bytes sent of its size, speed, time left, a bar, and Cancel; done, paused and error states.4 views · 7 downloadsAlertA message in the page in six tones and three variants, with an icon, announced to screen readers, and dismissable.5 views · 9 downloadsBadgeA small pill for a status or a count: six tones, soft, solid or outline, a status dot, and 99+.8 views · 6 downloadsBannerAn announcement across the top of the page in six tones, with a link, closed for the session once dismissed.7 views · 6 downloads
Thread
Thread 0 posts
On ProgressRing: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.