Color Picker
A versatile color picker component that supports swatches, custom colors, and various picker formats.
Basic Usage
The type prop chooses how the picker is presented:
swatch(default) — a small color trigger that opens a popover of preset swatches. Best when users pick from a curated palette (brand colors, a theme).picker— a color trigger that opens the full custom picker (saturation/brightness area, hue and alpha sliders, and input fields). Best when users need to choose any color.inline-picker— the full picker rendered directly in the page with no trigger or popover. Best for embedding inside a panel or form where it should always be visible.
Bind the selected color with value and listen to @update:picker (custom colors) or @select (swatch/final selection). The three examples below show each type.
<template>
<HLColorPicker id="basic-color-picker" :swatches="swatches" />
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
import { swatches } from './options'
</script>import type { HLColorPickerSections } from '@platform-ui/highrise'
export const swatches: HLColorPickerSections[] = [
{
key: 'brand',
label: 'Brand Colors',
swatches: ['var(--primary-200)', 'var(--primary-500)', 'var(--primary-800)'],
showAddButton: false,
showTooltip: 'value',
},
]<template>
<HLColorPicker id="basic-color-picker-2" type="picker" @select="handleOnSelect" />
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
const handleOnSelect = (...args: unknown[]) => {
console.log('select: ', ...args)
}
</script><template>
<div class="w-80">
<HLColorPicker id="basic-color-picker-3" type="inline-picker" @select="handleOnSelect" />
</div>
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
const handleOnSelect = (...args: unknown[]) => {
console.log('select: ', ...args)
}
</script>Configuring the Picker
Use pickerOptions to control which parts of the picker UI appear and which color formats are available. Every field is optional and falls back to its default (see Types):
showHue— the hue slider (the rainbow bar) for choosing the base color. Hiding it locks the picker to shades of the current hue.showAlpha— the opacity slider and its alpha input. Hide it when you only want fully-opaque colors.showInputFields— the numeric/hex input fields (with the format dropdown) for typing exact values, instead of only dragging in the color area.showEyeDropper— the eyedropper button that lets users sample any color on screen. (Browser support varies; it only appears where the EyeDropper API is available.)showCTA— the Save / Cancel action buttons. Only applies to theswatchtype's add/edit flow;pickerandinline-pickercommit changes live and don't show these.pickerFormatOptions— which formats appear in the format dropdown (any ofHEX,RGB,HSL,HSB,Custom).defaultPickerFormat— the format selected initially. Must be one ofpickerFormatOptions, otherwise it falls back to the first entry.
<template>
<HLColorPicker
id="picker-options-demo"
type="inline-picker"
:value="color"
:picker-options="{
showAlpha: false, // hide the opacity slider
showEyeDropper: false, // hide the eyedropper tool
showCTA: false, // hide the save/cancel buttons
pickerFormatOptions: ['HEX', 'RGB'], // only offer HEX and RGB
defaultPickerFormat: 'RGB', // start in RGB
}"
@update:picker="(value, value8) => (color = value8)"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { HLColorPicker } from '@platform-ui/highrise'
const color = ref('#26a6a6')
</script>Empty States
Use the #empty slot to render custom content for sections with no swatches.
<template>
<HLColorPicker id="basic-color-picker" :swatches="emptySwatches">
<template #empty="{ key }"> No {{ key.toLowerCase() }} colors found </template>
</HLColorPicker>
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
import { emptySwatches } from './options'
</script>import type { HLColorPickerSections } from '@platform-ui/highrise'
export const emptySwatches: HLColorPickerSections[] = [
{
key: 'brand',
label: 'Brand Colors',
swatches: [],
showAddButton: false,
showTooltip: 'value',
},
{
key: 'default',
label: 'Default Colors',
swatches: [],
showAddButton: true,
showTransparentSwatch: true,
showEyeDropper: true,
showTooltip: 'both',
},
{
key: 'custom',
label: 'Custom Colors',
swatches: [],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
]More Swatches
Open dev tools console and play with the picker to see how the emits work!
<template>
<HLColorPicker
id="basic-color-picker"
:swatches="moreSwatches"
:forward-picker-updates="true"
@select="(...args) => handleCustomUpdate('select', args)"
@swatch:add="(...args) => handleCustomUpdate('swatch:add', args)"
@swatch:delete="(...args) => handleCustomUpdate('swatch:delete', args)"
@swatch:edit="(...args) => handleCustomUpdate('swatch:edit', args)"
@swatch:reset="(...args) => handleCustomUpdate('swatch:reset', args)"
@update:picker="(...args) => handleCustomUpdate('update:picker', args)"
@update:picker:back="(...args) => handleCustomUpdate('update:picker:back', args)"
@update:picker:close="(...args) => handleCustomUpdate('update:picker:close', args)"
@update:show="(...args) => handleCustomUpdate('update:show', args)"
@update:swatches="(...args) => handleCustomUpdate('update:swatches', args)"
/>
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
import { moreSwatches } from './options'
const handleCustomUpdate = (type: string, args: unknown[]) => {
console.log(`${type}: `, ...args)
}
</script>import type { HLColorPickerSections } from '@platform-ui/highrise'
export const moreSwatches: HLColorPickerSections[] = [
{
key: 'brand',
label: 'Brand Colors',
swatches: ['var(--primary-500)', 'var(--primary-600)', 'var(--primary-700)', 'var(--primary-800)', 'var(--primary-900)'],
showAddButton: false,
showTooltip: 'value',
},
{
key: 'default',
label: 'Default Colors',
swatches: ['var(--gray-100)', 'var(--gray-200)', 'var(--gray-300)', 'var(--gray-400)', 'var(--gray-500)'],
showAddButton: true,
showTransparentSwatch: true,
showEyeDropper: true,
showTooltip: 'both',
},
{
key: 'custom',
label: 'Custom Colors',
swatches: ['var(--green-100)', 'var(--green-200)', 'var(--green-300)', 'var(--green-400)', 'var(--green-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
{
key: 'blues',
label: 'Blues',
swatches: ['var(--indigo-100)', 'var(--indigo-200)', 'var(--indigo-300)', 'var(--indigo-400)', 'var(--indigo-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
{
key: 'pinks',
label: 'Pinks',
swatches: ['var(--pink-100)', 'var(--pink-200)', 'var(--pink-300)', 'var(--pink-400)', 'var(--pink-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
]CRUD Operations on Swatches
Look out for notifications based on CRUD operations performed on the swatches!
<template>
<HLColorPicker
id="basic-color-picker"
:swatches="colorpickerSections"
@swatch:add="handleSwatchAdd"
@swatch:edit="handleSwatchEdit"
@swatch:delete="handleSwatchDelete"
/>
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
import { colorpickerSections, handleSwatchAdd, handleSwatchEdit, handleSwatchDelete } from './options'
</script>import { h } from 'vue'
import type { HLColorPickerSections, HLColorSwatch } from '@platform-ui/highrise'
import { HLAlert, HLSwatchTile, HLText, useHLNotification } from '@platform-ui/highrise'
export const colorpickerSections: HLColorPickerSections[] = [
{
key: 'brand',
label: 'Brand Colors',
swatches: ['var(--primary-500)', 'var(--primary-600)', 'var(--primary-700)', 'var(--primary-800)', 'var(--primary-900)'],
showAddButton: false,
showTooltip: 'value',
},
{
key: 'default',
label: 'Default Colors',
swatches: ['var(--gray-100)', 'var(--gray-200)', 'var(--gray-300)', 'var(--gray-400)', 'var(--gray-500)'],
showAddButton: true,
showTransparentSwatch: true,
showEyeDropper: true,
showTooltip: 'both',
},
{
key: 'custom',
label: 'Custom Colors',
swatches: ['var(--green-100)', 'var(--green-200)', 'var(--green-300)', 'var(--green-400)', 'var(--green-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
{
key: 'blues',
label: 'Blues',
swatches: ['var(--indigo-100)', 'var(--indigo-200)', 'var(--indigo-300)', 'var(--indigo-400)', 'var(--indigo-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
{
key: 'pinks',
label: 'Pinks',
swatches: ['var(--pink-100)', 'var(--pink-200)', 'var(--pink-300)', 'var(--pink-400)', 'var(--pink-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
]
const notification = useHLNotification()
function openNotification(
action: 'add' | 'edit' | 'delete',
sectionKey: string,
sectionIndex: number,
value: string | HLColorSwatch,
editorDeleteIndex?: number
) {
const mergedValue = typeof value === 'string' ? value : JSON.stringify(value)
const message =
action === 'add' ? 'A new swatch has been added' : action === 'edit' ? 'A swatch has been edited' : 'A swatch has been deleted'
const color = action === 'add' ? 'green' : action === 'edit' ? 'blue' : 'red'
const n = notification.create({
content: () =>
h(
HLAlert,
{
closable: true,
color,
id: 'test-alert',
width: '720px',
onClose: () => {
n.destroy()
},
},
{
default: () =>
h(
'div',
{
class: 'flex flex-col gap-2',
},
[
h(
HLText,
{
size: 'xl',
weight: 'bold',
},
() => message
),
h(
HLText,
{
size: 'md',
weight: 'medium',
},
() => `Section: ${sectionKey}`
),
h(
HLText,
{
size: 'md',
weight: 'medium',
},
() => `Section Index: ${sectionIndex}`
),
h(
HLText,
{
size: 'md',
weight: 'medium',
},
() => `Value: ${mergedValue}`
),
h(
HLText,
{
size: 'md',
weight: 'medium',
},
() => `Swatch Index: ${editorDeleteIndex ?? 'N/A'}`
),
h(HLSwatchTile, {
value: typeof value === 'string' ? value : value.value8,
shape: 'rectangle',
size: 'lg',
}),
]
),
}
),
duration: 10000,
})
}
export const handleSwatchAdd = (sectionKey: string, sectionIndex: number, value: string | HLColorSwatch) => {
console.log('handleSwatchAdd: ', sectionKey, sectionIndex, value)
openNotification('add', sectionKey, sectionIndex, value)
}
export const handleSwatchEdit = (sectionKey: string, sectionIndex: number, editIndex: number, value: string | HLColorSwatch) => {
console.log('handleSwatchEdit: ', sectionKey, sectionIndex, editIndex, value)
openNotification('edit', sectionKey, sectionIndex, value, editIndex)
}
export const handleSwatchDelete = (sectionKey: string, sectionIndex: number, deleteIndex: number, value: string | HLColorSwatch) => {
console.log('handleSwatchDelete: ', sectionKey, sectionIndex, deleteIndex, value)
openNotification('delete', sectionKey, sectionIndex, value, deleteIndex)
}Default Swatches
Spread defaultColorSections to include the built-in default palette alongside your own sections.
<template>
<HLColorPicker id="basic-color-picker" :swatches="colorpickerSections" :width="394" />
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
import { colorpickerSections } from './options'
</script>import type { HLColorPickerSections } from '@platform-ui/highrise'
import { defaultColorSections } from '@platform-ui/highrise'
export const colorpickerSections: HLColorPickerSections[] = [
{
key: 'brand',
label: 'Brand Colors',
swatches: ['var(--primary-500)', 'var(--primary-600)', 'var(--primary-700)', 'var(--primary-800)', 'var(--primary-900)'],
showAddButton: false,
showTooltip: 'value',
},
...defaultColorSections,
{
key: 'custom',
label: 'Custom Colors',
swatches: ['var(--green-100)', 'var(--green-200)', 'var(--green-300)', 'var(--green-400)', 'var(--green-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
]Tooltip Types
The showTooltip property controls what information is displayed when hovering over a color swatch. It has four possible values:
name: Shows only the color's label in the tooltipvalue: Shows only the color value and alpha percentage in the tooltipboth: Shows both the name and value information If the color has a label: Shows the label in the header and the color value with alpha below If the color has no label: Shows just the color value with alphafalse: No tooltip will appear when hovering over the color swatch
<template>
<HLColorPicker id="basic-color-picker" :swatches="tooltipSections" :width="392" />
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
import { tooltipSections } from './options'
</script>import type { HLColorPickerSections } from '@platform-ui/highrise'
export const tooltipSections: HLColorPickerSections[] = [
{
key: 'custom1',
label: 'Show Name',
swatches: [
{
value: '#22C55E',
value8: '#22C55EFF',
alpha: 100,
label: 'Success Green',
},
{
value: '#16A34A',
value8: '#16A34AFF',
alpha: 100,
label: 'Forest Green',
},
{
value: '#15803D',
value8: '#15803DFF',
alpha: 100,
label: 'Deep Green',
},
{
value: '#166534',
value8: '#166534FF',
alpha: 100,
label: 'Dark Green',
},
{
value: '#14532D',
value8: '#14532DFF',
alpha: 100,
label: 'Pine Green',
},
{
value: '#14532D',
value8: '#14532DFE',
alpha: 99,
label: 'Pine Green v2',
custom: '{{ customValues.pine.green.v2 }}',
},
],
showAddButton: true,
showEyeDropper: true,
showTransparentSwatch: true,
showTooltip: 'name',
editable: true,
},
{
key: 'custom2',
label: 'Show Value',
swatches: [
{
value: '#3B82F6',
value8: '#3B82F6FF',
alpha: 100,
label: 'Primary Blue',
},
{
value: '#2563EB',
value8: '#2563EBFF',
alpha: 100,
label: 'Royal Blue',
},
{
value: '#1D4ED8',
value8: '#1D4ED8FF',
alpha: 100,
label: 'Deep Blue',
},
{
value: '#1E40AF',
value8: '#1E40AFFF',
alpha: 100,
label: 'Navy Blue',
},
{
value: '#1E3A8A',
value8: '#1E3A8AFF',
alpha: 100,
label: 'Dark Blue',
},
{
value: '#1E3A8A',
value8: '#1E3A8AFE',
alpha: 99,
label: 'Dark Blue v2',
custom:
'{{ customValues.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2.darkBlue.v2 }}',
},
],
showAddButton: true,
showEyeDropper: true,
showTransparentSwatch: true,
showTooltip: 'value',
editable: true,
},
{
key: 'custom3',
label: 'Show Both',
swatches: [
{
value: '#EF4444',
value8: '#EF4444FF',
alpha: 100,
label: 'Bright Red',
},
{
value: '#DC2626',
value8: '#DC2626FF',
alpha: 100,
label: 'Fire Red',
},
{
value: '#B91C1C',
value8: '#B91C1CFF',
alpha: 100,
label: 'Ruby Red',
},
{
value: '#991B1B',
value8: '#991B1BFF',
alpha: 100,
label: 'Dark Red',
},
{
value: '#7F1D1D',
value8: '#7F1D1DFF',
alpha: 100,
label: 'Deep Red',
},
{
value: '#7F1D1D',
value8: '#7F1D1DFE',
alpha: 99,
label: 'Deep Red v2',
custom:
'{{ customValues.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2.deepRed.v2 }}',
},
],
showAddButton: true,
showEyeDropper: true,
showTransparentSwatch: true,
showTooltip: 'both',
editable: true,
},
]Different Swatch Shapes
Control swatch appearance with swatch-shape and swatch-size on the picker (they set the default square/circle/rectangle shape and size for all swatches), then override individual tiles with overrideTileShape per section or per swatch. The example below sets swatch-size="3xs" and uses per-swatch overrideTileShape.
<template>
<!-- swatch-shape sets the default for every tile; overrideTileShape (in options) overrides individual ones -->
<HLColorPicker id="basic-color-picker" swatch-shape="circle" swatch-size="3xs" :width="392" :swatches="swatches" />
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
import { swatches } from './options'
</script>import type { HLColorPickerSections } from '@platform-ui/highrise'
export const swatches: HLColorPickerSections[] = [
{
key: 'custom1',
label: 'Show Name',
swatches: [
{
value: '#22C55E',
value8: '#22C55EFF',
alpha: 100,
label: 'Success Green',
overrideTileShape: 'circle',
},
{
value: '#16A34A',
value8: '#16A34AFF',
alpha: 100,
label: 'Forest Green',
},
{
value: '#15803D',
value8: '#15803DFF',
alpha: 100,
label: 'Deep Green',
overrideTileShape: 'rectangle',
},
{
value: '#166534',
value8: '#166534FF',
alpha: 100,
label: 'Dark Green',
},
{
value: '#14532D',
value8: '#14532DFF',
alpha: 100,
label: 'Pine Green',
},
],
showAddButton: true,
showEyeDropper: true,
showTransparentSwatch: true,
showTooltip: 'name',
editable: true,
overrideTileShape: 'rectangle',
},
{
key: 'custom2',
label: 'Show Value',
swatches: [
{
value: '#3B82F6',
value8: '#3B82F6FF',
alpha: 100,
label: 'Primary Blue',
},
{
value: '#2563EB',
value8: '#2563EBFF',
alpha: 100,
label: 'Royal Blue',
},
{
value: '#1D4ED8',
value8: '#1D4ED8FF',
alpha: 100,
label: 'Deep Blue',
},
{
value: '#1E40AF',
value8: '#1E40AFFF',
alpha: 100,
label: 'Navy Blue',
},
{
value: '#1E3A8A',
value8: '#1E3A8AFF',
alpha: 100,
label: 'Dark Blue',
},
],
showAddButton: true,
showEyeDropper: true,
showTransparentSwatch: true,
showTooltip: 'value',
editable: true,
},
]Popover Behavior
For swatch and picker types the picker opens in a popover. Tune it with:
placement— where the popover opens relative to the trigger (anyHLPopoverPlacement, defaultbottom-start).autoCloseOnSelect— close the popover as soon as a color is selected (defaultfalse, so it stays open for multiple picks).to— the teleport target for the popover. Pass a CSS selector or element to mount it inside a specific container, orfalseto render it in place (useful inside scrolling/overflow-hidden containers).
<template>
<HLColorPicker
id="popover-behavior-demo"
placement="right-start"
:auto-close-on-select="true"
:to="false"
:swatches="swatches"
/>
</template>
<script setup lang="ts">
import { HLColorPicker } from '@platform-ui/highrise'
import { swatches } from './options'
</script>import type { HLColorPickerSections } from '@platform-ui/highrise'
export const swatches: HLColorPickerSections[] = [
{
key: 'brand',
label: 'Brand Colors',
swatches: ['var(--primary-500)', 'var(--success-500)', 'var(--warning-500)', 'var(--error-500)'],
showAddButton: false,
},
]Custom Trigger
Use the #trigger slot to replace the default swatch trigger with your own element.
<template>
<HLColorPicker id="basic-color-picker" :width="394" :swatches="swatches">
<template #trigger>
<HLButton id="cp-trigger-1" size="sm" variant="secondary" color="blue"> Select Color </HLButton>
</template>
</HLColorPicker>
</template>
<script setup lang="ts">
import { HLColorPicker, HLButton } from '@platform-ui/highrise'
import { swatches } from './options'
</script>import type { HLColorPickerSections } from '@platform-ui/highrise'
export const swatches: HLColorPickerSections[] = [
{
key: 'custom',
label: 'Custom Colors',
swatches: ['var(--green-100)', 'var(--green-200)', 'var(--green-300)', 'var(--green-400)', 'var(--green-500)'],
},
]Custom Add Button Slot
Use the #swatchAddButton slot to customize the per-section Add button; it receives sectionKey and sectionIndex.
<template>
<HLColorPicker id="basic-color-picker" :width="394" :swatches="colorpickerSections">
<template #swatchAddButton="{ sectionKey, sectionIndex }">
<HLButton :id="`${sectionKey}-${sectionIndex}`" size="3xs" color="blue" variant="secondary">
{{ sectionIndex }}. {{ sectionKey }}
</HLButton>
</template>
</HLColorPicker>
</template>
<script setup lang="ts">
import { HLColorPicker, HLButton } from '@platform-ui/highrise'
import { colorpickerSections } from './options'
</script>import type { HLColorPickerSections } from '@platform-ui/highrise'
export const colorpickerSections: HLColorPickerSections[] = [
{
key: 'brand',
label: 'Brand Colors',
swatches: ['var(--primary-500)', 'var(--primary-600)', 'var(--primary-700)', 'var(--primary-800)', 'var(--primary-900)'],
showAddButton: false,
showTooltip: 'value',
},
{
key: 'default',
label: 'Default Colors',
swatches: ['var(--gray-100)', 'var(--gray-200)', 'var(--gray-300)', 'var(--gray-400)', 'var(--gray-500)'],
showAddButton: true,
showTransparentSwatch: true,
showEyeDropper: true,
showTooltip: 'both',
},
{
key: 'custom',
label: 'Custom Colors',
swatches: ['var(--green-100)', 'var(--green-200)', 'var(--green-300)', 'var(--green-400)', 'var(--green-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
{
key: 'blues',
label: 'Blues',
swatches: ['var(--indigo-100)', 'var(--indigo-200)', 'var(--indigo-300)', 'var(--indigo-400)', 'var(--indigo-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
{
key: 'pinks',
label: 'Pinks',
swatches: ['var(--pink-100)', 'var(--pink-200)', 'var(--pink-300)', 'var(--pink-400)', 'var(--pink-500)'],
showAddButton: true,
showEyeDropper: true,
showTooltip: 'name',
editable: true,
},
]Accessibility
- Label the picker via
aria-label/aria-labelledbyand expose the chosen color witharia-valuetext. - Tie contrast guidance or validation hints through
aria-describedby, and togglearia-invalidwhen a color is rejected. - When a palette popover opens, keep the trigger’s
aria-expanded/aria-controlsin sync with the panel id.
Props
| Name | Type | Default | Description |
|---|---|---|---|
| id * | string | undefined | undefined | The unique identifier for the color picker |
| value | string | HLColorSwatch | '#000000ff' | The current color value |
| autoCloseOnSelect | boolean | false | Whether to close the picker after color selection |
| forwardPickerUpdates | boolean | false | When true, emit update:picker to consumers when the picker value changes in swatch mode (add/edit flow) as well |
| pickerOptions | HLColorPickerOptions | defaultPickerOpts | Configuration options for the color picker |
| placement | 'top' | 'bottom' | 'left' | 'right' | 'top-start' | 'top-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end' | 'bottom-start' | 'bottom-end' as HLPopoverPlacement | 'bottom-start' | Placement of the color picker |
| swatches | HLColorPickerSections[] | [] | Array of color section configurations |
| swatchShape | 'square' | 'circle' | 'rectangle' as HLSwatchTileShape | 'square' | The shape of color swatches |
| swatchSize | 'lg' | 'md' | 'sm' | 'xs' | '2xs' | '3xs' as HLSwatchTileSize | 'xs' | The size of color swatches |
| trigger | 'click' | 'hover' | 'focus' | 'manual' as HLPopoverTrigger | 'click' | The trigger action for the color-picker to open |
| type | 'swatch' | 'picker' | 'inline-picker' as HLColorPickerType | 'swatch' | The type of color picker to display |
| width | number | 298 | Width of the color picker in pixels |
| to | string | HTMLElement | false | undefined | Teleport target for the color picker popover. Pass a CSS selector or HTMLElement to mount the picker inside a specific container. Pass false to disable teleporting. |
Types
export type HLColorPickerSections = {
key: string
label: string | false
swatches: Array<HLColorSwatch | string>
showAddButton?: boolean
showTransparentSwatch?: boolean
showEyeDropper?: boolean
showTooltip?: 'name' | 'value' | 'both' | false
editable?: boolean
overrideTileShape?: 'square' | 'circle' | 'rectangle'
}export type HLColorPickerOptions = {
// Format to show by default in the color picker
defaultPickerFormat?: 'HEX' | 'RGB' | 'HSL' | 'HSB' | 'Custom'
// Available format options in the dropdown
pickerFormatOptions?: Array<'HEX' | 'RGB' | 'HSL' | 'HSB' | 'Custom'>
// Show alpha/opacity control
showAlpha?: boolean
// Show save/cancel buttons
showCTA?: boolean
// Show eyedropper tool
showEyeDropper?: boolean
// Show hue slider
showHue?: boolean
// Show input fields for color values
showInputFields?: boolean
}// Default values
const defaultPickerOpts = {
defaultPickerFormat: 'HEX',
pickerFormatOptions: ['HEX', 'RGB', 'HSL', 'HSB', 'Custom'],
showAlpha: true,
showCTA: true,
showEyeDropper: true,
showHue: true,
showInputFields: true,
} as constexport type HLColorSwatch = {
alpha: number
value: string
value8: string
label?: string
oldValue?: string | HLColorSwatch
overrideTileShape?: 'square' | 'circle' | 'rectangle'
custom?: false | string
inputType?: 'HEX' | 'RGB' | 'HSL' | 'HSB' | 'Custom'
}Supported Color Formats
The color picker supports the following formats:
| Format | Example | Description |
|---|---|---|
| HEX | #FF0000 | 6-digit (RGB) hexadecimal |
| HEXA | #FF0000FF | 8-digit (RGBA) hexadecimal |
| RGB | rgb(255, 0, 0) | RGB values (0-255) |
| RGBA | rgba(255, 0, 0, 1) | RGB with alpha channel (0-1) |
| HSL | hsl(0, 100%, 50%) | Hue (0-360), Saturation (0-100%), Lightness (0-100%) |
| HSLA | hsla(0, 100%, 50%, 1) | HSL with alpha channel (0-1) |
| HSB | hsb(0, 100%, 100%) | Hue (0-360), Saturation (0-100%), Brightness (0-100%) |
| Custom | var(--primary-500) | {{ location.customValue }} | Custom variable names |
Emits
Note: When using @update:picker, use rest parameters or an optional 7th parameter so your handler works both when forwardPickerUpdates is true (7 arguments) and when it is false or when using non-swatch types (6 arguments).
| Name | Parameters | Description |
|---|---|---|
@select | (selectedValue: string | HLColorSwatch, sectionKey?: string, sectionIndex?: number, tileIndex?: number) => void | Emitted when a color is selected. For type="picker" / type="inline-picker", selectedValue is the HEXA string. For type="swatch", selectedValue is the chosen swatch and the remaining arguments identify its section and position. |
@swatch:add | (sectionKey: string, sectionIndex: number, newValue: HLColorSwatch) => void | Emitted when a new swatch is added; index not necessary as new swatches are added to the start of the array; swatches array is not updated in case of custom value |
@swatch:delete | (sectionKey: string, sectionIndex: number, deleteIndex: number, deletedValue: string | HLColorSwatch) => void | Emitted when a swatch is deleted |
@swatch:edit | (sectionKey: string, sectionIndex: number, editIndex: number, updatedValue: string | HLColorSwatch) => void | Emitted when a swatch is edited |
@swatch:reset | (sectionKey: string, sectionIndex: number, resetIndex: number, revertedValue: string | HLColorSwatch) => void | Emitted when a swatch is deleted |
@update:picker | (value: string, value8: string, alpha: number, inputType?: PickerInputType, label?: string, custom?: string | false, isEditing?: boolean) => void | Emitted when picker value changes. Always emitted for type="picker" and type="inline-picker". For type="swatch", also emitted during add/edit flow when forwardPickerUpdates is true. The 7th argument isEditing is true when the update is from editing an existing swatch. |
@update:picker:back | (save?: boolean, deleteColor?: boolean, custom?: boolean) => void | Emitted when the user navigates back from the picker (swatch add/edit flow). Only when forwardPickerUpdates is true. save is true when saving, deleteColor when deleting the color being edited, custom for custom value. |
@update:picker:close | () => void | Emitted when the picker popover is closed. Only when forwardPickerUpdates is true. |
@update:show | (value: boolean) => void | Emitted when picker visibility changes |
@update:swatches | (value: HLColorPickerSections[]) => void | Emitted when swatches are updated |
Slots
| Name | Parameters | Description |
|---|---|---|
| trigger | () | Custom trigger element. If not provided, defaults to a color swatch with the current value |
| swatchAddButton | (sectionKey: string, sectionIndex: number) | Slot to replace the "Add" button in each section. Will be available only if showAddButton is enabled for the corresponding section |