<script>
import ColorSelector from '$registry/spelte/color-selector.svelte';
const colors = ['red', 'blue', 'green', 'yellow', 'purple'];
</script>
<ColorSelector {colors} defaultValue="blue" />Installation
pnpm dlx shadcn-svelte@latest add https://spelte.dev/r/color-selector.json<script lang="ts">
import { cn } from '$lib/utils';
interface Props {
colors: string[];
size?: 'default' | 'sm' | 'lg';
defaultValue: string;
name?: string;
onColorSelect?: (color: string) => void;
class?: string;
}
let { colors, size = 'default', defaultValue, name, onColorSelect, class: className }: Props = $props();
const colorMap: Record<string, string> = {
default: 'var(--foreground)',
red: 'var(--color-red-500)',
green: 'var(--color-green-500)',
blue: 'var(--color-blue-500)',
yellow: 'var(--color-yellow-500)',
purple: 'var(--color-purple-500)',
pink: 'var(--color-pink-500)',
indigo: 'var(--color-indigo-500)',
orange: 'var(--color-orange-500)',
teal: 'var(--color-teal-500)',
cyan: 'var(--color-cyan-500)',
lime: 'var(--color-lime-500)',
emerald: 'var(--color-emerald-500)',
violet: 'var(--color-violet-500)',
fuchsia: 'var(--color-fuchsia-500)',
rose: 'var(--color-rose-500)',
sky: 'var(--color-sky-500)',
amber: 'var(--color-amber-500)'
};
let selectedColor = $state('');
let initialized = false;
function handleColorSelect(color: string) {
selectedColor = color;
onColorSelect?.(color);
}
const sizeClass = $derived(
size === 'sm' ? 'size-4' : size === 'lg' ? 'size-6' : 'size-5'
);
$effect(() => {
if (initialized) return;
initialized = true;
selectedColor = defaultValue;
});
function getColorValue(color: string): string {
return colorMap[color] || color;
}
</script>
<div class={cn('flex gap-2', className)}>
{#if name}
<input type="hidden" {name} value={selectedColor} />
{/if}
{#each colors as color}
{@const colorValue = getColorValue(color)}
<button
type="button"
class="{sizeClass} rounded-full cursor-pointer transition-transform duration-200 active:scale-90"
style="background-color: {colorValue}; {selectedColor === color ? `box-shadow: inset 0 0 0 2px var(--background), 0 0 0 2px ${colorValue};` : ''}"
onclick={() => handleColorSelect(color)}
aria-label="Select {color} color"
aria-pressed={selectedColor === color}
></button>
{/each}
</div>
Examples
Size
<script lang="ts">
import ColorSelector from '$registry/spelte/color-selector.svelte';
const colors = ['red', 'blue', 'green', 'yellow', 'purple'];
<\/script>
<div class="flex items-center gap-5">
<ColorSelector {colors} size="sm" defaultValue="red" />
<ColorSelector {colors} defaultValue="blue" />
<ColorSelector {colors} size="lg" defaultValue="green" />
</div>Callback
<script lang="ts">
import ColorSelector from '$registry/spelte/color-selector.svelte';
const colors = ['red', 'blue', 'green', 'yellow', 'purple'];
let selectedColor = $state('purple');
<\/script>
<div class="flex items-center gap-3">
<ColorSelector
{colors}
defaultValue="purple"
onColorSelect={(color) => (selectedColor = color)}
/>
<span class="text-sm text-muted-foreground">
Selected: {selectedColor}
</span>
</div>Props
| Prop | Type | Default | Description |
|---|---|---|---|
colors | string[] | — | Array of color names or hex values |
defaultValue | string | — | Initially selected color |
size | "sm" | "default" | "lg" | "default" | Size of color circles |
name | string | — | Name for hidden form input |
onColorSelect | (color: string) => void | — | Callback when color is selected |
class | string | — | Additional CSS classes |