ColorSlider
A single-channel color control on a native <input type="range">, pairing a track painting the channel's gradient with a thumb reporting the current value and an <output> for its formatted display.
View code
let channels = { ...OPENING };
<div
mix={[
vstack({ gap: 4, align: "stretch" }),
is("100%"),
maxIs("24rem"),
channelSync(),
on<HTMLDivElement, "ui:color-channel-change">("ui:color-channel-change", (event) => {
channels = { ...channels, ...event.values };
void handle.update();
}),
]}
>
{CHANNELS.map((channel) => (
<div key={channel.name} mix={[vstack({ gap: 1, align: "stretch" })]}>
<div mix={[hstack({ gap: 2, align: "center" })]}>
<Label htmlFor={`preview-channel-${channel.name}`} mix={[is("100%")]}>
{channel.label}
</Label>
<output
htmlFor={`preview-channel-${channel.name}`}
mix={[font("mono"), text("xs"), fg("neutral")]}
>
{Math.round(channels[channel.name])}
{channel.unit}
</output>
</div>
<ColorSlider channel={channel.name} value={channels[channel.name]}>
<ColorSlider.Track hue={channels.hue}>
<ColorSlider.Thumb
id={`preview-channel-${channel.name}`}
data-channel={channel.name}
aria-label={channel.label}
/>
</ColorSlider.Track>
</ColorSlider>
</div>
))}
<div mix={[hstack({ gap: 3, align: "center" })]}>
<ColorSwatch size="lg" shape="rounded" value={swatch} />
<span mix={[font("mono"), text("sm"), weight("medium")]}>{swatch}</span>
</div>
</div>Installation
An ordinary dependency: install it, import the theme once, and import the component where it is used.
npm add @sdxc/uiimport "@sdxc/ui/theme.css";Usage
import { ColorSlider } from "@sdxc/ui";Renders the root host: a <div> stacking its children with a small gap,
resolving the channel, range, and value into component context and
mirroring the channel onto its own data-channel attribute.
Composition
The parts the component publishes, each a static property of the host.
ColorSliderColorSlider.TrackRenders the visual track: aposition: relative<div>painting its whole length with the gradient the nearest ancestor ColorSlider'sdata-channelattribute selects, over a checkerboard backdrop.ColorSlider.ThumbRenders the interactive thumb: a native<input type="range">reset to cover its enclosing ColorSlider.Track's entire box, so drag, arrow-key, and click-to-jump behavior spans the track's whole length.ColorSlider.OutputRenders a live readout: a native<output>reporting the formatted value passed aschildren.
Examples
<ColorSlider channel="alpha" min={0} max={1} defaultValue={1}>
<ColorSlider.Track hue={210}>
<ColorSlider.Thumb aria-label={t("colorPicker.alpha")} />
</ColorSlider.Track>
</ColorSlider>Props
Read from the component's own types, so every prop, every default and every allowed value is listed.
| Prop | Type | Description |
|---|---|---|
channel | "hue" | "saturation" | "lightness" | "alpha" | The single channel this instance edits. |
min? | number | Lower bound of the channel's range. Defaults to DEFAULT_MIN. |
max? | number | Upper bound of the channel's range. Defaults to channel's entry in DEFAULT_MAX_BY_CHANNEL. |
value? | number | Current value, for an instance whose value the consumer tracks itself. |
defaultValue? | number | Starting value, for an instance that never tracks its own value. |
Also accepts everything in TagProps<"div">.
ColorSlider.Track
| Prop | Type | Description |
|---|---|---|
hue? | number | The color's current hue, in degrees 0–360, read into TRACK_HUE_PROPERTY at render time so a "saturation", "lightness", or "alpha" track's gradient matches it. Defaults to DEFAULT_HUE. |
Also accepts everything in TagProps<"div">.
ColorSlider.Thumb
Also accepts everything in Omit<TagProps<"input">, "type" | "role">.
ColorSlider.Output
Also accepts everything in TagProps<"output">.
Types
| Name | Values | What it decides |
|---|---|---|
Channel | "hue" | "saturation" | "lightness" | "alpha" | The single color channel one ColorSlider instance edits. |