Color
Color picker field with a preset palette and a free-form picker, both storing HSL.
Preview
Usage
import { z } from "zod";
import { AutoForm } from "@vitnode/core/components/form/auto-form";
import { AutoFormColor } from "@vitnode/core/components/form/fields/color";const formSchema = z.object({
color: z.string().default('hsl(240, 80%, 60%)'),
})<AutoForm
formSchema={formSchema}
fields={[
{
id: 'color',
component: (props) => <AutoFormColor {...props} label="Color" />,
},
]}
/>Preset palette
The popover opens with a grid of preset swatches - eight hues (gray, red,
orange, yellow, green, teal, blue and purple) in three tones each. Click one and
the field stores it as an HSL string, for example hsl(215, 81%, 52%). The
swatches form a single radio group, so arrow keys move between them and the
selected one shows a check mark.
The first swatch is the default, and it carries no color of its own. It renders in the current theme's text color and stores an empty value, which is how you say "no color" without leaving the palette.
The three tone rows were picked in OKLCH, so they step evenly to the eye rather than just on paper, and then written out as HSL - the format the picker itself speaks. Every tone keeps at least a 3:1 contrast ratio against both the light and the dark theme background, so a color chosen by an author in one theme stays readable for a reader in the other. A unit test enforces that, so keep it in mind if you fork the palette.
The presets live in @vitnode/core/components/ui/color-presets, and the
standalone swatch grid ships as ColorPresetPicker from
@vitnode/core/components/ui/color-preset-picker if you want the palette
without the free-form picker:
import { ColorPresetPicker } from '@vitnode/core/components/ui/color-preset-picker'
;<ColorPresetPicker value={color} onChange={setColor} />Output format
Both the presets and the free-form picker store an HSL string such as
hsl(215, 81%, 52%), and the two stay in sync - click a preset and the
picker's handle moves onto that color. The text field below takes any CSS
color you paste into it, so the stored value is whatever you type there. Hex,
rgb(...), hsl(...) and oklch(...) all show up on the picker; anything
else leaves it parked on black until you drag it. The picker is powered by
react-colorful and is
lazy-loaded, so its bundle only ships once the popover is opened.
Editor text color
The rich text editor's text color toolbar action uses the same preset palette and nothing else - no free-form picker. Its popover is titled "Text color" and ends with a "Remove color" button, disabled while the selection has no color. The default swatch clears the color the same way.
Props
Prop
Type