Easy to Use
Simple v-model API with rounded corners, smooth transitions, and a refined UI
A lightweight, accessible color picker component for Vue 3
Selected color: #ff0000
English locale: #3b82f6
Japanese locale: #10b981
<template>
<colorPicker
v-model="color"
locale="en-US"
:messages="{ moreColors: 'Custom Label...' }"
/>
</template>The panel auto-detects available viewport space by default. You can lock it to any side with the placement prop.
Pinned to top-end: #f59e0b
<colorPicker v-model="color" placement="top-end" />
<colorPicker v-model="color" placement="bottom" /> <!-- vertical locked, horizontal auto -->npm install vcolorpicker -SRegister the plugin in main.js:
import { createApp } from 'vue'
import vcolorpicker from 'vcolorpicker'
import App from './App.vue'
const app = createApp(App)
app.use(vcolorpicker)
app.mount('#app')Use in your component:
<template>
<colorPicker v-model="color" />
</template>
<script setup>
import { ref } from 'vue'
const color = ref('#ff0000')
</script>| Prop | Type | Default | Description |
|---|---|---|---|
v-model / modelValue | string | — | Current color value |
defaultColor | string | #000000 | Color the "Default" button resets to |
disabled | boolean | false | Disabled state |
locale | 'zh-CN' | 'en-US' | 'ja-JP' | Auto | Built-in panel labels; follows <html lang> / navigator.language when omitted |
messages | Partial<ColorPickerMessages> | — | Override built-in labels with custom text |
placement | ColorPickerPlacement | 'auto' | Panel placement: 'auto', 'top', 'bottom', 'top-start', 'top-end', 'bottom-start', 'bottom-end'. 'auto' picks based on available viewport space; directional values lock that axis |
| Event | Payload | Description |
|---|---|---|
change | (color: string) | Color value changed |
update:modelValue | (color: string) | v-model sync event |
open | — | Panel opened |
close | — | Panel closed (outside click, Esc, or after selection) |
hover | (color: string) | Swatch hover; emits empty string on leave |
<colorPicker v-model="color" @change="onColorChange" />Methods exposed via template ref:
<script setup lang="ts">
import { ref } from 'vue'
import type { ColorPickerInstance } from 'vcolorpicker'
const pickerRef = ref<ColorPickerInstance>()
const color = ref('#ff0000')
const openProgrammatically = () => pickerRef.value?.open()
</script>
<template>
<colorPicker ref="pickerRef" v-model="color" />
<button @click="openProgrammatically">Open Panel</button>
</template>| Method | Description |
|---|---|
open() | Open the panel (no-op when disabled) |
close() | Close the panel |
focus() | Move focus back to the trigger button |
TabEnter / Space activates; ↑ / ↓ on a focused trigger also opens the panelEsc closes the panel and returns focus to the triggerrole="button", aria-haspopup="dialog", aria-expanded; the panel uses role="dialog"; every swatch has aria-label="#RRGGBB":focus-visible, so mouse users are not distracteddocument / navigator are unavailable (Node SSR), the initial locale falls back to zh-CN (or the explicit locale prop) so server and client render identically — no hydration mismatchonMounted. To avoid a post-mount flicker from Chinese to another language, pass an explicit locale prop in SSR projectsMutationObserver watching <html lang> is a module-level singleton — multiple component instances share a single observerOverride these custom properties to theme the component without piercing selectors:
.m-colorPicker {
--vcp-swatch-size: 15px;
--vcp-panel-width: 190px;
--vcp-panel-bg: #fff;
--vcp-panel-border: 1px solid #ddd;
--vcp-panel-radius: 2px;
--vcp-panel-shadow: 0 8px 24px rgba(0, 0, 0, .18);
--vcp-panel-padding: 10px;
--vcp-text-color: #333;
--vcp-focus-color: #4e81bb;
--vcp-transition: .3s ease;
--vcp-z-index: 10000;
}Example — dark theme:
.dark .m-colorPicker {
--vcp-panel-bg: #1f1f1f;
--vcp-panel-border: 1px solid #333;
--vcp-text-color: #eee;
}Types exported from the package:
import type {
ColorPickerProps,
ColorPickerEmits,
ColorPickerExposed,
ColorPickerInstance,
ColorPickerLocale,
ColorPickerMessages,
ColorPickerPlacement
} from 'vcolorpicker'Yes. vColorPicker is built for Vue 3 and can be used with a standard v-model API.
Yes. Set locale="zh-CN", locale="en-US" or locale="ja-JP" to use built-in translations, or pass messages to override any label.
Yes. The package ships with full type declarations — props, emits, instance methods, and helper types.
Yes. Clicking More Colors... opens the native HTML5 color input in supported browsers.
Yes. Tab to focus, Enter / Space to activate, Esc to close, and ARIA roles / labels are all wired up.