Cairn
Stable

Ring

Single-value radial progress, a grayscale ink arc on a neutral track. tone=accent opts into hue.

  • Compute82%
  • Storage66%
  • Cache48%
  • Network34%
Show code
import { Ring } from '@six-vallees/ui-react';

const val = 'font-semibold leading-none tabular-nums';

// On a dark surface the acid rides direct, no keyline needed (contrast ~15:1). ink inverts
// to near-white via the dark-theme chart tokens, so every arc stays perceptible.
const metrics = [
  { label: 'Compute', value: 82, size: 200, color: 'var(--sv-sys-chart-categorical-2)' }, // blue
  { label: 'Storage', value: 66, size: 156, color: 'var(--sv-sys-chart-categorical-3)' }, // acid, signature
  { label: 'Cache', value: 48, size: 112, color: 'var(--sv-sys-chart-axis)' },            // graphite
  { label: 'Network', value: 34, size: 68, color: 'var(--sv-sys-chart-ink)' },            // ink → near-white on dark
];

export default function RingDemo() {
  return (
    <div className="flex flex-col gap-10">
      {/* Single value, accent blue on the light surface, arc fills on mount */}
      <div className="flex flex-wrap items-center gap-10 text-on-surface">
        <Ring value={70} tone="accent">
          <div className={`${val} text-[28px]`}>70%</div>
        </Ring>
        <Ring value={42} size={120} thickness={12} tone="accent">
          <div className={`${val} text-[22px]`}>42%</div>
        </Ring>
        <Ring value={88} tone="accent">
          <div className={`${val} text-[28px]`}>88%</div>
        </Ring>
      </div>

      {/* Concentric multi-metric on a dark tile, acid sings, edge-free. Colour is carried by
          a labelled legend, never colour alone. */}
      <div
        data-theme="dark"
        className="flex flex-wrap items-center gap-x-12 gap-y-8 rounded-card bg-surface p-8 text-on-surface"
      >
        <div className="relative shrink-0" style={{ width: 200, height: 200 }}>
          {metrics.map((m) => (
            <div key={m.label} className="absolute inset-0 grid place-items-center">
              <Ring value={m.value} size={m.size} thickness={12} color={m.color} aria-label={`${m.label} ${m.value}%`} />
            </div>
          ))}
        </div>
        <ul className="flex flex-col gap-3">
          {metrics.map((m) => (
            <li key={m.label} className="flex items-center gap-3 text-[15px]">
              <span className="size-3 shrink-0 rounded-full" style={{ background: m.color }} aria-hidden="true" />
              <span className="w-24 text-on-surface-variant">{m.label}</span>
              <span className={`${val} text-[16px]`}>{m.value}%</span>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

Installation

npx shadcn@latest add https://cairn.sixvallees.com/r/ring.json