# Gauge

**Maturity:** experimental

Show a scalar value positioned inside a bounded range (default 0…1) as an arc or bar — a speedometer, a battery, a load meter.

## Import

```tsx
import { Gauge } from "@liquidify/react/gauge"
```

## Props

- `className`: `string | undefined`. Optional additional CSS class merged into the glass surface class. The supported per-instance customisation seam: override any `--lq-*` custom property from this class's CSS — the token cascade the engine reads (ADR-0004). No raw inline style is involved, so this stays ADR-0003 clean.
- `currentValueLabel`: `ReactNode`. Formatted current value (SwiftUI `currentValueLabel: () -> View`). Rendered visibly on the two marker/accessory styles (leading the line on `accessoryLinear`, large and centred on `accessoryCircular`); not rendered on the two capacity styles (unexercised by the reference). When its content is a plain `string`/`number`, it also drives `aria-valuetext` so assistive tech announces the formatted value (e.g. `"68%"`) rather than a bare number.
- `label`: `ReactNode` (required). The primary descriptor (SwiftUI `label: () -> Label`, required) — the accessible name source. Rendered visibly on the two **capacity** styles (above the bar / centred in the ring); folded into the accessible name only (via a visually-hidden node) on the two **marker/accessory** styles, where the reference shows no visible `label` glyph. A string/number renders through the `Text` primitive; a `ReactNode` passes through the `TextLabel` guard unwrapped (ADR-0028). A caller supplying a visually-empty `label` (e.g. a bare tint swatch) **must** also supply an explicit `aria-label` — Gauge does not synthesize a name from `tint` / `variant`.
- `labelProps`: `LabelProps | undefined`. Per-instance typography override for the primary {@link GaugeProps.label} (ADR-0028, charter §2). Token-backed axes only; spread **last** onto the internal `Text` so an explicit value wins over the component's computed default. Applies to the visible label on `linearCapacity` (`.lq-gauge-label`) and `accessoryCircularCapacity` (`.lq-gauge-ring-label`). Has no effect on the two marker/accessory styles, where `label` renders visually-hidden.
- `max`: `number | undefined`; default ``1``. Upper bound of the range (SwiftUI `in: lower...upper`).
- `maximumValueLabel`: `ReactNode`. Upper-bound caption (SwiftUI `maximumValueLabel: () -> View`). Same placement rule as {@link GaugeProps.minimumValueLabel}.
- `min`: `number | undefined`; default ``0``. Lower bound of the range (SwiftUI `in: lower...upper`).
- `minimumValueLabel`: `ReactNode`. Lower-bound caption (SwiftUI `minimumValueLabel: () -> View`). Rendered only by `accessoryCircular` in the reference, flanking below {@link GaugeProps.currentValueLabel}.
- `ref`: `Ref<HTMLDivElement> | undefined`. Forwarded ref to the rendered element — the component's native root (or the merged child element on a component that opts into {@link SlottableProps}). Generic over `E` (charter `docs/api-conventions.md` §4 rule 1, default `HTMLElement`) so a component with a polymorphic root (Link's navigation / action mode union, Text's `as`) can instantiate the concrete element per variant instead of leaving every consumer with a widened `Ref<HTMLElement>`. A component that does not narrow simply inherits the `HTMLElement` default — source-compatible with every pre-existing non-generic `extends ControlProps`.
- `tint`: `LiquidTintValue | undefined`. System-accent of the capacity fill (SwiftUI `.tint(_:)`), drawn from the restricted {@link LIQUID_COLORS } palette. Meaningful **only** on the two capacity styles (`linearCapacity`, `accessoryCircularCapacity`); the two marker/accessory styles always render monochrome primary and ignore this prop. When omitted on a capacity style, the fill resolves to `--lq-color-accent` (SwiftUI's default, system blue).
- `value`: `number` (required). The current value, positioned within `[min, max]`. Out-of-range values are clamped (never extrapolated past the track/arc ends) and the clamped bound — not the raw prop — is what `aria-valuenow` reports.
- `valueProps`: `LabelProps | undefined`. Per-instance typography override for {@link GaugeProps.currentValueLabel} (charter §2 rule 3). Token-backed axes only; spread **last** onto the internal `Text` so an explicit value wins over the component's computed default. Applies to `accessoryLinear` (`.lq-gauge-current`) and `accessoryCircular` (`.lq-gauge-arc-current`). {@link GaugeProps.minimumValueLabel} / {@link GaugeProps.maximumValueLabel} carry no override seam.
- `variant`: `GaugeStyle | undefined`; default ``"linearCapacity"``. Visual style — verbatim SwiftUI `.gaugeStyle(_:)` member spelling.

## SwiftUI mapping

- ``Gauge(value:label:)`` → ``value: number` (required) + `label: ReactNode` (required)` (direct): Display-only — no `onChange` (ADR-0015 does not apply; see Interaction).
- ``in: lower...upper`` → ``min?: number` / `max?: number`` (direct): Default `min=0, max=1` (SwiftUI implicit `0...1`).
- ``label: () -> Label`` → ``label: ReactNode` (required)` (direct): Primary descriptor; accessible name (see Accessibility). String/number renders through the `Text` primitive; a `ReactNode` passes through the `TextLabel` guard unwrapped (ADR-0028).
- ``currentValueLabel: () -> View`` → ``currentValueLabel?: ReactNode`` (direct): Formatted current value. Placement is `variant`-dependent: leading of the line (`accessoryLinear`), centred (`accessoryCircular`/`accessoryCircularCapacity`); absent on `linearCapacity` in the reference.
- ``minimumValueLabel: () -> View`` → ``minimumValueLabel?: ReactNode`` (direct): Rendered only by `accessoryCircular` in the reference (flanks below the current-value label).
- ``maximumValueLabel: () -> View`` → ``maximumValueLabel?: ReactNode`` (direct): Same placement rule as `minimumValueLabel`.
- ``.gaugeStyle(.linearCapacity)` etc.` → ``variant?: "linearCapacity" | "accessoryCircularCapacity" | "accessoryLinear" | "accessoryCircular"`` (direct): `.<control>Style(_:)` → library-wide `variant` (Toggle/Picker/Progress convention); values are verbatim SwiftUI member spelling; default `"linearCapacity"` (SwiftUI's `.automatic` resolves to this on iOS).
- ``.tint(Color)`` → ``tint?: LiquidTintValue` (via `TintableControlProps`)` (direct): Drives the capacity-fill hue; the restricted 13-colour palette plus the `"accent"` system-default sentinel (ADR-0023/0024). No effect on `accessoryLinear` / `accessoryCircular` (see above).
- ``.tint(Gradient)`` → `— (Out of scope)` (direct): Not authored in the demo; Apple's built-in per-tint arc gradient (desaturated→saturated) is likewise not reproduced — ship a solid fill (see Tokens, Out of scope).
- ``markedValueLabels:`` → `— (Out of scope)` (direct): Not exercised; omitted from v1.
- ``Text(value, format:)` inside a label closure` → `(caller's responsibility)` (direct): Value formatting is a *label content* concern, not a Gauge prop — the caller formats `currentValueLabel`'s content itself.
- `*(no analogue — web-only)*` → ``labelProps?: LabelProps`` (web-only): Per-instance typography override seam (ADR-0028, charter §2), spread **last** onto the primary `label` `Text` (`linearCapacity`'s `.lq-gauge-label`, `accessoryCircularCapacity`'s `.lq-gauge-ring-label`) so an explicit value wins over the component's computed default.
- `*(no analogue — web-only)*` → ``valueProps?: LabelProps`` (web-only): Secondary typography-override seam (charter §2 rule 3), spread **last** onto the `currentValueLabel` `Text` (`accessoryLinear`'s `.lq-gauge-current`, `accessoryCircular`'s `.lq-gauge-arc-current`). `minimumValueLabel`/`maximumValueLabel` intentionally have **no** override seam — the charter names only `labelProps` + `valueProps` for Gauge.
