Skip to content
Lenso UI

ColorField 颜色输入框

基于 React Aria ColorField 的颜色输入字段,支持标签、描述与验证

用法

import { ColorField, parseColor } from '@lenso/ui';

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

"use client";
import { ColorField, ColorSwatch, parseColor } from "@lenso/ui";import { useState } from "react";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({ field: { width: 280, maxWidth: "100%" } });export function Basic() {  const [color, setColor] = useState<ReturnType<typeof parseColor> | null>(() =>    parseColor("#0485F7"),  );  return (    <ColorField xstyle={styles.field} name="color" value={color} onChange={setColor}>      <ColorField.Label>Color</ColorField.Label>      <ColorField.Group>        <ColorField.Prefix>          <ColorSwatch {...(color ? { color } : {})} size="xs" />        </ColorField.Prefix>        <ColorField.Input />      </ColorField.Group>    </ColorField>  );}

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

组件结构

import {ColorField, Label, ColorSwatch, Description, FieldError, parseColor} from '@lenso/ui';
export default () => (  <ColorField>    <Label />    <ColorField.Group>      <ColorField.Prefix>        <ColorSwatch color="#000000" />      </ColorField.Prefix>      <ColorField.Input />    </ColorField.Group>    <Description />    <FieldError />  </ColorField>)

ColorField 将标签、颜色输入、描述与错误合并为单个无障碍组件。

示例

变体

ColorField.Group 组件支持两种视觉变体:

  • primary(默认)- 标准样式带阴影,适用于大多数场景
  • secondary - 低强调变体无阴影,适用于 Surface 组件内

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorField } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";export function Variants() {  return (    <div {...stylex.props(styles.column)}>      <ColorField xstyle={styles.width280} defaultValue="#0485F7" name="primary-color">        <ColorField.Label>Primary variant</ColorField.Label>        <ColorField.Group variant="primary">          <ColorField.Input />        </ColorField.Group>      </ColorField>      <ColorField xstyle={styles.width280} defaultValue="#F43F5E" name="secondary-color">        <ColorField.Label>Secondary variant</ColorField.Label>        <ColorField.Group variant="secondary">          <ColorField.Input />        </ColorField.Group>      </ColorField>    </div>  );}

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

表面样式

在 Surface 组件内使用时,在 ColorField.Group 上使用 variant="secondary" 以应用适合 Surface 背景的低强调变体。

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorField, Surface } from "@lenso/ui";import { styles } from "../color-picker/source.stylex";export function OnSurface() {  return (    <Surface xstyle={[styles.width320, styles.padded]}>      <ColorField defaultValue="#3B82F6" name="color">        <ColorField.Label>Theme Color</ColorField.Label>        <ColorField.Group variant="secondary">          <ColorField.Input />        </ColorField.Group>        <ColorField.Description>Select your theme color</ColorField.Description>      </ColorField>    </Surface>  );}

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

带描述

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorField } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";export function WithDescription() {  return (    <div {...stylex.props(styles.column)}>      <ColorField xstyle={styles.width280} defaultValue="#3B82F6" name="color">        <ColorField.Label>Primary Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input />        </ColorField.Group>        <ColorField.Description>Enter your brand's primary color</ColorField.Description>      </ColorField>      <ColorField xstyle={styles.width280} defaultValue="#F59E0B" name="accent-color">        <ColorField.Label>Accent Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input />        </ColorField.Group>        <ColorField.Description>Used for highlights and CTAs</ColorField.Description>      </ColorField>    </div>  );}

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

必填字段

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorField } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";export function Required() {  return (    <div {...stylex.props(styles.column)}>      <ColorField isRequired xstyle={styles.width280} name="color">        <ColorField.Label>Brand Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input placeholder="#000000" />        </ColorField.Group>      </ColorField>      <ColorField isRequired xstyle={styles.width280} name="theme-color">        <ColorField.Label>Theme Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input placeholder="#000000" />        </ColorField.Group>        <ColorField.Description>Required field</ColorField.Description>      </ColorField>    </div>  );}

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

禁用

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorField } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";export function Disabled() {  return (    <div {...stylex.props(styles.column)}>      <ColorField isDisabled xstyle={styles.width280} defaultValue="#0485F7" name="color">        <ColorField.Label>Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input />        </ColorField.Group>        <ColorField.Description>This color field is disabled</ColorField.Description>      </ColorField>      <ColorField isDisabled xstyle={styles.width280} name="color-empty">        <ColorField.Label>Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input placeholder="#000000" />        </ColorField.Group>        <ColorField.Description>This color field is disabled</ColorField.Description>      </ColorField>    </div>  );}

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

宽度充满

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorField } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";export function FullWidth() {  return (    <div {...stylex.props(styles.width400, styles.column)}>      <ColorField fullWidth defaultValue="#10B981" name="color">        <ColorField.Label>Brand Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input />        </ColorField.Group>      </ColorField>      <ColorField fullWidth defaultValue="#8B5CF6" name="color-with-suffix">        <ColorField.Label>Theme Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input />        </ColorField.Group>      </ColorField>    </div>  );}

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

表单校验

将 isInvalid 与 FieldError 一起使用以显示验证消息。

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorField } from "@lenso/ui";import { useState } from "react";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";export function Invalid() {  // A Color cannot represent malformed text; keep the source's invalid edit in the input.  const [invalidText, setInvalidText] = useState("not-a-color");  return (    <div {...stylex.props(styles.column)}>      <ColorField isInvalid isRequired xstyle={styles.width280} name="color">        <ColorField.Label>Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input placeholder="#000000" />        </ColorField.Group>        <ColorField.Error>Please enter a valid hex color</ColorField.Error>      </ColorField>      <ColorField isInvalid xstyle={styles.width280} name="invalid-color">        <ColorField.Label>Background Color</ColorField.Label>        <ColorField.Group>          <ColorField.Input            value={invalidText}            onChange={(event) => setInvalidText(event.target.value)}          />        </ColorField.Group>        <ColorField.Error>Invalid color format. Use hex (e.g., #FF5733)</ColorField.Error>      </ColorField>    </div>  );}

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

分量编辑

ColorField 支持通过设置 colorSpace 与 channel 属性编辑单个颜色通道(hue、saturation、lightness、red、green、blue、alpha)。

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { ColorField, ColorSwatch, parseColor } from "@lenso/ui";import type { Color } from "@lenso/ui";import { useState } from "react";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";export function ChannelEditing() {  const [color, setColor] = useState<Color | null>(parseColor("#7F007F"));  return (    <div {...stylex.props(styles.column)}>      <p {...stylex.props(styles.muted)}>Edit individual HSL channels:</p>      <div {...stylex.props(styles.controls)}>        {(["hue", "saturation", "lightness"] as const).map((channel) => (          <ColorField            key={channel}            channel={channel}            xstyle={styles.width100}            colorSpace="hsl"            name={channel}            value={color}            onChange={setColor}          >            <ColorField.Label xstyle={styles.capitalize}>{channel}</ColorField.Label>            <ColorField.Group>              <ColorField.Input />              {channel !== "hue" && (                <ColorField.Suffix>                  <span {...stylex.props(styles.muted)}>%</span>                </ColorField.Suffix>              )}            </ColorField.Group>          </ColorField>        ))}      </div>      <div {...stylex.props(styles.row2)}>        <ColorSwatch color={color ?? undefined} size="md" />        <span {...stylex.props(styles.small)}>          Current: {color ? color.toString("hex") : "(empty)"}        </span>      </div>    </div>  );}

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

受控组件

控制值以与其他组件或状态管理同步。

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. */import { Button, ColorField, ColorSwatch, parseColor } from "@lenso/ui";import type { Color } from "@lenso/ui";import { useState } from "react";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";export function Controlled() {  const [value, setValue] = useState<Color | null>(parseColor("#0485F7"));  return (    <div {...stylex.props(styles.column)}>      <ColorField xstyle={styles.width280} name="color" value={value} onChange={setValue}>        <ColorField.Label>Color</ColorField.Label>        <ColorField.Group>          <ColorField.Prefix>            <ColorSwatch color={value ?? undefined} size="xs" />          </ColorField.Prefix>          <ColorField.Input />        </ColorField.Group>        <ColorField.Description>          Current value: {value ? value.toString("hex") : "(empty)"}        </ColorField.Description>      </ColorField>      <div {...stylex.props(styles.row2)}>        <Button variant="tertiary" onClick={() => setValue(parseColor("#EF4444"))}>          Set Red        </Button>        <Button variant="tertiary" onClick={() => setValue(parseColor("#10B981"))}>          Set Green        </Button>        <Button variant="tertiary" onClick={() => setValue(null)}>          Clear        </Button>      </div>    </div>  );}

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

表单示例

包含验证与提交处理的完整表单示例。

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. Native form and Base UI button retain the source submit workflow. */import { Button, ColorField, ColorSwatch } from "@lenso/ui";import type { Color } from "@lenso/ui";import { useState, type FormEvent } from "react";import * as stylex from "@stylexjs/stylex";import { styles } from "../color-picker/source.stylex";export function FormExample() {  const [value, setValue] = useState<Color | null>(null);  const [isSubmitting, setIsSubmitting] = useState(false);  function handleSubmit(event: FormEvent<HTMLFormElement>) {    event.preventDefault();    if (!value || isSubmitting) return;    setIsSubmitting(true);    setTimeout(() => {      setValue(null);      setIsSubmitting(false);    }, 1500);  }  return (    <form {...stylex.props(styles.column, styles.width280)} onSubmit={handleSubmit}>      <ColorField        fullWidth        isRequired        xstyle={styles.full}        name="brand-color"        value={value}        onChange={setValue}      >        <ColorField.Label>Brand Color</ColorField.Label>        <ColorField.Group>          <ColorField.Prefix>            <ColorSwatch color={value ?? undefined} size="xs" />          </ColorField.Prefix>          <ColorField.Input placeholder="#000000" />        </ColorField.Group>        <ColorField.Description>Choose your brand's primary color</ColorField.Description>      </ColorField>      <Button        xstyle={styles.full}        disabled={!value}        isLoading={isSubmitting}        type="submit"        variant="primary"      >        {isSubmitting ? "Saving..." : "Save Color"}      </Button>    </form>  );}

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

渲染函数

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

"use client";/** Adapted from HeroUI v3.2.6. Apache-2.0. Native RAC render state replaces DOM render interception. */import { ColorField, ColorSwatch, parseColor } from "@lenso/ui";import type { Color } from "@lenso/ui";import { useState } from "react";import { styles } from "../color-picker/source.stylex";export function RenderFunction() {  const [color, setColor] = useState<Color | null>(parseColor("#0485F7"));  return (    <ColorField      xstyle={styles.width280}      name="color"      data-custom="foo"      value={color}      onChange={setColor}    >      {({ isInvalid }) => (        <>          <ColorField.Label>Color</ColorField.Label>          <ColorField.Group data-custom="foo" data-invalid={isInvalid || undefined}>            <ColorField.Prefix>              <ColorSwatch color={color ?? undefined} size="xs" />            </ColorField.Prefix>            <ColorField.Input />          </ColorField.Group>        </>      )}    </ColorField>  );}

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 { ColorField, ColorSwatch, parseColor } from "@lenso/ui";import type { Color } from "@lenso/ui";import { useState } from "react";import { styles } from "../color-picker/source.stylex";export function CustomStyles() {  const [color, setColor] = useState<Color | null>(parseColor("#6366F1"));  return (    <ColorField xstyle={styles.customField} name="accent-color" value={color} onChange={setColor}>      <ColorField.Label xstyle={styles.label}>Accent color</ColorField.Label>      <ColorField.Description>Applied to buttons, links, and focus rings.</ColorField.Description>      <ColorField.Group xstyle={styles.customGroup} variant="secondary">        <ColorField.Prefix>          <ColorSwatch xstyle={styles.square} color={color ?? undefined} size="xs" />        </ColorField.Prefix>        <ColorField.Input xstyle={styles.customInput} />      </ColorField.Group>    </ColorField>  );}

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

全局 CSS

ColorField 默认样式较少。覆盖 .color-field 类以自定义容器样式。

@layer components {  .color-field {    @apply flex flex-col gap-1;
    &[data-invalid="true"],    &[aria-invalid="true"] {      [data-slot="description"] {        @apply hidden;      }    }
    [data-slot="label"] {      @apply w-fit;    }
    [data-slot="description"] {      @apply px-1;    }  }}

样式参考

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

CSS 类

  • .color-field – 最小样式的根容器(flex flex-col gap-1)

Note: 子组件(Label、Description、FieldError)有各自的 CSS 类与样式。请参阅各自文档了解自定义选项。ColorField.Group 样式见下方 API 参考。

交互状态

ColorField 根据状态自动管理以下 data 属性:

  • Invalid:[data-invalid="true"] 或 [aria-invalid="true"] - 无效时自动隐藏 description slot
  • Required:[data-required="true"] - isRequired 为 true 时应用
  • Disabled:[data-disabled="true"] - isDisabled 为 true 时应用
  • Focus Within:[data-focus-within="true"] - 任一子 input 聚焦时应用

API 参考

ColorField

ColorField 继承 React Aria ColorField 组件的所有属性。

Base Props

Prop类型默认值描述
childrenReact.ReactNode | (values: ColorFieldRenderProps) => React.ReactNode-子组件(Label、ColorField.Group 等)或 render 函数
classNamestring | (values: ColorFieldRenderProps) => string-CSS 类,支持 render props
styleReact.CSSProperties | (values: ColorFieldRenderProps) => React.CSSProperties-内联样式,支持 render props
fullWidthbooleanfalse是否占满容器宽度
idstring-元素唯一标识符
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, ColorFieldRenderProps>-使用自定义 render 函数覆盖默认 DOM 元素

Value Props

Prop类型默认值描述
valueColor | null-当前值(受控)
defaultValueColor | null-默认值(非受控)
onChange(color: Color | null) => void-值变化时的回调

Channel Props

Prop类型默认值描述
colorSpaceColorSpace-提供 channel 时颜色字段操作的颜色空间
channelColorChannel-要编辑的颜色通道。未提供时编辑 hex 值

Validation Props

Prop类型默认值描述
isRequiredbooleanfalse表单提交前是否必须输入
isInvalidboolean-值是否无效
validate(value: Color) => ValidationError | true | null | undefined-自定义验证函数
validationBehavior'native' | 'aria''native'使用原生 HTML 表单验证还是 ARIA 属性

State Props

Prop类型默认值描述
isDisabledboolean-是否禁用
isReadOnlyboolean-是否可选中但不可更改
isWheelDisabledboolean-是否禁用滚轮更改值

Form Props

Prop类型默认值描述
namestring-HTML 表单提交时 input 元素的名称
autoFocusboolean-渲染时是否自动聚焦

Accessibility Props

Prop类型默认值描述
aria-labelstring-无可见标签时的无障碍标签
aria-labelledbystring-标注此字段的元素 ID
aria-describedbystring-描述此字段的元素 ID
aria-detailsstring-包含附加详情的元素 ID

Composition Components

ColorField 与以下需单独导入并直接使用的组件配合:

  • Label - 来自 @lenso/ui 的字段标签组件
  • ColorField.Group - 颜色输入组组件(见下方文档)
  • ColorField.Input - ColorField.Group 内的 input 元素
  • ColorField.Prefix / ColorField.Suffix - 输入组的前缀与后缀 slot
  • ColorSwatch - 来自 @lenso/ui 的颜色预览组件
  • Description - 来自 @lenso/ui 的帮助文本组件
  • FieldError - 来自 @lenso/ui 的验证错误消息

每个组件有各自的 props API。在 ColorField 内直接使用它们进行组合:

import {ColorField, Label, ColorSwatch, Description, FieldError, parseColor} from '@lenso/ui';
<ColorField  isRequired  isInvalid={hasError}  value={color}  onChange={setColor}>  <Label>Brand Color</Label>  <ColorField.Group>    <ColorField.Prefix>      <ColorSwatch color={color?.toString("hex") || "#E4E4E7"} />    </ColorField.Prefix>    <ColorField.Input />  </ColorField.Group>  <Description>Select your brand's primary color.</Description>  <FieldError>Please enter a valid color.</FieldError></ColorField>

Color Types

ColorField 使用 React Aria Components 的 Color 对象:

import {parseColor} from '@lenso/ui';
// Parse from hex stringconst color = parseColor('#3B82F6');
// Get hex string from colorconst hex = color.toString('hex'); // "#3b82f6"
// Get RGB valuesconst rgb = color.toString('rgb'); // "rgb(59, 130, 246)"
// Use in ColorField<ColorField value={color} onChange={setColor}>  {/* ... */}</ColorField>

Render Props

对 className、style 或 children 使用 render props 时,可使用以下值:

Prop类型描述
isDisabledboolean字段是否禁用
isInvalidboolean字段是否当前无效
isReadOnlyboolean字段是否只读
isRequiredboolean字段是否必填
isFocusedboolean字段是否当前聚焦
isFocusWithinboolean是否有子元素聚焦
isFocusVisibleboolean焦点是否可见(键盘导航)

ColorField.Group

ColorField.Group 接受 React Aria Group 组件的所有属性,以及以下属性:

Prop类型默认值描述
classNamestring-与组件样式合并的 Tailwind 类
fullWidthbooleanfalse颜色输入组是否占满容器宽度
variant"primary" | "secondary""primary"视觉变体。primary 为默认带阴影样式;secondary 为低强调无阴影,适用于 Surface 内
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, GroupRenderProps>-使用自定义 render 函数覆盖默认 DOM 元素

ColorField.Input

ColorField.Input 接受 React Aria Input 组件的所有属性,以及以下属性:

Prop类型默认值描述
classNamestring-与组件样式合并的 Tailwind 类
placeholderstring-为空时显示的占位文本

ColorField.Prefix

ColorField.Prefix 接受标准 HTML div 属性:

Prop类型默认值描述
classNamestring-与组件样式合并的 Tailwind 类
childrenReactNode-前缀 slot 中显示的内容

ColorField.Suffix

ColorField.Suffix 接受标准 HTML div 属性:

Prop类型默认值描述
classNamestring-与组件样式合并的 Tailwind 类
childrenReactNode-后缀 slot 中显示的内容

ColorField.Group Styling

Customizing the component classes

基础类驱动每个实例。使用 @layer components 一次性覆盖。

@layer components {  .color-input-group {    @apply inline-flex h-9 items-center overflow-hidden rounded-field border bg-field text-sm text-field-foreground shadow-field outline-none;
    &:hover,    &[data-hovered="true"] {      @apply bg-field-hover;    }
    &[data-focus-within="true"],    &:focus-within {      @apply status-focused-field;    }
    &[data-invalid="true"] {      @apply status-invalid-field;    }
    &[data-disabled="true"],    &[aria-disabled="true"] {      @apply status-disabled;    }  }
  .color-input-group__input {    @apply flex flex-1 items-center rounded-none border-0 bg-transparent px-3 py-2 shadow-none outline-none;  }
  .color-input-group__prefix,  .color-input-group__suffix {    @apply shrink-0 text-field-placeholder flex items-center;  }}

ColorField.Group CSS Classes

  • .color-input-group – 根容器样式
  • .color-input-group__input – Input 包装器样式
  • .color-input-group__prefix – 前缀元素样式
  • .color-input-group__suffix – 后缀元素样式

ColorField.Group Interactive States

  • Hover::hover 或 [data-hovered="true"]
  • Focus Within:[data-focus-within="true"] 或 :focus-within
  • Invalid:[data-invalid="true"](与 aria-invalid 同步)
  • Disabled:[data-disabled="true"] 或 [aria-disabled="true"]

相关组件