Number Gauge
Scrub a number directly with a compact, draggable gauge.

use blinc_cn as cn;
use blinc_core::reactive::{Signal, computed};
use blinc_layout::{binding::IntoReactive, prelude::*};
pub fn number_gauge_demo(number: Signal<f64>, disabled: Signal<bool>) -> Div {
div()
.class("demo-stack")
.child(cn::label("Volume"))
.child(
cn::number_gauge(number)
.range(0.0..=100.0)
.step(1.0)
.w(256.0)
.disabled(disabled),
)
.child(bound_text(computed(move |g| format!("{:.0}%", g.get(number).unwrap_or(0.0)))).class("demo-caption"))
}
fn bound_text(value: impl IntoReactive<String>) -> Text {
Text::bound(value.into_reactive())
}
@layer components {
.cn-number-gauge:focus-visible {
outline: 2px solid var(--focus-ring);
outline-offset: 2px;
}
.cn-number-gauge {
border-color: var(--border);
background: var(--input-bg);
color: var(--text-primary);
cursor: ew-resize;
outline: 2px solid transparent;
outline-offset: 2px;
transition: border-color var(--duration-fast) var(--ease-state);
}
.cn-number-gauge--sm {
border-radius: var(--radius-sm);
}
.cn-number-gauge--md,
.cn-number-gauge--lg {
border-radius: var(--radius-default);
}
.cn-number-gauge:hover:not(:disabled) {
border-color: var(--border-hover);
}
.cn-number-gauge[data-focus-visible] {
outline-color: var(--focus-ring);
}
.cn-number-gauge-fill {
background: color-mix(in srgb, var(--primary) 22%, var(--input-bg));
}
.cn-number-gauge-rest {
background: transparent;
}
.cn-number-gauge-thumb {
background: color-mix(in srgb, var(--primary) 30%, var(--input-bg));
color: var(--primary);
transition: background-color var(--duration-fast) var(--ease-state);
}
.cn-number-gauge:hover:not(:disabled) > .cn-number-gauge-thumb,
.cn-number-gauge:active:not(:disabled) > .cn-number-gauge-thumb,
.cn-number-gauge[data-state="dragging"] > .cn-number-gauge-thumb,
.cn-number-gauge[data-focus-visible] > .cn-number-gauge-thumb {
background: color-mix(in srgb, var(--primary) 44%, var(--input-bg));
}
.cn-number-gauge:disabled {
color: var(--text-tertiary);
cursor: default;
}
.cn-number-gauge:disabled > .cn-number-gauge-fill {
background: var(--input-bg-disabled);
}
.cn-number-gauge:disabled > .cn-number-gauge-thumb {
background: var(--border-secondary);
color: var(--text-tertiary);
}
.cn-number-gauge-layer[data-endpoint="lower"] > .cn-number-gauge-fill {
background: var(--input-bg);
}
.cn-number-gauge:hover:not(:disabled) > .cn-number-gauge-layer > .cn-number-gauge-thumb,
.cn-number-gauge:active:not(:disabled) > .cn-number-gauge-layer > .cn-number-gauge-thumb,
.cn-number-gauge[data-state="dragging"] > .cn-number-gauge-layer > .cn-number-gauge-thumb,
.cn-number-gauge[data-focus-visible] > .cn-number-gauge-layer > .cn-number-gauge-thumb {
background: color-mix(in srgb, var(--primary) 44%, var(--input-bg));
}
.cn-number-gauge:disabled > .cn-number-gauge-layer > .cn-number-gauge-fill {
background: var(--input-bg-disabled);
}
.cn-number-gauge:disabled > .cn-number-gauge-layer > .cn-number-gauge-thumb {
background: var(--border-secondary);
color: var(--text-tertiary);
}
}
Usage and properties
Scrub a number directly with a compact, draggable gauge. Apply CSS after the component layer to restyle the documented parts.
Use the installation guide to add blinc_cn and its component stylesheet. Create the fixture bindings once, and return the demo from your UI builder. Values marked Bound accept Signal/Computed sources where the API supports them; structural options configure the component at construction.
| Property | Type | Update model | This example |
|---|---|---|---|
value | Signal<f64> | Bound | 42 |
range / step | RangeInclusive<f64> / f64 | Construction | 0..=100 / 1 |
Keyboard and interaction
Tab focuses the gauge. Arrow keys, Page Up and Page Down, Home and End move it; values snap to the step. The wheel also steps it. :focus-visible marks keyboard focus.
Customizing it
Add application CSS after the default component layer. These selectors are the restyling surface for this component:
.cn-number-gauge.cn-number-gauge-fill.cn-number-gauge-thumb.cn-number-gauge-grip.cn-number-gauge-rest.cn-number-gauge-value
Theme and component variables: --primary, --text-primary, --text-secondary, --surface, --border, --radius-default, --duration-fast, --ease-state.
Built-in themes
The Live theme control installs Blinc's own theme bundles, including their colours, focus rings, corner shapes and motion tokens.
pub fn theme_bundle_for(name: &str) -> blinc_theme::ThemeBundle {
match name {
"restrained" => blinc_theme::RestrainedTheme::bundle(),
"expressive" => blinc_theme::ExpressiveTheme::bundle(),
_ => blinc_theme::HybridTheme::bundle(),
}
.with_css(blinc_cn::cn_styles::CN_STYLES)
}Download the default widget and component stylesheets. Sample assets and licenses are available in the asset guide.
Documentation
From the canonical component guide.
A number shown as a fill, with the value written over it:
let opacity = ctx.use_signal(64.0);
cn::number_gauge(opacity)
.range(0.0..=100.0) // the default
.step(1.0) // the default
.size(GaugeSize::Medium) // Small, Medium, Large
.format(|n| format!("{n} %"))
.disabled(locked) // a bool, Signal or Computed
.on_change(|n| println!("opacity: {n}"))
Drag it, click where you want it, or scroll over it. After a click the arrow keys, Page Up/Down and Home/End move it too. Values snap to the step.
The gauge is as wide as its longest value needs, so it doesn't change width
as you drag; .w(px) sets a width instead.
Number Range Gauge
Two ends on one gauge, held in one Signal<RangeInclusive<f64>>:
let band = ctx.use_signal(18.0..=24.0);
cn::number_range_gauge(band)
.range(10.0..=30.0)
.step(0.5)
.format(|r| format!("{}–{} °C", r.start(), r.end()))
Clicking or scrolling moves the nearer end. The ends never cross.
Styling
Both are a .cn-number-gauge (the range one also .cn-number-range-gauge)
holding .cn-number-gauge-fill, .cn-number-gauge-thumb and
.cn-number-gauge-rest, with the value in .cn-number-gauge-value. The range
gauge puts each face in a .cn-number-gauge-layer with
data-endpoint="lower" or "upper". The gauge has data-state="dragging"
during a drag, data-focus-visible once a key has moved it, and disabled.
Colours, the border, the radius per size (.cn-number-gauge--sm, --md,
--lg) and the cursor are rules of CN_STYLES:
.my-gauge > .cn-number-gauge-fill { background: color-mix(in srgb, #16a34a 25%, var(--input-bg)); }
.my-gauge > .cn-number-gauge-thumb { color: #16a34a; }
cn::number_gauge(opacity).class("my-gauge")
Platforms and version
The component API is available in Blinc 0.6.0. The Live example runs in a dedicated worker and requires a compatible GPU surface. Preview and Code remain available when Live cannot start. The canvas has a descriptive label; a full screen-reader DOM mirror is not provided. The gallery integration is based on revision e2e55c24e078.
Recordings and live demos use the default Hybrid theme with bundled Noto Sans. The recording uses a 560 × 320 logical viewport at twice that resolution. Live follows its container and actual display density. Source base revision · Exact build source · Artifact versions and checksums · Font license.