ImageSwitch
A boolean control that displays one of two images based on state, perfect for on/off switches and buttons with custom bitmap graphics.
ImageSwitch is a boolean control that displays one of two images based on the boolean value. It shares the same layout, parameter model, interaction, and accessibility as other controls (vector, raster, and control primitives); see the Raster introduction.
The image displayed is determined by the boolean value:
false(normalized 0.0) displaysimageHrefFalsetrue(normalized 1.0) displaysimageHrefTrue
Note:
No Theming Support: This component does NOT support themable props (color, roundness, thickness) as visuals are entirely determined by the image content.
Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
value | boolean | — | Required | Current value of the control |
onChange | (event: AudioControlEvent<boolean>) => void | — | Optional | Handler for value changes |
latch | boolean | false | Optional | Whether the button operates in latch (toggle) mode or momentary mode |
label | string | — | Optional | Label displayed below the component |
frameWidth | number | — | Required | Width of the viewBox (determines viewBox width) |
frameHeight | number | — | Required | Height of the viewBox (determines viewBox height) |
imageHrefFalse | string | — | Required | URL to the image for false/off state |
imageHrefTrue | string | — | Required | URL to the image for true/on state |
adaptiveSize | boolean | false | Optional | Whether the component stretches to fill its container |
size | "xsmall" | "small" | "normal" | "large" | "xlarge" | normal | Optional | Size of the component |
parameter | BooleanParameter | — | Optional | Audio Parameter definition (Model). If provided, overrides label/latch from ad-hoc props |
Basic Usage
ImageSwitch requires two image URLs (one for off state, one for on state) and frame dimensions:
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function BasicImageSwitchExample() {
const [isOn, setIsOn] = useState(false);
return (
<ImageSwitch
value={isOn}
latch={true}
label="Power"
size="large"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setIsOn(e.value)}
/>
);
}Modes of Operation
Latch Mode (Toggle)
In latch mode, the button toggles between pressed and released states:
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function LatchImageSwitchExample() {
const [isOn, setIsOn] = useState(false);
return (
<ImageSwitch
value={isOn}
latch={true}
label="Favorite"
size="large"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setIsOn(e.value)}
/>
);
}Momentary Mode
In momentary mode, the button is only active while being pressed:
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function MomentaryImageSwitchExample() {
const [isPressed, setIsPressed] = useState(false);
return (
<ImageSwitch
value={isPressed}
latch={false}
label="Record"
size="large"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setIsPressed(e.value)}
/>
);
}Image Selection
The component displays different images based on the boolean value:
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function ImageSelectionExample() {
const [isOn, setIsOn] = useState(false);
return (
<ImageSwitch
value={isOn}
latch={true}
label="Switch"
size="large"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setIsOn(e.value)}
/>
);
}Parameter Model
Use a parameter model for integration with audio parameter systems. The following example uses ad-hoc props; with the full library you would use createBooleanParameter and the parameter prop:
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function ImageSwitchParameterModelExample() {
const [value, setValue] = useState(false);
return (
<ImageSwitch
label="Favorite"
latch={true}
value={value}
size="large"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setValue(e.value)}
/>
);
}Adaptive Sizing
The ImageSwitch component supports both fixed sizes and adaptive sizing. By default, the size of the component is driven by the Size System and their size attribute:
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function ImageSwitchSizingExample() {
const [v1, setV1] = useState(false);
const [v2, setV2] = useState(false);
const [v3, setV3] = useState(false);
const [v4, setV4] = useState(false);
return (
<div className="flex gap-4 items-center flex-wrap">
<ImageSwitch
value={v1}
latch={true}
label="Small"
size="small"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setV1(e.value)}
/>
<ImageSwitch
value={v2}
latch={true}
label="Normal"
size="normal"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setV2(e.value)}
/>
<ImageSwitch
value={v3}
latch={true}
label="Large"
size="large"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setV3(e.value)}
/>
<ImageSwitch
value={v4}
latch={true}
label="XLarge"
size="xlarge"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setV4(e.value)}
/>
</div>
);
}Adaptive sizing allows the component to adapt to the size of its parent container, adjusting its dimensions intelligently without causing distortion (scaleToFit display mode). The fill display mode makes the component fill the entire container, potentially distorting it.
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function ImageSwitchAdaptiveSize() {
const [wideVal, setWideVal] = useState(false);
const [tallVal, setTallVal] = useState(false);
const [distortedVal, setDistortedVal] = useState(false);
return (
<div className="flex gap-6 items-center flex-wrap">
<div className="w-32 h-12 border rounded-lg p-2">
<ImageSwitch
value={wideVal}
onChange={(e) => setWideVal(e.value)}
latch={true}
adaptiveSize={true}
label="Wide"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
/>
</div>
<div className="w-12 h-32 border rounded-lg p-2">
<ImageSwitch
value={tallVal}
onChange={(e) => setTallVal(e.value)}
latch={true}
adaptiveSize={true}
label="Tall"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
/>
</div>
<div className="w-24 h-20 border rounded-lg p-2">
<ImageSwitch
value={distortedVal}
onChange={(e) => setDistortedVal(e.value)}
latch={true}
adaptiveSize={true}
displayMode="fill"
label="Distorted"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
/>
</div>
</div>
);
}Common Use Cases
Favorite/Star Button
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function FavoriteButtonExample() {
const [isFavorite, setIsFavorite] = useState(false);
return (
<ImageSwitch
value={isFavorite}
latch={true}
label="Favorite"
size="large"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setIsFavorite(e.value)}
/>
);
}Power Switch
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function PowerSwitchExample() {
const [isOn, setIsOn] = useState(false);
return (
<ImageSwitch
value={isOn}
latch={true}
label="Power"
size="large"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setIsOn(e.value)}
/>
);
}Momentary Record Button
import { useState } from "react";
import { ImageSwitch } from "@cutoff/audio-ui-react";
export default function RecordButtonExample() {
const [isRecording, setIsRecording] = useState(false);
return (
<ImageSwitch
value={isRecording}
latch={false}
label="Record"
size="large"
frameWidth={100}
frameHeight={100}
imageHrefFalse="/images/demo/star-off.png"
imageHrefTrue="/images/demo/star-on.png"
onChange={(e) => setIsRecording(e.value)}
/>
);
}Image Requirements
- Format: Any image format supported by browsers (PNG, JPG, SVG, etc.)
- Dimensions: The
frameWidthandframeHeightprops determine the viewBox dimensions - Aspect Ratio: Images will be scaled to fit the viewBox while preserving aspect ratio
- States: Provide two separate images for off and on states
Image Selection Logic
The component selects images based on the boolean value:
value === false→ DisplaysimageHrefFalsevalue === true→ DisplaysimageHrefTrue
The selection is immediate and does not animate between states.
Next Steps
- Explore ImageKnob for continuous rotary controls
- Learn about ImageRotarySwitch for discrete rotary controls
- Check out the playground for interactive examples