Brand Color Input

A colour field that names the nearest brand token and offers a snap when a value is a hair off, so near-miss brand colours don't ship.

StopsBrand colour off by a hex digit

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/brand-color-input.json

The files land in your project. They're yours to edit.

Usage

brand-color-input-usage.tsx
import { BrandColorInput } from "@/components/ui/brand-color-input"

<BrandColorInput label="Button background" defaultValue="#1E40AE" palette={palette} />

What it catches

  • Values a hair away from a palette token, with a snap to the token
  • The letter O typed for zero, and stray characters from a paste
  • A digit too many or too few
  • Alpha hidden in 4- and 8-digit hex
  • Android #AARRGGBB order, which CSS reads as a different colour

Props

BrandColorInput props
PropTypeDefault
label

Visible label.

string"Colour"
value

Controlled text.

string—
defaultValue

Initial text when uncontrolled.

string""
onValueChange

Called with the text on every change, including one-tap fixes.

(value: string) => void—
onColorChange

Called with the canonical hex the text renders as, or null when it can't be read.

(hex: string | null) => void—
palette

Brand tokens by name, e.g. { "blue-700": "#1e40af" }.

Record<string, string>NO_PALETTE
messages

Override any message.

Partial<typeof BRAND_COLOR_MESSAGES>—
snapLabel

Label of the one-tap fix that snaps to a token ("Use blue-700").

string"Use"
fixLabel

Label of the other one-tap fixes.

string"Fix to"

* required. Also accepts the native props of <input> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Visible <label>; the hint is linked with aria-describedby and is aria-live="polite"
  • aria-invalid when the value can't be read
  • Fix buttons have aria-labels naming the token and value; the swatch is aria-hidden
  • The flash on fix is skipped with prefers-reduced-motion

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

  • Only knows the palette you pass; with no palette it checks syntax only
  • "Close" is a perceptual distance threshold, so an intentional near-shade can be flagged

What it stops

Brand colour off by a hex digit

Also known as

hex color · brand color · color input · design tokens · theme · palette · oklab · tailwind colors

Field type

Dependencies

Pairs well with