Data Display
Gauge
A radial gauge — one number against the range it lives in.
import { Gauge } from 'omaris' Examples
Basic
One number against the range it lives in. label goes under the readout.
<script lang="ts"> import { Gauge } from 'omaris';</script><Gauge value={72} label="CPU" /><Gauge value={38} label="Memory" tone="info" /><Gauge value={94} label="Disk" tone="destructive" /> Segments and ticks
segments paint zones on the track — a red band past 80% — without touching the indicator, so the reading and the scale stay separate things. ticks marks the scale, and format writes the number in the middle.
<script lang="ts"> import { Gauge, latn } from 'omaris';</script><Gauge value={86} label="Load" tone="warning" ticks={9} segments={[ { from: 0, to: 60, tone: 'success' }, { from: 60, to: 80, tone: 'warning' }, { from: 80, tone: 'destructive' } ]}/><Gauge value={1420} max={2000} label="of 2,000" tone="tertiary" format={(v) => Math.round(v).toLocaleString(undefined, latn())}/> Sizes and sweep
sweep is degrees of arc: 270 is the classic dial, 360 closes it into a ring. thickness is a share of the radius, so it holds at every size.
<script lang="ts"> import { Gauge, Text } from 'omaris';</script><div class="flex flex-wrap items-end justify-center gap-8"> <div class="flex flex-col items-center gap-2"> <Gauge value={64} size="sm" label="sm" /> <Text variant="label-sm" tone="muted" font="mono">sweep 270</Text> </div> <div class="flex flex-col items-center gap-2"> <Gauge value={64} size="md" sweep={360} rounded={false} label="md" /> <Text variant="label-sm" tone="muted" font="mono">sweep 360</Text> </div> <div class="flex flex-col items-center gap-2"> <Gauge value={64} size="lg" sweep={180} thickness={0.32} label="lg" tone="secondary" /> <Text variant="label-sm" tone="muted" font="mono">sweep 180</Text> </div></div> Animated
A new value glides in on the emphasized curve, and the number counts with the arc — both driven by one tween, so they stop together. animate={false} makes it jump; a number sets the duration.
<script lang="ts"> import { Button, Gauge, SegmentedButton } from 'omaris'; let value = $state(64); let mode = $state('smooth'); const animate = $derived(mode === 'instant' ? false : mode === 'slow' ? 1600 : true); const bump = () => (value = Math.round(5 + Math.random() * 90));</script><div class="flex flex-col items-center gap-4"> <div class="flex flex-wrap items-center justify-center gap-6"> <Gauge {value} {animate} label="Throughput" tone={value > 80 ? 'warning' : 'primary'} /> <Gauge {value} {animate} label="Ring" sweep={360} thickness={0.14} tone="tertiary" format={(v) => `${Math.round(v)}%`} /> </div> <div class="flex flex-wrap items-center justify-center gap-3"> <SegmentedButton bind:value={mode} size="sm" label="Animation" items={[ { value: 'smooth', label: 'Smooth' }, { value: 'slow', label: 'Slow' }, { value: 'instant', label: 'Instant' } ]} /> <Button size="sm" variant="tonal" onclick={bump}>New reading</Button> </div></div> When to use it
Use it for
- One number against its range: CPU at 72%, quota used, a score out of 100. The value is printed in the middle, so nobody has to read an arc.
- A status light with a number in it. Set
tone="warning"past 60 anddestructivepast 80 from the value in the page. - A scale with zones.
segmentspaint a red band from 80 on the track without touching the indicator, so reading and scale stay separate. - A live reading. The arc and the number tween together, so a new value glides and counts up.
animate={false}lands a value at once.
Not for
- Progress toward finishing a task, like an upload or a wizard → Progress. A gauge is a reading, not a wait.
- Several progress-shaped values side by side →
RadialBarChartin Chart, and past about six aBarChart. - A trend over time →
Sparklineinside the stat, or aLineChart, both in Chart. - A number with no meaningful ceiling, like revenue or a count → a
display-smText in a card. A dial with an inventedmaxreads as a share that is not there.
Do
- Say what the number is under it:
label="CPU", orlabel="of 2,000"whenformatwrites the unit into the readout. - Pick
sweepfor the space: 270 is the classic dial, 180 fits a half-height card, 360 closes it into a ring. - In a dense table cell, use
size="sm"withshowValue={false}and put the figure in the next column. - Prefer this one, from
omaris, unless the page already importsomaris/chart. That entry has aGaugetoo, drawn by layerchart withthresholdsandcaption, for dials that share the chart palette.
Don't
- Colour the indicator from a
segmentsband and fromtonewith two different meanings. The band is the scale; the tone is the reading. - Set
tickson asmgauge. At that size they are noise. - Tween a value that updates several times a second. Pass a short
animateorfalse, or the dial never catches up.
Quick reference
tone primary(default)secondarytertiarydestructivesuccesswarninginfo
size smmd(default)lg
API
Gauge
A radial gauge — one number against the range it lives in.
The arc is a real SVG stroke with a dash offset, and it stays crisp at any size. The sweep and the number in the middle are driven by one tweened value on the emphasized curve, so a new reading glides in and counts up together, stopping at the same instant — and the dial rises from empty when it first appears. animate={false} makes it jump, a number sets the duration in ms. segments paint zones on the track (a red band past 80%, say) without touching the indicator, so the reading and the scale stay separate things.
import { Gauge } from 'omaris' <Gauge value={72} label="CPU" tone="warning" segments={[{ from: 80, tone: 'destructive' }]} /> Parts
Every element this renders is reachable from outside. Pass Tailwind for one part as classes={{ part: '…' }}; class covers the root and is merged last, so it always wins.
root- No description in the source yet.
svg- The square the arc is drawn in.
track- The unfilled remainder of the sweep.
segment- A coloured band on the track, behind the indicator.
indicator- The filled arc. Its sweep is tweened in script; only the colour transitions here.
content- Centred stack: value over label.
value- No description in the source yet.
label- No description in the source yet.
tick- Tick marks around the scale.
Props
value required number min Defaults to 0
number max Defaults to 100
number tone Defaults to 'primary'
GaugeTone primarysecondarytertiarydestructivesuccesswarninginfo
size Defaults to 'md'
GaugeSize smmdlg
sweep Defaults to 270
number Degrees of arc. 270 is the classic dial; 360 closes it into a ring.
thickness Defaults to 0.22
number Stroke width as a share of the radius.
rounded Defaults to true
boolean Round the ends of both arcs.
segments GaugeSegment[] Zones on the track — thresholds, safe ranges, a red line.
ticks Defaults to 0
number Evenly spaced ticks around the scale. 0 draws none.
label string Under the number — "CPU", "of 2,000".
format (value: number) => string Formats the number in the middle. Defaults to a rounded integer.
showValue Defaults to true
boolean Hide the centred readout — for a gauge in a dense table cell.
animate Defaults to true
boolean | number Glide to a new value rather than jump. true takes 700 ms on the emphasized curve, a number sets the duration in ms, false is instant. Reduced motion is always instant.
children Snippet Replaces the whole centre stack.
name string Accessible name. Falls back to label, and one of the two is required: a meter with a value and no name reaches a screen reader as "64 percent" of nothing. Give it one whenever the centre stack is replaced by children, which is the case where label is gone.
class string classes GaugeClasses height number | string Plot height. A number is px; a string is any CSS length.
color string Any CSS colour. Ignored where a thresholds entry matches.
thresholds { at: number; color: string }[] Colour by value: the first entry whose at the value is at or under wins, and anything above them all falls back to color.
caption string A word under the number — "of quota", "requests/s".
centre Snippet<[{ value: number }]> Replaces the number and caption in the middle.
title string Accessible description of what the gauge shows.
error boolean | string | Error Something went wrong. Truthy puts the chart into its error state; a string or an Error supplies the message.
errorText string The message, when error is just true.
errorState Snippet<[{ message: string }]> Replaces the whole error state.
onRetry () => void Offers a "Try again" button in the error state.
csv boolean | string Offer the plotted rows as a CSV download, from a button in the corner. A string names the file.
csvColumns (string | { key: string; label?: string; value?: (row: T) => unknown })[] Which fields the download writes, in order. Defaults to every field.