Components · Data Entry
Color picker
Pick a colour from a selectable palette of presets.
Examples
Size
Disabled
Interactive · click to open the palette — the selected swatch is ringed + checked (probe value #6A1EBB)
<!-- Paste-and-run: save as .html and open in a browser. No build step.
<aha-color-picker> is the SAME shared custom element React and Vue consume.
Defaults to the brand ramp; override with swatches="#hex|#hex". size = small|default|large,
disabled greys the control. The swatch matching value is ringed + checked. Emits a composed `change`. -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/tokens.css">
<script type="module">
import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/icons.js'; // <aha-icon> — the selected-swatch check glyph
import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/aha-color-picker.js'; // registers <aha-color-picker>
</script>
<aha-color-picker id="pick" value="#6A1EBB" size="default"></aha-color-picker>
<aha-color-picker value="#FF4081" size="small"></aha-color-picker>
<aha-color-picker value="#20E8B5" size="large"></aha-color-picker>
<aha-color-picker value="#6A1EBB" disabled></aha-color-picker>
<aha-color-picker value="#0FB5C4" swatches="#0FB5C4|#6A1EBB|#FF4081|#1A1A1A"></aha-color-picker>
<script>
// Plain DOM — no framework. Read e.detail.value off the composed CustomEvent.
document.getElementById('pick').addEventListener('change', (e) => {
console.log('colour:', e.detail.value);
});
</script>
import '@ahaslides-product/design/icons'; // <aha-icon> — the selected-swatch check glyph
import '@ahaslides-product/design/aha-color-picker'; // registers <aha-color-picker>
import { useRef, useEffect } from 'react';
// React 18 needs a thin wrapper; React 19 can use <aha-color-picker> directly.
function AhaColorPicker({ value, swatches, size, disabled, onChange }) {
const ref = useRef();
useEffect(() => {
const el = ref.current;
if (value) el.value = value;
const h = (e) => onChange?.(e.detail.value); // composed CustomEvent
el.addEventListener('change', h);
return () => el.removeEventListener('change', h);
});
return <aha-color-picker ref={ref} swatches={swatches} size={size} disabled={disabled || undefined} />;
}
// usage
<AhaColorPicker value={colour} size="large" onChange={setColour} />
// main.ts — register the element + mark aha-* as custom elements
import '@ahaslides-product/design/icons'; // <aha-icon> — the selected-swatch check glyph
import '@ahaslides-product/design/aha-color-picker';
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('aha-');
// Component.vue
<script setup>
import { ref } from 'vue';
const colour = ref('#6A1EBB');
</script>
<template>
<aha-color-picker
:value.prop="colour"
size="large"
@change="colour = $event.detail.value"
/>
</template>
API
| Prop | Type | Default | Notes |
|---|---|---|---|
value | string | #6A1EBB | Selected colour (hex) — its swatch is ringed + checked |
swatches | string | brand ramp (12) | Pipe-separated hex presets, e.g. "#6A1EBB|#FF4081" |
size | 'small' | 'default' | 'large' | default | Scales trigger + swatch dimensions |
disabled | boolean | false | Greys + inerts the whole control |
open | boolean | false | Panel open state; reflected attribute |
change | CustomEvent<{value}> | — | Composed event; read e.detail.value |
Install
# .npmrc — once: point the @ahaslides-product scope at GitHub Packages
@ahaslides-product:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} # a GitHub token with read:packages
npm i @ahaslides-product/design
import '@ahaslides-product/design/tokens.css'; // once, at the app root
import '@ahaslides-product/design/aha-color-picker'; // registers <aha-color-picker>
Agent feed for this component (absolute, fetchable anywhere): color-picker.agent.json · color-picker.md · color-picker.llms.txt
When to use
When to use
- Color picker — choosing a brand or theme colour from a curated set
- Segmented — picking a labelled option rather than a colour
- Input — an arbitrary free-form value is genuinely needed
Prefer a curated palette over a free spectrum — on-brand results, fewer accessibility misses. Show the current value beside the trigger so the choice is legible.
Surfaces
editor dashboard settings
Spec
Trigger 1px border #E3E3E3, radius 6; current swatch 16/20/24 by size (radius 4) · Panel bg-elevated #FFFFFF, radius 8, 4-col swatch grid · Swatch 22/28/34 by size, radius 4; selected ringed color-primary + check glyph · Selected aria-pressed=true, .on ring + system-check (dark on pale chips) · Disabled bg-container-disabled fill, border-disabled, not-allowed, inert · Motion panel fade + lift; swatch hover scale; check fade (ease-out)