sdxc

Type to search, or start from one of these:

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.

210°
84%
56%
100%
hsl(210, 84%, 56%)
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/ui
import "@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.

  • ColorSlider
  • ColorSlider.TrackRenders the visual track: a position: relative <div> painting its whole length with the gradient the nearest ancestor ColorSlider's data-channel attribute 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 as children.

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.

PropTypeDescription
channel"hue" | "saturation" | "lightness" | "alpha"The single channel this instance edits.
min?numberLower bound of the channel's range. Defaults to DEFAULT_MIN.
max?numberUpper bound of the channel's range. Defaults to channel's entry in DEFAULT_MAX_BY_CHANNEL.
value?numberCurrent value, for an instance whose value the consumer tracks itself.
defaultValue?numberStarting value, for an instance that never tracks its own value.

Also accepts everything in TagProps<"div">.

ColorSlider.Track

PropTypeDescription
hue?numberThe color's current hue, in degrees 0360, 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

NameValuesWhat it decides
Channel"hue" | "saturation" | "lightness" | "alpha"The single color channel one ColorSlider instance edits.