A labelled group of color swatches bound to a single hex value. Built on Base UI's RadioGroup and Radio.Root; renders a label, the swatches (each an inner ColorRadio), and optional helper/error text.
Use @uxf/ui/color-radio-group for a controlled color-swatch group outside a form, where you own value and onChange.
Use @uxf/form/color-radio-group inside a @uxf/form form — that twin wires react-hook-form (useController), consumes the form context (disabled/read-only, required validation), and derives its value from the field.
import { ColorRadioGroup } from "@uxf/ui/color-radio-group";
import { HexColor } from "@uxf/ui/types";
import { useState } from "react";
const options = [
{ value: "#ff0000", label: "Red" },
{ value: "#00ff00", label: "Green" },
{ value: "#0000ff", label: "Blue" },
] satisfies { value: HexColor; label: string }[];
function Example() {
const [value, setValue] = useState<HexColor | null>("#ff0000");
return (
<ColorRadioGroup
id="colors"
label="Pick a color"
name="color"
onChange={setValue}
options={options}
value={value}
/>
);
}
Extends FormControlProps<HexColor | null> (from @uxf/ui/types). HexColor is `#${string}`.
| Prop | Type | Default | Description |
|---|---|---|---|
label | ReactNode | — (required) | Group label. |
name | string | — (required) | Field name. |
options | ColorRadioGroupOption[] | — (required) | Swatches to render. |
value | HexColor | null | — (required) | Hex value of the selected swatch. |
onChange | (value: HexColor | null) => void | — (required) | Called with the selected hex value. |
helperText | ReactNode | — | Text shown below the swatches; styled as an error when isInvalid. |
hiddenLabel | boolean | false | Visually hide the label (kept for accessibility). |
id | string | — | Root id; also used to build the error-message id. |
className | string | — | Extra class on the root element. |
style | CSSProperties | — | Inline style on the root element. |
isDisabled | boolean | false | Disables the group and all swatches. |
isInvalid | boolean | false | Error styling on the group and helper text. |
isRequired | boolean | false | Marks the label as required. |
The inherited isFocused, isReadOnly, onFocus, and onBlur are part of the shared FormControlProps shape but are not wired by this UI component; they are consumed by the @uxf/form twin. Unlike RadioGroup, ColorRadioGroup has no variant or radioSize props.
ColorRadioGroupOption — one entry of options:
| Field | Type | Description |
|---|---|---|
value | `#${string}` | Hex color; both the option value and the swatch color. |
label | ReactNode | Accessible label for the swatch. |
disabled | boolean | Disable this single swatch. |
No theme variants or sizes. States are driven by props: the selected swatch shows a check icon, isDisabled dims the swatches, and isInvalid applies error styling to the helper text.
Enter on a focused option submits the surrounding form through requestSubmit(), like Enter on a native radio
button. Enter on a link inside an option's label only follows the link.
Import the stylesheets once in your global CSS (the group renders ColorRadio, which uses the check icon):
@import url("@uxf/ui/css/icon.css");
@import url("@uxf/ui/css/color-radio.css");
@import url("@uxf/ui/css/color-radio-group.css");
form-component.css provides the helper/error text styling (.uxf-helper-text); import it if you use helperText or validation:
@import url("@uxf/ui/css/form-component.css");
Also requires the global @uxf/ui token layer, set up once per app — see @uxf/ui setup.