Skip to main content
BM

ColorField

A color input: a native color picker and a hex field under one legend, with optional suggested swatches.

View source on GitHub

Action color

Buttons and links use it.

#b37500#1c87a5#5b3fa6#2a8556
ColorFieldExample.tsx
import { ColorField } from "@/components/ColorField";

export function ColorFieldExample() {
  return (
    <ColorField
      label="Action color"
      hint="Buttons and links use it."
      defaultValue="#b37500"
      swatches={[
        { value: "#b37500", name: "Gold 600" },
        { value: "#1c87a5", name: "Cyan 500" },
        { value: "#5b3fa6", name: "Violet 600" },
        { value: "#2a8556", name: "Green 600" },
      ]}
    />
  );
}

Examples

Hex only

Background

Controlled

Second accent
#5b3fa6#4a3290#3d2875

Stored value: #5b3fa6

Invalid hex

Accent

Type "#12" and leave the field: the error shows, and the last valid color stays.

Disabled

Status color
#c8372c

Props

Any native prop not listed here goes to the root element unchanged.

Native <fieldset> props (className, id, ref and the rest) go to the fieldset. Hex is a template type for "#…" strings; the value is always lowercase "#rrggbb". The hex field reads "#rgb", "#rrggbb", or either without "#", in any case.

ColorField props
PropTypeDefaultDescription
labelstring—The visible legend. It names the group and the color picker. Required by the type.
hintReactNode—Help text under the legend, read as the group's description.
valueHex—Controlled value, "#rrggbb". Pair with onValueChange.
defaultValueHex"#000000"Uncontrolled initial value.
onValueChange(value: Hex) => void—Called with each new valid value, lowercase "#rrggbb": from the picker, a swatch, or hex text as soon as it parses.
swatchesreadonly { value: Hex; name: string }[]—Suggested colors, shown as buttons named by name, with the hex as their description. The one matching the value is pressed.
swatchesLabelstring"Suggested colors"The swatch group's accessible name.
disabledbooleanfalseDisables the whole fieldset: the picker, the hex field and the swatches.

Component tokens

ColorField component tokens
TokenCopyDescriptionAliasesLightDarkPreview
--component-color-field-gapSpace between the legend, hint, controls and swatches, and between swatches.space.stack.sm0.5remfrom space.20.5remfrom space.2
--component-color-field-swatch-sizeSwatch button size: at least 24px (WCAG 2.5.8).size.icon.lg1.5remfrom size.61.5remfrom size.6
--component-color-field-swatch-borderSwatch outline, so a swatch close to the surface still has a 3:1 boundary.color.border.strong#6d7e90from color.gray.500#818b9efrom color.slate.400
--component-color-field-swatch-radiusSwatch corner radius.radius.control4pxfrom radius.44pxfrom radius.4
--component-color-field-picker-sizeThe color picker's size: the height of the small hex field beside it.size.control.sm2remfrom size.82remfrom size.8
--component-color-field-picker-borderColor picker outline.color.border.strong#6d7e90from color.gray.500#818b9efrom color.slate.400
--component-color-field-picker-radiusColor picker corner radius.radius.control4pxfrom radius.44pxfrom radius.4
--component-color-field-legend-textThe legend.color.text.default#17202bfrom color.gray.900#fffffffrom color.gray.0

Accessibility

  • A <fieldset> whose <legend> names the group, and the native color picker inside it through aria-labelledby. The hex field is a TextField labelled "Hex", so the group reads as, for example, "Action color, group", then "Hex, edit text".
  • The value is always shown as hex text, so it never relies on color alone.
  • Hex text is applied as soon as it's a valid color. If it isn't valid when the field loses focus, the field shows an error with a warning icon, is marked invalid, and the last valid color stays.
  • Each swatch is a toggle button named by its swatch name, with the hex as its description and both in a tooltip. The one matching the value is pressed, shown by a ring around it, outside a gap, so it reads on light and dark swatches alike, and not by color. In forced colors the pressed swatch gets a thick system-color border, apart from the focus outline.
  • Swatches are 24px (WCAG 2.5.8), and swatch and picker outlines are checked to 3:1 against the surfaces in both themes, so a color close to the page still has a visible edge. In forced colors the colors themselves stay, with system-color outlines.
ColorField keyboard
KeyAction
TabMoves to the color picker, then the hex field, then each swatch.
Enter / SpaceOn the picker, opens the browser's color dialog. On a swatch, sets its color.