OKLCH-native colour picker: a gamut-aware lightness and chroma plane, RGB and OKLCH tabs whose rows show their own colour ramp on hover, a field that accepts hex, rgb() or oklch(), screen eyedropper and preset swatches.
Adds the component and everything it depends on to your project.
npx shadcn add https://ui.beste.co/component/r-base/color-pickerNew here? Read the installation guide.
The import and the props worth knowing about, in one place.
import { ColorPicker } from "@/components/beste/component/color-picker";
// Hex in, hex out — the drop-in case
<ColorPicker color={color} onChange={setColor} />
// Emit oklch() and keep the expensive work off the drag path. The OKLCH tab
// opens selected, since that is the notation being written back.
<ColorPicker
color={brand}
format="oklch" // "hex" (default) | "oklch" | "rgb"
onChange={setBrand} // every adjustment
onChangeComplete={(value) => console.log("persist", value)} // once per gesture
/>
<ColorPicker
color={overlay}
onChange={setOverlay}
alpha // adds the alpha row, emits 8-digit hex
// Presets are opt-in; without this prop the picker shows no swatch row at all.
swatches={["#171717", "#64748b", "#6366f1", "#0ea5e9", "#14b8a6", "#22c55e", "#f59e0b", "#ef4444"]}
/>
// Compact: no tabs, so plane and hue only, and no text field either
<ColorPicker color={color} onChange={setColor} oklch={false} hideInput />Turn the props on the right; the snippet under them is what you would write to get what you see.
import { ColorPicker } from "@/components/beste/component/color-picker";
<ColorPicker
color="#6366f1"
/>Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.
| Arrow keys on the plane | Move the swatch. Up and Down change lightness while keeping the colour as saturated as it was; Left and Right change chroma. |
|---|---|
| Shift + Arrow | A coarse step, for crossing the plane without dragging. |
| Arrow keys on a slider | One step of hue or alpha — the sliders are the inspector's own rows, so they answer everything those answer. |
| Enter in the field | Commit what was typed. An unparseable value is marked invalid rather than silently dropped. |
| Escape in the field | Throw the draft away and put the committed colour back. |
| The eyedropper | Offered only where the browser has `EyeDropper`; picks a colour from anywhere on screen. |
Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
color | string | — | Current colour. Hex, `rgb()`/`rgba()` and `oklch()` are all understood. |
onChange | (color: string) => void | — | Fires on every adjustment, in `format`. |
onChangeComplete | (color: string) => void | — | Fires once an adjustment is finished — a drag release, a committed edit, a swatch click. Use it for work too expensive to run per frame. |
format | "hex" | "oklch" | "rgb" | "hex" | Notation the callbacks emit. |
alpha | boolean | — | Show the alpha row and carry an alpha channel through `format`. |
oklch | boolean | true | Offer the RGB/OKLCH tabs. The OKLCH one adds lightness and chroma rows for precise control and writes the value as `oklch(...)`; the choice only affects what is shown and typed, never what `format` emits. Turn it off for a compact picker: plane, hue and the field. |
swatches | string[] | — | Preset colours offered under the picker, in any supported notation. |
hideInput | boolean | — | Hide the text field that accepts and displays the value. |
className | string | — | |
aria-label | string | — | Accessible name for the lightness/chroma plane. |
| Actions | ||||||
|---|---|---|---|---|---|---|
A Amara Okaforamara@northwind.io | Scale | Active | $4,820 | Jan 4, 2026 | ||
D Diego Santosdiego@lumen.app | Starter | Trial | $0 | Feb 18, 2026 | ||
P Priya Nairpriya@vertex.co | Growth | Active | $2,140 | Nov 22, 2025 | ||
T Tom Fischertom@basecamp.dev | Starter | Churned | $380 | Aug 9, 2025 | ||
L Lena Björklena@aurora.se | Scale | Active | $6,390 | Mar 2, 2026 | ||
M Marcus Reedmarcus@hexa.io | Starter | Trial | $0 | Feb 27, 2026 |
8 row(s)
Client-side data-table engine: column-driven config with custom cell renderers, sortable headers, keyword search, row selection, per-row action menus, and pagination. Owns all state; blocks pass columns + rows as data.
A month grid with selectable days, a today marker, colored event dots per day, and prev/next month controls. Data-driven (weekStart + daysInMonth) so it renders deterministically; controlled or self-managed selection.
Topbar bell trigger with an unread count and a popover feed: icon rows with title, description, timestamp, unread dots, a mark-all-read action, and a scrollable list. Manages read state internally.
Dashboard sidebar with a brand header, grouped nav items, Lucide icons, trailing count badges, and an active state. Collapse is driven from the shell topbar via the `collapsed` prop (icon rail when true).
Topbar account menu: avatar trigger with name and email, dropdown with icon items, keyboard shortcuts, and a destructive sign-out row. Compact avatar-only mode for dense headers.
Atrium Loft
Floor 3 · 12 seats
Studio B
Floor 2 · 8 seats
Garden Room
Ground · 20 seats
Rooftop Deck
Level 5 · 40 seats
A Gantt-style day timeline: resource rows against an hour axis with time-positioned event bars (left/width computed from start/end), grid lines, a live 'now' marker, colored tones, and clickable bars with a hover tooltip showing the event and its time range. Ideal for room bookings, shifts, and resource scheduling.