Skip to content
Viewership Inquire
Astro UI

Progress Ring.

Small progress ring with a count or glyph in the center.

DataAtomNo dependencies Beautiful UI, MIT

.md
Today's content plan
  • Spring email 5 of 5 · Approved
  • Weekly report 2 of 5 · In review
  • Reddit replies 1 of 4 · Next up
  • YouTube script 1 of 6 · Behind plan

Install

  1. Import the foundation once

    foundation.css holds the tokens every component reads.

    Layout.astro
    ---
    // src/layouts/Layout.astro
    import "../styles/foundation.css";
    ---
  2. Copy the 2 files

    Paste into src/components/viewership/progress-ring/

  3. Use it

    Page.astro
    ---
    import ProgressRing from "../components/viewership/progress-ring/ProgressRing.astro";
    ---
    
    <ProgressRing />

Props 7

PropTypeDefaultDescription
progress number · 0 to 1.
tone "orange" | "green" | "red" | "accent" "orange" Arc color.
size number 28 Diameter in px.
stroke number 2 Stroke width in px.
label string · Accessible name (or pass aria-labelledby).
valueText string · Spoken value, e.g. "3 of 5 drafts". Center slot is visual only.
setProgressRing(el, p, text?) (el: HTMLElement, progress: number, valueText?: string) => void · Animate to a new value and sync ARIA.

Source 2 files

src/components/viewership/progress-ring/progress-ring.ts
/**
 * progress-ring: update a <ProgressRing> from script.
 *
 * Ported from Beautiful UI `components/atoms/ProgressRing.tsx`
 * (MIT, © 2026 Shane Levine).
 *
 *   setProgressRing(ringEl, 0.6, "3 of 5 drafts");
 *
 * Animates the arc and syncs aria-valuenow and aria-valuetext. Update the
 * center content yourself.
 */
export function setProgressRing(root: HTMLElement, progress: number, valueText?: string): void {
  const p = Math.min(1, Math.max(0, Number.isFinite(progress) ? progress : 0));
  const bar = root.querySelector<SVGCircleElement>(".vs-progress-ring__bar");
  if (bar) {
    const c = 2 * Math.PI * bar.r.baseVal.value;
    bar.style.strokeDasharray = String(c);
    bar.style.strokeDashoffset = String(c * (1 - p));
  }
  root.setAttribute("aria-valuenow", String(Math.round(p * 100)));
  if (valueText !== undefined) root.setAttribute("aria-valuetext", valueText);
}

Ported from Beautiful UI, MIT. Notices.