Swatch Picker renders a list of colors as round buttons and reports the one that was pressed. It has three props, all of them required, and no state: the palette as an array of strings, the current value, and a change handler.
Anatomy
Section titled “Anatomy”-
Swatch grid the whole control, wrapping its swatches into rows. It has no label of its own, which is what Form Field is for. -
Swatch one color, as a button. Selection cannot be shown in color here, so it is shown as a ring around the chosen one.
The grid wraps into rows at the width of whatever contains it, each swatch is a
24px button filled with its color, and the selected one is marked with a ring
around it. There is no swatch component and no per-swatch options, because
colors is an array of strings and the string is everything the picker knows
about a color.
When to use
Section titled “When to use”The palette is the whole control. colors is a fixed array and there is no
field to type into, which suits a choice the product has already narrowed:
brand colors, or the accent on a hosted flow. A swatch picker has no way to
accept a typed value, so a text input does that job, either beside the picker or
in place of it.
A swatch picker also holds a single value. For choosing several colors at once there is no PDS control, and building one is building a component.
Order the array by hue or lightness, and keep it that way
Section titled “Order the array by hue or lightness, and keep it that way”Mixing brand colors with arbitrary ones empties the constraint the picker exists to express. Order the array by hue or by lightness and keep it that way between renders: the reader is scanning for a color and there is nothing else in the grid to scan by, so a familiar position is the only landmark on offer.
Pass full six-digit hex
Section titled “Pass full six-digit hex”The strings in colors go straight into background-color. White has to be
special-cased to be visible at all, and PDS does that by comparing the string to
#FFFFFF and swapping the white border for a hairline one. The comparison is on
the string, so #fff, white and an rgb() triple all render a white circle
with a white border on a white surface. The source says the same, and says it is
a hack that handles exact white only, so near-white colors have the problem
too.
Accessibility
Section titled “Accessibility”Assume the reader hears a hex code
Section titled “Assume the reader hears a hex code”Each swatch is a <button> with the color string as its title and nothing
inside it, so its accessible name is “#3F48FD”. There is no prop for naming a
color, and PDS’s own test file records the problem as unsolved. A reader using a
screen reader gets the palette as a list of hex codes in the order you passed
them.
So a swatch picker should not be the only route to a color that matters.
Count on every swatch being a tab stop
Section titled “Count on every swatch being a tab stop”The picker is a plain div with no role: no radiogroup, no roving tabindex, no
arrow keys. Tab therefore stops on all ten swatches of a ten-color palette,
which is one more reason to keep a palette short.
Nothing marks a swatch unavailable, either. There is no disabled on the
picker or on a swatch, and no way to take one out of the tab order, so a color
that must not be chosen has to be left out of colors.
A form field gives the picker a visible label and nothing more
Section titled “A form field gives the picker a visible label and nothing more”An aria-label passed to Swatch Picker lands on that plain div, where a
generic element takes no accessible name and the label has nowhere to attach.
Wrap the picker in Form Field for a visible label above
it. Note what that does and does not buy: the label is visible text, and with no
input underneath it there is nothing for it to be programmatically associated
with.
Content
Section titled “Content”Print the token name where precision matters
Section titled “Print the token name where precision matters”PDS already puts the hex in a browser tooltip on every swatch, so a picker whose
reader needs Core / Purple / 600 has to print it outside the grid. The field
label and its helper text are the place for that, and the rules for both are on
Writing.
| Name | Type |
|---|---|
valuerequired |
|
onChangerequired |
|
colorsrequired |
|
Omit<ComponentPropsWithoutRef<‘div’>, ‘onChange’>.Was this page helpful?