Skip to main content

Usage

import "@ambientcss/css/ambient.css";
import "@ambientcss/components/styles.css";

import {
AmbientButton,
AmbientFader,
AmbientKnob,
AmbientPanel,
AmbientProvider,
AmbientSlider,
AmbientSwitch
} from "@ambientcss/components";

export function Example() {
return (
<AmbientProvider
theme={{
lightX: -1,
lightY: -1,
keyLight: 0.9,
fillLight: 0.72,
lightHue: 220,
lightSaturation: 14,
highlightColor: "#7dd3fc",
lumeHue: 190
}}
>
<AmbientPanel>
<AmbientButton>Play</AmbientButton>
<AmbientSwitch label="Bypass" defaultValue />
<AmbientKnob value={40} onChange={(next) => console.log("knob", next)} />
<AmbientSlider value={28} onChange={(next) => console.log("slider", next)} />
<AmbientFader value={72} onChange={(next) => console.log("fader", next)} />
</AmbientPanel>
</AmbientProvider>
);
}

Controlled vs uncontrolled

Every control takes the same pair. Pass value to drive it from outside, or defaultValue (or neither) to let it hold its own state. onChange fires either way, so you can read an uncontrolled control without taking it over.

Presets and mechanisms

The components above are presets: a mechanism with a set of parts already chosen. Underneath, each one is a mechanism that owns the kinematics, the value and the ARIA, and knows nothing about how the control looks.

If you want a control that looks like yours rather than like ours, reach for the mechanism and give it parts — see Composing controls.

Accessibility

Controls expose slider/switch semantics and ARIA values. Prefer providing label for clear assistive text.

The control root owns the role, the tab stop and the keyboard handler, so parts are presentational by contract: a part must not contain a focusable element or an interactive role. In development, a check warns if one does.