Color Picker
A neo-brutalist style color picker component built on reka-ui Popover. Supports HEX/RGB/HSL color formats, an alpha channel, a preset color palette, and locally stored color history.
Demo
基础用法(HEX)
颜色格式
透明度通道(showAlpha)
自定义预设颜色
尺寸
禁用状态
程序化控制(通过 ref 打开面板)
通过 pickerRef.open 可在外部按钮中打开或关闭颜色面板。
The color picker provides a saturation/brightness selection area, a hue slider, an opacity slider, a HEX input, preset colors, and history.
Installation
pnpm dlx brutx-vue@latest add color-pickerUsage
Basic Usage
<script setup>
import { ref } from 'vue'
import { ColorPicker } from 'brutx-ui-vue'
const color = ref(null)
</script>
<template>
<ColorPicker v-model="color" placeholder="Select color" />
</template>Specifying Color Format
Supports hex (default), rgb, and hsl formats. modelValue outputs in the corresponding format:
<script setup>
import { ref } from 'vue'
import { ColorPicker } from 'brutx-ui-vue'
const color = ref(null)
</script>
<template>
<ColorPicker v-model="color" format="rgb" />
<ColorPicker v-model="color" format="hsl" />
</template>Alpha Channel
When showAlpha is enabled, the panel displays an opacity slider and the output value includes the alpha channel:
<template>
<ColorPicker v-model="color" :show-alpha="true" />
</template>Preset Colors
Includes the Tailwind CSS default color palette out of the box, or you can customize presets:
<script setup>
import { ref } from 'vue'
import { ColorPicker } from 'brutx-ui-vue'
const color = ref(null)
const presets = [
'#FF6B6B',
'#4ECDC4',
'#FFE66D',
'#EF476F',
'#7FB069',
]
</script>
<template>
<ColorPicker v-model="color" :presets="presets" :show-presets="true" />
</template>Presets also support an object format with labels (optional disabled field to disable individual swatches):
<script setup>
const presets = [
{ label: 'Coral Red', value: '#FF6B6B' },
{ label: 'Mint Green', value: '#4ECDC4' },
{ label: 'Deprecated', value: '#999999', disabled: true },
]
</script>Color History
When showHistory is enabled, user-selected colors are automatically recorded to history, stored in localStorage by default:
<template>
<ColorPicker
v-model="color"
:show-history="true"
:history-max="20"
history-storage-key="my-app-color-history"
/>
</template>Clearable
<template>
<ColorPicker v-model="color" :clearable="true" />
</template>Disabled State
<template>
<ColorPicker v-model="color" disabled />
</template>Sizes
| Size | Description |
|---|---|
sm | Small size |
default | Default size |
lg | Large size |
<template>
<ColorPicker v-model="color" size="sm" />
<ColorPicker v-model="color" size="default" />
<ColorPicker v-model="color" size="lg" />
</template>Data Types
| Format | Example | Description |
|---|---|---|
hex | #FF6B6B / #FF6B6B80 | Hexadecimal (two extra digits when alpha is included) |
rgb | rgb(255, 107, 107) / rgba(255, 107, 107, 0.5) | RGB function notation |
hsl | hsl(0, 100%, 71%) / hsla(0, 100%, 71%, 0.5) | HSL function notation |
Composables
The ColorPicker component's popup panel triggering, color format normalization, clearing, and confirmation logic has been extracted into a standalone useColorPicker composable. It can be used independently when you need to build a fully custom trigger or color palette. It manages panel open/close state, display value synchronization with modelValue, normalization to the target format, and triggers open / close / change / update:modelValue events through the provided emit.
import { useColorPicker } from 'brutx-ui-vue'
import type { UseColorPickerOptions } from 'brutx-ui-vue'
const emit = defineEmits<{
'update:modelValue': [value: string | null]
'change': [value: string | null]
'open': []
'close': []
}>()
const {
open, // Whether the panel is open
displayValue, // Current displayed value in the panel
normalizedDisplay, // Display string normalized to the target format
swatchStyle, // Inline style for the trigger swatch
handlePanelUpdate, // Panel value update callback
handlePanelConfirm, // Panel confirm callback
handlePanelClear, // Panel clear callback
handleClearClick, // Trigger clear button click callback
handleTriggerKeydown, // Trigger keyboard event callback
} = useColorPicker({
modelValue,
format: 'hex',
showAlpha: false,
disabled: false,
emit,
})Options
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | MaybeRefOrGetter<string | null> | null | Currently selected color (supports v-model) |
format | MaybeRefOrGetter<'hex' | 'rgb' | 'hsl'> | 'hex' | Color format |
showAlpha | MaybeRefOrGetter<boolean> | false | Whether to support the alpha channel |
disabled | MaybeRefOrGetter<boolean> | false | Whether disabled |
emit | ColorPickerEmit | — | Event emitter function (required, type matches the component's emits) |
Return Values
| Property | Type | Description |
|---|---|---|
open | Ref<boolean> | Whether the panel is open |
displayValue | Ref<string | null> | Current displayed value in the panel |
normalizedDisplay | ComputedRef<string | null> | Display string normalized by format (null if unparseable) |
swatchStyle | ComputedRef<{ backgroundColor: string }> | Inline style for the trigger swatch |
handlePanelUpdate(value) | (value: string | null) => void | Called when panel value updates; syncs displayValue and triggers update:modelValue |
handlePanelConfirm(value) | (value: string | null) => void | Called on panel confirm; triggers update:modelValue / change and closes the panel |
handlePanelClear() | () => void | Called on panel clear; triggers update:modelValue(null) / change(null) |
handleClearClick(event) | (event: MouseEvent) => void | Trigger clear button click callback; stops event propagation and clears |
handleTriggerKeydown(event) | (event: KeyboardEvent) => void | Trigger keyboard event callback; Enter / Space opens the panel (no response when disabled) |
Note:
emitmust be a function conforming to theColorPickerEmitsignature (i.e., the return value of the component'sdefineEmits). Color parsing and formatting are provided byparseColor/formatColorfrom@/lib/color.
Programmatic Control
ColorPicker exposes an open reactive ref via defineExpose, allowing the parent component to programmatically open or close the color panel. open is a Ref<boolean> that is two-way bound to the internal Popover, and can be read or written directly.
<script setup>
import { ref } from 'vue'
import { ColorPicker } from 'brutx-ui-vue'
const pickerRef = ref()
const color = ref(null)
</script>
<template>
<ColorPicker ref="pickerRef" v-model="color" />
<button @click="pickerRef?.open = true">Open Panel</button>
<button @click="pickerRef?.open = false">Close Panel</button>
</template>API Reference
ColorPicker
| Name | Type | Default | Description |
|---|---|---|---|
open | boolean | undefined | undefined | The controlled open state of the color panel, used with v-model:open. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPicker.vue | |||
size | "default" | "lg" | "sm" | undefined | "default" | The size of the trigger and color controls. |
DetailsDeclared typeNonNullable<"default" | "lg" | "sm" | null | undefined> | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPicker.vue | |||
modelValueNullable | string | null | undefined | null | The current color string; null means no color is selected. Supports two-way binding with v-model. |
DetailsDeclared typestring | null | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
format | ColorPickerFormat | undefined | "hex" | The input and output color format: HEX, RGB, or HSL. |
DetailsDeclared typeColorPickerFormat | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
showAlpha | boolean | undefined | false | Shows the opacity slider and includes the alpha channel in emitted color values. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
presets | string[] | readonly ColorPreset[] | undefined | undefined | Optional swatches as color strings or ColorPreset objects with labels and disabled states. The panel uses its built-in presets when omitted. |
DetailsDeclared typestring[] | readonly ColorPreset[] | undefined Referenced types ColorPreset Type definition — ColorPresetexport interface ColorPreset {
readonly label: string
readonly value: string
readonly disabled?: boolean
}Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
showPresets | boolean | undefined | true | Controls whether the panel displays preset swatches. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
presetsLabel | string | undefined | undefined | The visible heading for the preset area; localized text is used when omitted. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
showHistory | boolean | undefined | true | Controls whether the panel displays and maintains recently selected colors. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
historyMax | number | undefined | 8 | The maximum number of entries retained in color history. |
DetailsDeclared typenumber | undefined Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
historyStorageKey | string | undefined | "brutx-color-history" | The localStorage key used to persist color history. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
showInput | boolean | undefined | true | Shows the color text in the trigger. When false, the trigger shows the swatch and placeholder only. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
placeholder | string | undefined | undefined | Placeholder text shown when there is no valid color; it is also the localized fallback for the accessible name. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
disabled | boolean | undefined | false | Disables the trigger and clear action and prevents opening the color panel. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
clearable | boolean | undefined | false | Shows a clear button when a color is selected and the control is enabled. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
name | string | undefined | undefined | The form field name. When set, a hidden input submits the current color; a disabled control is excluded from form submission. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
id | string | undefined | undefined | Sets the native HTML id on the trigger button. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
ariaLabel | string | undefined | undefined | The accessible name of the trigger; localized placeholder text is used when omitted. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
classNullable | ClassValue | undefined | CSS classes added to the color picker trigger. Supports array and object forms accepted by ClassValue. |
DetailsDeclared typeClassValue Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/types.ts | |||
| Name | Signature or type | Description |
|---|---|---|
@update:modelValue | [value: string | null] | Emits the formatted color as it is typed, selected by dragging, or cleared; clearing emits null. |
DetailsDeclared type[value: string | null] Literal values
Sourcepackages/ui/src/components/color-picker/ColorPicker.vue | ||
@open | [] | Emitted without a payload when the panel opens. |
DetailsDeclared type[] Sourcepackages/ui/src/components/color-picker/ColorPicker.vue | ||
@close | [] | Emitted without a payload when the panel closes. |
DetailsDeclared type[] Sourcepackages/ui/src/components/color-picker/ColorPicker.vue | ||
@update:open | [value: boolean] | Emits the new boolean open state so a controlled open value can be updated. |
DetailsDeclared type[value: boolean] Literal values
Sourcepackages/ui/src/components/color-picker/ColorPicker.vue | ||
@change | [value: string | null] | Emits the final value when the user confirms or clears a color, separate from intermediate update:modelValue changes. |
DetailsDeclared type[value: string | null] Literal values
Sourcepackages/ui/src/components/color-picker/ColorPicker.vue | ||
| Name | Signature or type | Description |
|---|---|---|
open | Ref<boolean, boolean> | A Ref for the panel open state. Read or write it through the component instance to open or close the panel programmatically. |
DetailsDeclared typeRef<boolean, boolean> Literal values
Sourcepackages/ui/src/components/color-picker/ColorPicker.vue | ||
ColorPickerHistory
| Name | Type | Default | Description |
|---|---|---|---|
historyRequired | readonly string[] | — | The list of historical color strings to display; invalid colors are filtered out. |
DetailsDeclared typereadonly string[] Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerHistory.vue | |||
modelValueNullable | string | null | undefined | null | The current color, used to highlight a swatch with the same normalized color value. |
DetailsDeclared typestring | null | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerHistory.vue | |||
size | "default" | "lg" | "sm" | undefined | "default" | The size of the history swatches. |
DetailsDeclared type"default" | "lg" | "sm" | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerHistory.vue | |||
ariaLabel | string | undefined | undefined | The accessible name of the history group; a localized heading is used when omitted. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerHistory.vue | |||
clearLabel | string | undefined | undefined | The accessible name of the clear-history button; localized text is used when omitted. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerHistory.vue | |||
| Name | Signature or type | Description |
|---|---|---|
@clear | [] | Emitted without a payload when the user activates the clear button. |
DetailsDeclared type[] Sourcepackages/ui/src/components/color-picker/ColorPickerHistory.vue | ||
@select | [value: string] | Emits the color string when the user selects a valid history swatch. |
DetailsDeclared type[value: string] Sourcepackages/ui/src/components/color-picker/ColorPickerHistory.vue | ||
ColorPickerInput
| Name | Type | Default | Description |
|---|---|---|---|
modelValueNullable | string | null | undefined | null | The current color. Valid values are displayed in the requested format; null leaves the input empty. |
DetailsDeclared typestring | null | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerInput.vue | |||
format | "hex" | "rgb" | "hsl" | undefined | "hex" | The format used to normalize and emit the input value. |
DetailsDeclared type"hex" | "rgb" | "hsl" | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerInput.vue | |||
showAlpha | boolean | undefined | false | Whether formatted color values include the alpha channel. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerInput.vue | |||
disabled | boolean | undefined | false | Disables the native text input. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerInput.vue | |||
ariaLabel | string | undefined | undefined | The accessible name of the text input. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerInput.vue | |||
| Name | Signature or type | Description |
|---|---|---|
@update:modelValue | [value: string | null] | Emitted when the input is empty or contains a valid color; invalid text does not update the color value. |
DetailsDeclared type[value: string | null] Literal values
Sourcepackages/ui/src/components/color-picker/ColorPickerInput.vue | ||
@confirm | [value: string | null] | Confirms a valid color or empty value on Enter or blur; invalid text is restored from the current model value. |
DetailsDeclared type[value: string | null] Literal values
Sourcepackages/ui/src/components/color-picker/ColorPickerInput.vue | ||
ColorPickerPanel
| Name | Type | Default | Description |
|---|---|---|---|
modelValueNullable | string | null | undefined | null | The panel current color; null means no color is selected. |
DetailsDeclared typestring | null | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
format | ColorFormat | undefined | "hex" | The color format used when the panel creates and formats color values. |
DetailsDeclared typeColorFormat | undefined Literal values
Referenced types ColorFormat Type definition — ColorFormatexport type ColorFormat = 'hex' | 'rgb' | 'hsl' Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
showAlpha | boolean | undefined | false | Shows the opacity control and includes the alpha channel in color values. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
presets | string[] | readonly ColorPreset[] | undefined | Factory evaluated per instance | Swatches as strings or ColorPreset objects. The built-in palette is used when omitted. |
DetailsDeclared typestring[] | readonly ColorPreset[] | undefined Referenced types ColorPreset Type definition — ColorPresetexport interface ColorPreset {
readonly label: string
readonly value: string
readonly disabled?: boolean
}Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
showPresets | boolean | undefined | true | Whether to render the preset swatches section. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
presetsLabel | string | undefined | undefined | The preset-section heading; localized text is used when omitted. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
showHistory | boolean | undefined | true | Whether to display the color history section. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
historyMax | number | undefined | 8 | The maximum number of colors retained in history. |
DetailsDeclared typenumber | undefined Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
historyStorageKey | string | undefined | undefined | The localStorage key passed to the color-history storage logic. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
showInput | boolean | undefined | true | Whether to show the editable color text input. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
clearable | boolean | undefined | true | Whether to show the action for clearing the current color. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
size | ColorPickerSize | undefined | "default" | The size of the panel swatches and controls. |
DetailsDeclared typeColorPickerSize | undefined Literal values
Referenced types ColorPickerSize Type definition — ColorPickerSizeexport type ColorPickerSize = 'sm' | 'default' | 'lg' Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | |||
| Name | Signature or type | Description |
|---|---|---|
@update:modelValue | [value: string | null] | Emits the new value when a panel control changes the color. |
DetailsDeclared type[value: string | null] Literal values
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | ||
@clear | [] | Emitted without a payload when the user clears the current color. |
DetailsDeclared type[] Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | ||
@confirm | [value: string | null] | Emits the final color value when the user confirms the panel selection. |
DetailsDeclared type[value: string | null] Literal values
Sourcepackages/ui/src/components/color-picker/ColorPickerPanel.vue | ||
ColorPickerSwatch
| Name | Type | Default | Description |
|---|---|---|---|
valueRequired | string | — | The color string represented by the swatch; invalid colors disable the button. |
DetailsDeclared typestring Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerSwatch.vue | |||
label | string | undefined | undefined | The swatch tooltip and fallback accessible name. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerSwatch.vue | |||
selected | boolean | undefined | false | Whether the swatch is selected, also reflected by aria-pressed. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerSwatch.vue | |||
disabled | boolean | undefined | false | Disables mouse and keyboard selection of the swatch. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerSwatch.vue | |||
size | "default" | "lg" | "sm" | undefined | "default" | The size of the swatch button. |
DetailsDeclared typeNonNullable<"default" | "lg" | "sm" | null | undefined> | undefined Literal values
Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerSwatch.vue | |||
ariaLabel | string | undefined | undefined | Explicitly sets the swatch button accessible name, taking precedence over label and the color value. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/color-picker/ColorPickerSwatch.vue | |||
| Name | Signature or type | Description |
|---|---|---|
@select | [value: string] | Emits the color string when a valid, enabled swatch is activated. |
DetailsDeclared type[value: string] Sourcepackages/ui/src/components/color-picker/ColorPickerSwatch.vue | ||
Accessibility
Trigger
| Key | Action |
|---|---|
Enter / Space | Open the panel (no response when disabled) |
Escape | Close the panel |
Saturation/Brightness Area
| Key | Action |
|---|---|
Left / Right | Adjust saturation (step 1, Shift step 10) |
Up / Down | Adjust brightness (step 1, Shift step 10) |
Hue Slider
| Key | Action |
|---|---|
Left / Right | Adjust hue (step 1, Shift step 15) |
Opacity Slider
| Key | Action |
|---|---|
Left / Right | Adjust opacity (step 0.01, Shift step 0.1) |
Preset & History Swatches
Preset and history color swatches are native <button> elements (Tab-focusable, activated with Enter/Space). The selected state is expressed via aria-pressed, and a focus-visible ring provides keyboard focus feedback. Invalid color values are filtered out (history); invalid preset swatches are dimmed with opacity-40 and rendered as natively disabled buttons (not focusable, cursor-not-allowed, not keyboard-activatable).
FAQ
Q: What happens to the previous modelValue format when switching format?
A: The component automatically normalizes the existing color value to the format corresponding to the current format. For example, when switching from hex to rgb, the previous #FF6B6B is automatically converted to rgb(255, 107, 107). No manual format conversion is needed.
Q: Where is color history stored? How do I clear it?
A: Color history is stored in the browser's localStorage by default, with the key controlled by the historyStorageKey prop (default: 'brutx-color-history'). It can be cleared via the browser developer tools' Application panel, or programmatically with localStorage.removeItem('brutx-color-history'). Setting a different historyStorageKey allows maintaining independent histories for different use cases.
Q: How does the output format change when showAlpha is enabled?
A: When the alpha channel is enabled, the output value includes alpha information. The hex format becomes 8 digits (e.g., #FF6B6B80), rgb becomes rgba(), and hsl becomes hsla(). When showAlpha is disabled, the output reverts to the standard format without opacity.