Skip to content
Lenso UI

ColorPicker 颜色选择器

可组合的颜色选择器,在多个颜色组件间同步颜色值

用法

import {  ColorPicker,  ColorArea,  ColorSlider,  ColorSwatch,  ColorField,  ColorSwatchPicker,} from '@lenso/ui';

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
import { ColorArea, ColorPicker, ColorSlider, ColorSwatch } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({  area: { maxWidth: "100%" },  slider: { gap: 4, paddingInline: 4 },  output: { color: "var(--muted)" },});export function Basic() {  return (    <ColorPicker defaultValue="#0485F7">      <ColorPicker.Trigger>        <ColorSwatch size="lg" />        <span>Pick a color</span>      </ColorPicker.Trigger>      <ColorPicker.Popover>        <ColorArea          aria-label="Color area"          xstyle={styles.area}          colorSpace="hsb"          xChannel="saturation"          yChannel="brightness"        >          <ColorArea.Thumb />        </ColorArea>        <ColorSlider aria-label="Hue" channel="hue" xstyle={styles.slider} colorSpace="hsb">          <span>Hue</span>          <ColorSlider.Output xstyle={styles.output} />          <ColorSlider.Track>            <ColorSlider.Thumb />          </ColorSlider.Track>        </ColorSlider>      </ColorPicker.Popover>    </ColorPicker>  );}

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

组件结构

ColorPicker 是组合多个颜色组件的可组合组件:

import { ColorPicker, ColorArea, ColorSlider, ColorSwatch, Label } from '@lenso/ui';
export default () => (  <ColorPicker defaultValue="#0485F7">    <ColorPicker.Trigger>      <ColorSwatch />      <Label>Pick a color</Label>    </ColorPicker.Trigger>    <ColorPicker.Popover>      <ColorArea colorSpace="hsb" xChannel="saturation" yChannel="brightness">        <ColorArea.Thumb />      </ColorArea>      <ColorSlider channel="hue" colorSpace="hsb">        <ColorSlider.Track>          <ColorSlider.Thumb />        </ColorSlider.Track>      </ColorSlider>    </ColorPicker.Popover>  </ColorPicker>);

示例

受控组件

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. Gravity Shuffle replaces the source Iconify reference to the same icon. */import {  Button,  ColorArea,  ColorField,  ColorPicker,  ColorSlider,  ColorSwatch,  ColorSwatchPicker,  parseColor,} from "@lenso/ui";import { Shuffle } from "@gravity-ui/icons";import { useState } from "react";import * as stylex from "@stylexjs/stylex";import { styles } from "./source.stylex";const presets = [  "#ef4444",  "#f97316",  "#eab308",  "#22c55e",  "#06b6d4",  "#3b82f6",  "#8b5cf6",  "#ec4899",  "#f43f5e",];export function Controlled() {  const [color, setColor] = useState(parseColor("#325578"));  function shuffleColor() {    const hue = Math.floor(Math.random() * 360);    const saturation = 50 + Math.floor(Math.random() * 50);    const lightness = 40 + Math.floor(Math.random() * 30);    setColor(parseColor(`hsl(${hue}, ${saturation}%, ${lightness}%)`));  }  return (    <div {...stylex.props(styles.column)}>      <ColorPicker value={color} onChange={setColor}>        <ColorPicker.Trigger>          <ColorSwatch size="lg" />          <span>Pick a color</span>        </ColorPicker.Trigger>        <ColorPicker.Popover xstyle={styles.popover}>          <ColorSwatchPicker aria-label="Color presets" xstyle={styles.presets} size="xs">            {presets.map((preset) => (              <ColorSwatchPicker.Item key={preset} color={preset}>                <ColorSwatchPicker.Swatch />              </ColorSwatchPicker.Item>            ))}          </ColorSwatchPicker>          <ColorArea            aria-label="Color area"            xstyle={styles.area}            colorSpace="hsb"            xChannel="saturation"            yChannel="brightness"          >            <ColorArea.Thumb />          </ColorArea>          <div {...stylex.props(styles.hueRow)}>            <ColorSlider              aria-label="Hue slider"              channel="hue"              xstyle={styles.flex1}              colorSpace="hsb"            >              <ColorSlider.Track>                <ColorSlider.Thumb />              </ColorSlider.Track>            </ColorSlider>            <Button              isIconOnly              aria-label="Shuffle color"              size="sm"              variant="tertiary"              onClick={shuffleColor}            >              <Shuffle {...stylex.props(styles.icon)} />            </Button>          </div>          <ColorField aria-label="Color field">            <ColorField.Group variant="secondary">              <ColorField.Prefix>                <ColorSwatch size="xs" />              </ColorField.Prefix>              <ColorField.Input />            </ColorField.Group>          </ColorField>        </ColorPicker.Popover>      </ColorPicker>      <p {...stylex.props(styles.selected)}>        Selected: <span {...stylex.props(styles.medium)}>{color.toString("hex")}</span>      </p>    </div>  );}

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

带色板

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorArea, ColorPicker, ColorSlider, ColorSwatch, ColorSwatchPicker } from "@lenso/ui";import { styles } from "./source.stylex";const presets = [  "#ef4444",  "#f97316",  "#eab308",  "#22c55e",  "#06b6d4",  "#3b82f6",  "#8b5cf6",  "#ec4899",  "#f43f5e",];export function WithSwatches() {  return (    <ColorPicker defaultValue="#F43F5E">      <ColorPicker.Trigger>        <ColorSwatch size="lg" />        <span>Brand Color</span>      </ColorPicker.Trigger>      <ColorPicker.Popover>        <ColorArea          aria-label="Color area"          xstyle={styles.area}          colorSpace="hsb"          xChannel="saturation"          yChannel="brightness"        >          <ColorArea.Thumb />        </ColorArea>        <ColorSlider aria-label="Hue slider" channel="hue" xstyle={styles.slider} colorSpace="hsb">          <ColorSlider.Label>Hue</ColorSlider.Label>          <ColorSlider.Output xstyle={styles.output} />          <ColorSlider.Track>            <ColorSlider.Thumb />          </ColorSlider.Track>        </ColorSlider>        <ColorSwatchPicker aria-label="Color presets" xstyle={styles.swatches} size="xs">          {presets.map((preset) => (            <ColorSwatchPicker.Item key={preset} color={preset}>              <ColorSwatchPicker.Swatch />            </ColorSwatchPicker.Item>          ))}        </ColorSwatchPicker>      </ColorPicker.Popover>    </ColorPicker>  );}

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

带输入字段

使用 ColorField 允许用户编辑单个颜色通道值,配合 Select 切换颜色空间。

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorArea, ColorField, ColorPicker, ColorSlider, ColorSwatch } from "@lenso/ui";import { useState } from "react";import * as stylex from "@stylexjs/stylex";import { styles } from "./source.stylex";import { ColorDemoSelect } from "./source";type Space = "hsb" | "hsl" | "rgb";const channels = {  hsb: ["hue", "saturation", "brightness"],  hsl: ["hue", "saturation", "lightness"],  rgb: ["red", "green", "blue"],} as const;export function WithFields() {  const [colorSpace, setColorSpace] = useState<Space>("hsl");  return (    <ColorPicker defaultValue="hsla(220, 90%, 50%, 0.8)">      <ColorPicker.Trigger>        <ColorSwatch size="lg" />        <span>Pick a color</span>      </ColorPicker.Trigger>      <ColorPicker.Popover xstyle={styles.narrowPopover}>        <ColorArea          aria-label="Color area"          xstyle={styles.area}          colorSpace="hsb"          xChannel="saturation"          yChannel="brightness"        >          <ColorArea.Thumb />        </ColorArea>        <ColorSlider channel="hue" xstyle={styles.slider} colorSpace="hsb">          <ColorSlider.Label>Hue</ColorSlider.Label>          <ColorSlider.Output xstyle={styles.output} />          <ColorSlider.Track>            <ColorSlider.Thumb />          </ColorSlider.Track>        </ColorSlider>        <ColorDemoSelect          label="Color space"          value={colorSpace}          options={["hsb", "hsl", "rgb"]}          onChange={setColorSpace}          uppercase        />        <div {...stylex.props(styles.channelGrid)}>          {channels[colorSpace].map((channel) => (            <ColorField              key={channel}              aria-label={channel}              channel={channel}              colorSpace={colorSpace}            >              <ColorField.Group variant="secondary">                <ColorField.Input />              </ColorField.Group>            </ColorField>          ))}        </div>      </ColorPicker.Popover>    </ColorPicker>  );}

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

带滑块

使用多个 ColorSlider 组件调整颜色值的各通道。

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorPicker, ColorSlider, ColorSwatch } from "@lenso/ui";import { useState } from "react";import * as stylex from "@stylexjs/stylex";import { styles } from "./source.stylex";import { ColorDemoSelect } from "./source";type Space = "hsb" | "hsl" | "rgb";const channelProps = {  hsb: [    { colorSpace: "hsb", channel: "hue" },    { colorSpace: "hsb", channel: "saturation" },    { colorSpace: "hsb", channel: "brightness" },    { colorSpace: "hsb", channel: "alpha" },  ],  hsl: [    { colorSpace: "hsl", channel: "hue" },    { colorSpace: "hsl", channel: "saturation" },    { colorSpace: "hsl", channel: "lightness" },    { colorSpace: "hsl", channel: "alpha" },  ],  rgb: [    { colorSpace: "rgb", channel: "red" },    { colorSpace: "rgb", channel: "green" },    { colorSpace: "rgb", channel: "blue" },    { colorSpace: "rgb", channel: "alpha" },  ],} as const;export function WithSliders() {  const [colorSpace, setColorSpace] = useState<Space>("hsl");  return (    <ColorPicker defaultValue="hsl(219, 58%, 93%)">      <ColorPicker.Trigger>        <ColorSwatch size="lg" />        <span>Pick a color</span>      </ColorPicker.Trigger>      <ColorPicker.Popover xstyle={styles.slidersPopover}>        <ColorDemoSelect          label="Color space"          value={colorSpace}          options={["hsb", "hsl", "rgb"]}          onChange={setColorSpace}          uppercase        />        <div {...stylex.props(styles.column2)}>          {channelProps[colorSpace].map((props) => (            <ColorSlider              key={props.channel}              {...props}              aria-label={props.channel}              xstyle={styles.slider}            >              <ColorSlider.Label xstyle={styles.capitalize}>{props.channel}</ColorSlider.Label>              <ColorSlider.Output xstyle={styles.output} />              <ColorSlider.Track>                <ColorSlider.Thumb />              </ColorSlider.Track>            </ColorSlider>          ))}        </div>      </ColorPicker.Popover>    </ColorPicker>  );}

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

自定义样式

Tailwind CSS

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorArea, ColorPicker, ColorSlider, ColorSwatch } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "./source.stylex";export function CustomStyles() {  return (    <ColorPicker defaultValue="#0485F7">      <ColorPicker.Trigger xstyle={styles.trigger}>        <ColorSwatch size="lg" />        <span {...stylex.props(styles.label)}>Theme color</span>      </ColorPicker.Trigger>      <ColorPicker.Popover xstyle={styles.surface}>        <ColorArea          aria-label="Color area"          xstyle={styles.area}          colorSpace="hsb"          xChannel="saturation"          yChannel="brightness"        >          <ColorArea.Thumb />        </ColorArea>        <ColorSlider channel="hue" xstyle={styles.slider} colorSpace="hsb">          <ColorSlider.Label>Hue</ColorSlider.Label>          <ColorSlider.Output xstyle={styles.output} />          <ColorSlider.Track>            <ColorSlider.Thumb />          </ColorSlider.Track>        </ColorSlider>      </ColorPicker.Popover>    </ColorPicker>  );}

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

全局 CSS

可使用 @layer components 指令自定义 ColorPicker 组件类。 了解更多。

@layer components {  .color-picker {    @apply inline-flex;  }
  .color-picker__trigger {    @apply inline-flex items-center gap-4 rounded-lg;  }
  .color-picker__popover {    @apply p-4 rounded-xl;  }}

样式参考

HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。

CSS 类

ColorPicker 组件使用以下 CSS 类(查看源码样式):

基础类 [!toc]

  • .color-picker - 基础容器
  • .color-picker__trigger - 触发按钮
  • .color-picker__popover - 弹出层容器

交互状态

组件同时支持 CSS 伪类与 data 属性:

  • Focus::focus-visible 或 [data-focus-visible="true"]
  • Disabled::disabled 或 [data-disabled="true"]

API 参考

ColorPicker

继承自 React Aria ColorPicker。

Prop类型默认值描述
valuestring | Color-当前颜色值(受控)
defaultValuestring | Color-默认颜色值(非受控)
onChange(color: Color) => void-颜色变化时的回调
childrenReact.ReactNode-颜色选择器内容(Trigger、Popover 等)
classNamestring-附加 CSS 类

ColorPicker.Trigger

Prop类型默认值描述
childrenReact.ReactNode | ((renderProps) => React.ReactNode)-触发器内容或 render prop
classNamestring-附加 CSS 类

ColorPicker.Popover

Prop类型默认值描述
placementPlacement"bottom left"弹出层位置
childrenReact.ReactNode-弹出层内容
classNamestring-附加 CSS 类

Color

表示颜色值。完整 API 请参阅 React Aria Color。

MethodDescription
toString(format)将颜色转换为指定格式的字符串(hex、rgb、hsl、hsb、css)
toFormat(format)将颜色转换为指定格式并返回新的 Color 对象
getChannelValue(channel)返回指定通道的数值
withChannelValue(channel, value)设置通道数值并返回新的 Color

parseColor

import { parseColor } from 'react-aria-components';
// Parse from stringconst color = parseColor('#ff0000');const hslColor = parseColor('hsl(0, 100%, 50%)');

相关组件