COMPONENTS/INPUTS
Slider.
Find the right amount.
In practice
Compose Control, Track, Indicator and Thumb. Set aria-label on SliderThumb. Supports min, max and step for one numeric value.
Installation
Install Coal once. Components and TypeScript declarations are included. React 19 and React DOM 19 are peer dependencies.
Terminal · local package
npm install http://localhost:3100/downloads/chlohal-coal-ui-0.5.0.tgzThis installs the local package. It is not yet published on npm. See installation for stylesheet setup and integration.
Usage
example.tsx
"use client";
import * as React from "react";
import "@chlohal/coal-ui/styles.css";
import { Slider, SliderControl, SliderTrack, SliderIndicator, SliderThumb, SliderValue } from "@chlohal/coal-ui";
export default function Example() {
return (<Slider defaultValue={64}>
<div>
<span>Just enough</span>
<SliderValue />
</div>
<SliderControl>
<SliderTrack>
<SliderIndicator />
<SliderThumb aria-label="Intensity"/>
</SliderTrack>
</SliderControl>
</Slider>);
}
Source
The original Coal implementation. Use the package export to integrate it.
packages/react/src/slider.tsx
"use client";
import * as React from "react";
import { cn, useValue, useRequired } from "./internal.js";
const Context = React.createContext<
| {
value: number;
set: (value: number) => void;
min: number;
max: number;
step: number;
name?: string;
disabled?: boolean;
}
| undefined
>(undefined);
export type SliderProps = Omit<
React.ComponentPropsWithRef<"div">,
"defaultValue"
> & {
value?: number;
defaultValue?: number;
onValueChange?: (value: number) => void;
min?: number;
max?: number;
step?: number;
name?: string;
disabled?: boolean;
};
export function Slider({
value,
defaultValue = 0,
onValueChange,
min = 0,
max = 100,
step = 1,
name,
disabled,
children,
className,
...props
}: SliderProps) {
const [v, set] = useValue(value, defaultValue, onValueChange);
return (
<Context.Provider value={{ value: v, set, min, max, step, name, disabled }}>
<div className={cn("coal-slider", className)} {...props}>
{children}
</div>
</Context.Provider>
);
}
export function SliderControl(props: React.ComponentPropsWithRef<"div">) {
return <div {...props} />;
}
export function SliderTrack(props: React.ComponentPropsWithRef<"div">) {
return <div {...props} />;
}
export function SliderIndicator(_props: React.ComponentPropsWithRef<"span">) {
void _props;
return null;
}
export function SliderThumb({
className,
onChange,
...props
}: React.ComponentPropsWithRef<"input">) {
const c = useRequired(Context, "SliderThumb");
return (
<input
type="range"
min={c.min}
max={c.max}
step={c.step}
name={c.name}
disabled={c.disabled}
value={c.value}
className={cn("coal-slider-input", className)}
{...props}
onChange={(e) => {
onChange?.(e);
if (!e.defaultPrevented) c.set(e.target.valueAsNumber);
}}
/>
);
}
export function SliderValue(props: React.ComponentPropsWithRef<"output">) {
const c = useRequired(Context, "SliderValue");
return <output {...props}>{c.value}</output>;
}
Accessibility checklist
- Provide an accessible name for controls, including icon-only buttons.
- Check keyboard navigation, visible focus and disabled states in your application.
- Do not rely on color alone to communicate status.