Skip to content
Lenso UI

ColorSwatchPicker

A list of color swatches that allows users to select a color from a predefined palette.

Usage

import { ColorSwatchPicker, parseColor } from '@lenso/ui';
"use client";
import { ColorSwatchPicker } from "@lenso/ui";
const colors = ["#F43F5E", "#D946EF", "#8B5CF6", "#3B82F6", "#06B6D4", "#10B981", "#84CC16"];export function Basic() {  return (    <ColorSwatchPicker aria-label="Choose a color">      {colors.map((color) => (        <ColorSwatchPicker.Item key={color} color={color}>          <ColorSwatchPicker.Swatch />          <ColorSwatchPicker.Indicator />        </ColorSwatchPicker.Item>      ))}    </ColorSwatchPicker>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Anatomy

import { ColorSwatchPicker } from '@lenso/ui';
export default () => (  <ColorSwatchPicker>    <ColorSwatchPicker.Item color="#F43F5E">      <ColorSwatchPicker.Swatch />      <ColorSwatchPicker.Indicator />    </ColorSwatchPicker.Item>    <ColorSwatchPicker.Item color="#D946EF">      <ColorSwatchPicker.Swatch />      <ColorSwatchPicker.Indicator />    </ColorSwatchPicker.Item>    <ColorSwatchPicker.Item color="#8B5CF6">      <ColorSwatchPicker.Swatch />      <ColorSwatchPicker.Indicator />    </ColorSwatchPicker.Item>  </ColorSwatchPicker>);

Examples

Variants

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorSwatchPicker } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";import { SourceSwatches } from "./source";export function Variants() {  return (    <div {...stylex.props(styles.column6)}>      {(["circle", "square"] as const).map((variant) => (        <div key={variant} {...stylex.props(styles.column2)}>          <span {...stylex.props(styles.muted)}>            {variant === "circle" ? "Circle (default)" : "Square"}          </span>          <ColorSwatchPicker aria-label={`${variant} colors`} variant={variant}>            <SourceSwatches />          </ColorSwatchPicker>        </div>      ))}    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Sizes

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorSwatchPicker } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";import { SourceSwatches } from "./source";export function Sizes() {  return (    <div {...stylex.props(styles.column6)}>      {(["xs", "sm", "md", "lg", "xl"] as const).map((size) => (        <div key={size} {...stylex.props(styles.row4)}>          <span {...stylex.props(styles.width32, styles.muted)}>{size}</span>          <ColorSwatchPicker aria-label={`${size} colors`} size={size}>            <SourceSwatches />          </ColorSwatchPicker>        </div>      ))}    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Disabled

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorSwatchPicker } from "@lenso/ui";import { SourceSwatches } from "./source";export function Disabled() {  return (    <ColorSwatchPicker aria-label="Color">      <SourceSwatches disabled />    </ColorSwatchPicker>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Stack Layout

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorSwatchPicker } from "@lenso/ui";import { SourceSwatches } from "./source";export function StackLayout() {  return (    <ColorSwatchPicker aria-label="Color" layout="stack">      <SourceSwatches />    </ColorSwatchPicker>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Default Value

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorSwatchPicker } from "@lenso/ui";import { SourceSwatches } from "./source";export function DefaultValue() {  return (    <ColorSwatchPicker aria-label="Color" defaultValue="#8B5CF6">      <SourceSwatches />    </ColorSwatchPicker>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Controlled

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorSwatchPicker, parseColor } from "@lenso/ui";import { useState } from "react";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";import { SourceSwatches } from "./source";export function Controlled() {  const [value, setValue] = useState(parseColor("#F43F5E"));  return (    <div {...stylex.props(styles.column)}>      <ColorSwatchPicker aria-label="Color" value={value} onChange={setValue}>        <SourceSwatches />      </ColorSwatchPicker>      <p {...stylex.props(styles.muted)}>        Selected: <span {...stylex.props(styles.medium)}>{value.toString("hex")}</span>      </p>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Custom Indicator

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { HeartFill } from "@gravity-ui/icons";import { ColorSwatchPicker } from "@lenso/ui";import { SourceSwatches } from "./source";export function CustomIndicator() {  return (    <ColorSwatchPicker aria-label="Color">      <SourceSwatches indicator={<HeartFill />} />    </ColorSwatchPicker>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Render Function

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. Native RAC render state replaces DOM render interception. */import { ColorSwatchPicker } from "@lenso/ui";import { colors } from "./source";export function RenderFunction() {  return (    <ColorSwatchPicker aria-label="Color" data-custom="foo">      {colors.map((color) => (        <ColorSwatchPicker.Item key={color} color={color}>          {({ isSelected }) => (            <>              <ColorSwatchPicker.Swatch data-selected={isSelected || undefined} />              <ColorSwatchPicker.Indicator />            </>          )}        </ColorSwatchPicker.Item>      ))}    </ColorSwatchPicker>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Customization

Tailwind CSS

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorSwatchPicker } from "@lenso/ui";import { styles } from "../color-picker/source.stylex";import { SourceSwatches } from "./source";export function CustomStyles() {  return (    <ColorSwatchPicker      aria-label="Color"      xstyle={styles.pickerCustom}      defaultValue="#8B5CF6"      variant="square"    >      <SourceSwatches />    </ColorSwatchPicker>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Global CSS

To customize the ColorSwatchPicker component classes, you can use the @layer components directive. Learn more.

@layer components {  .color-swatch-picker {    @apply gap-4;  }
  .color-swatch-picker__item {    @apply shadow-md;  }
  .color-swatch-picker__swatch {    @apply border-2 border-white;  }}

Styling Reference

HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.

CSS Classes

The ColorSwatchPicker component uses these CSS classes (View source styles):

Base & Structure [!toc]

  • .color-swatch-picker - Base container (flex layout)
  • .color-swatch-picker__item - Individual swatch item wrapper
  • .color-swatch-picker__swatch - The color swatch visual element

Size Classes [!toc]

  • .color-swatch-picker--xs - Extra small (16px)
  • .color-swatch-picker--sm - Small (24px)
  • .color-swatch-picker--md - Medium (32px, default)
  • .color-swatch-picker--lg - Large (36px)
  • .color-swatch-picker--xl - Extra large (40px)

Shape Variants [!toc]

  • .color-swatch-picker--circle - Circle shape (default)
  • .color-swatch-picker--square - Square shape with rounded corners

Layout Classes [!toc]

  • .color-swatch-picker--grid - Horizontal wrapping layout (default)
  • .color-swatch-picker--stack - Vertical stacked layout

Interactive States

The component supports both CSS pseudo-classes and data attributes for flexibility:

  • Hover: :hover or [data-hovered="true"] - Scale up to 1.1 (only when not selected)
  • Focus: :focus-visible or [data-focus-visible="true"] - Focus ring
  • Selected: [data-selected="true"] - Inner border with same color as swatch
  • Disabled: [data-disabled="true"] - Reduced opacity

API Reference

ColorSwatchPicker

Inherits from React Aria ColorSwatchPicker.

PropTypeDefaultDescription
valuestring | Color-The current selected color (controlled)
defaultValuestring | Color-The default selected color (uncontrolled)
onChange(value: Color) => void-Handler called when selection changes
size"xs" | "sm" | "md" | "lg" | "xl""md"Size of the swatches
variant"circle" | "square""circle"Shape of the swatches
layout"grid" | "stack""grid"Layout direction
classNamestring-Additional CSS classes
childrenReact.ReactNode-ColorSwatchPicker.Item elements
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, ColorSwatchPickerRenderProps>-Overrides the default DOM element with a custom render function.

ColorSwatchPicker.Item

PropTypeDefaultDescription
colorstring | ColorRequiredThe color of the swatch
isDisabledbooleanfalseWhether the item is disabled
classNamestring-Additional CSS classes
childrenReact.ReactNode-ColorSwatchPicker.Swatch element
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, ColorSwatchPickerItemRenderProps>-Overrides the default DOM element with a custom render function.

ColorSwatchPicker.Swatch

PropTypeDefaultDescription
classNamestring-Additional CSS classes

parseColor

The parseColor function is re-exported from React Aria Components for convenience:

import { parseColor } from '@lenso/ui';
// Parse hex colorconst red = parseColor('#ff0000');
// Parse RGBconst green = parseColor('rgb(0, 255, 0)');
// Parse HSLconst blue = parseColor('hsl(240, 100%, 50%)');