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
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
value | string | Color | - | 当前颜色值(受控) |
defaultValue | string | Color | - | 默认颜色值(非受控) |
onChange | (color: Color) => void | - | 颜色变化时的回调 |
children | React.ReactNode | - | 颜色选择器内容(Trigger、Popover 等) |
className | string | - | 附加 CSS 类 |
ColorPicker.Trigger
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | React.ReactNode | ((renderProps) => React.ReactNode) | - | 触发器内容或 render prop |
className | string | - | 附加 CSS 类 |
ColorPicker.Popover
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
placement | Placement | "bottom left" | 弹出层位置 |
children | React.ReactNode | - | 弹出层内容 |
className | string | - | 附加 CSS 类 |
Related Types
Color
表示颜色值。完整 API 请参阅 React Aria Color。
| Method | Description |
|---|---|
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%)');