curated_colors
Curated Colors replaces color select lists and free-form color pickers with a visual swatch popover backed by named, exportable palettes. Editors choose from an approved set of named colors organized into groups and see a live preview of their selection before saving.
Palettes are stored as config, so they're exportable and tracked in git like any other configuration. The stored value is a key (brand-primary, not #0678be), keeping actual color values in your stylesheet. Brand updates become CSS changes rather than content migrations.
An example submodule (curated_colors_example) ships with the module and includes a sample palette config, a working SDC component, and a CSS class example showing the full pattern.
Features
Palettes
Palettes are config entities managed at /admin/config/content/curated-colors. Each color entry has a machine key, a human-readable label, an optional hex value for the admin preview, and an optional custom CSS string for gradients or anything a single hex can't express. Colors can be organized into named groups and dragged to reorder, with live preview swatches in the editor.
Field type
The curated_color field type stores a single color key. Field settings let you choose a palette and optionally restrict the picker to specific groups within it.
The field exposes computed properties for use in Twig templates and SDC props:
Property Returnsvalue
The stored key, e.g. brand-primary
hex
The hex value from the palette entry
style
The custom CSS string, if one was set
label
The human-readable color name
css
Custom CSS if set, otherwise background:"#hex", ready to use in a style attribute
Field widget
The picker widget replaces the default select with a swatch-based popover, with colors organized into labeled group sections. The popover is viewport-aware and positions itself to stay on screen.
Form element
The picker is also available as a standalone Form API element for use on non entity forms:
$form['color'] = [ '#type' => 'curated_color_picker', '#title' => $this->t('Accent color'), '#palette_id' => 'brand', '#allowed_groups' => ['primary', 'secondary'], '#default_value' => '', ];
Canvas integration
With the Canvas module installed, any SDC string prop annotated with x-curated-color-palette uses the swatch picker in the component editor, whether the prop is bound to a field or set as a static value.
# my_component.component.yml props: properties: color: type: string x-curated-color-palette: brand
Formatters
Two field formatters are included: a swatch chip with label, and a plain value formatter that can output the key, hex, label, or CSS string.
Using color keys in your theme
Keep color values out of the database. Use the stored key as a BEM modifier class and let the stylesheet own the color:
.my-component--brand-primary .my-component__accent { background: #0678be; } .my-component--brand-warm .my-component__accent { background: linear-gradient(…); }
For inline styles, SVG fills, or email templates where a CSS class won't work, the computed css property returns a background declaration ready to use in a style attribute. The example submodule (curated_colors_example) shows both approaches with a working SDC component.
Beyond colors: style selectors
The underlying mechanism is a constrained key picker with a visual chooser, which works for any set of options that have visual meaning.
Button style variants are a common example. Instead of a palette of hex values, define a palette of style options:
Key Label Hex (preview) Custom CSSbtn-primary
Primary
#0678be
—
btn-secondary
Secondary
#6c757d
—
btn-outline
Outline
—
border: 2px solid #0678be; color: #0678be; background: transparent;
btn-danger
Danger
#dc3545
—
The same approach works for card styles, hero text treatments, section backgrounds, icon themes, and any other field where editors are picking a visual variant. Palette groups let you combine related variants (button-style, card-style, hero-style) in one palette and use the field's group restriction to show only what's relevant for each field.