Color Swatch
A color swatch component for displaying color values with support for transparency and various sizes.
import { ColorSwatch } from "@/components/ui/color-swatch";
export function ColorSwatchDemo() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center gap-3">
<ColorSwatch color="#3b82f6" />
<span className="font-medium text-sm">Primary Blue</span>
</div>
<div className="flex items-center gap-3">
<ColorSwatch color="#ef4444" size="sm" />
<ColorSwatch color="#ef4444" size="default" />
<ColorSwatch color="#ef4444" size="lg" />
<span className="font-medium text-sm">Different Sizes</span>
</div>
<div className="flex items-center gap-3">
<ColorSwatch color="rgba(59, 130, 246, 0.5)" />
<span className="font-medium text-sm">Semi-transparent Blue</span>
</div>
<div className="flex items-center gap-3">
<span className="font-medium text-sm">Color Palette</span>
<div className="flex gap-2">
<ColorSwatch color="#ef4444" />
<ColorSwatch color="#f97316" />
<ColorSwatch color="#eab308" />
<ColorSwatch color="#22c55e" />
<ColorSwatch color="#3b82f6" />
<ColorSwatch color="#8b5cf6" />
<ColorSwatch color="#ec4899" />
</div>
</div>
<div className="flex items-center gap-3">
<ColorSwatch color="#ef4444" disabled />
<span className="font-medium text-sm">Disabled</span>
</div>
</div>
);
}
Installation
CLI
npx shadcn@latest add "https://diceui.com/r/color-swatch"
Manual
Install the following dependencies:
npm install @radix-ui/react-slot class-variance-authority
Copy and paste the following code into your project.
"use client";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "@/lib/utils";
const colorSwatchVariants = cva(
"box-border rounded-sm border shadow-sm [background-clip:padding-box] data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
{
variants: {
size: {
default: "size-8",
sm: "size-6",
lg: "size-12",
},
},
defaultVariants: {
size: "default",
},
},
);
function getIsCssColor(v: string): boolean {
try {
return typeof CSS !== "undefined" && typeof CSS.supports === "function"
? CSS.supports("color", v)
: true;
} catch {
return false;
}
}
function getHasAlpha(v: string): boolean {
const s = v.trim().toLowerCase();
if (s === "transparent") return true;
if (/^#(?:[0-9a-f]{4}|[0-9a-f]{8})$/i.test(s)) return true;
if (/\b(?:rgba|hsla)\s*\(/i.test(s)) return true;
if (
/\b(?:rgb|hsl|lab|lch|oklab|oklch|color)\s*\([^)]*\/\s*[\d.]+%?\s*\)/i.test(
s,
)
) {
return true;
}
return false;
}
interface ColorSwatchProps
extends Omit<React.ComponentProps<"div">, "children">,
VariantProps<typeof colorSwatchVariants> {
color?: string;
asChild?: boolean;
disabled?: boolean;
withoutTransparency?: boolean;
}
function ColorSwatch({
color,
size = "default",
asChild = false,
disabled = false,
withoutTransparency = false,
className,
style,
...props
}: ColorSwatchProps) {
const colorValue = color?.trim();
const backgroundStyle = React.useMemo<React.CSSProperties>(() => {
if (!colorValue) {
return {
background:
"linear-gradient(to bottom right, transparent calc(50% - 1px), hsl(var(--destructive)) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) no-repeat",
};
}
if (!getIsCssColor(colorValue)) {
return { backgroundColor: "transparent" };
}
if (!withoutTransparency && getHasAlpha(colorValue)) {
return {
background: `linear-gradient(${colorValue}, ${colorValue}), repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%) 0% 50% / 10px 10px`,
};
}
return { backgroundColor: colorValue };
}, [colorValue, withoutTransparency]);
const ariaLabel = !colorValue
? "No color selected"
: `Color swatch: ${colorValue}`;
const Primitive = asChild ? Slot : "div";
return (
<Primitive
role="img"
aria-label={ariaLabel}
aria-disabled={disabled || undefined}
data-disabled={disabled ? "" : undefined}
data-slot="color-swatch"
{...props}
className={cn(colorSwatchVariants({ size }), className)}
style={{
...backgroundStyle,
forcedColorAdjust: "none",
...style,
}}
/>
);
}
export { ColorSwatch };
Usage
Import the component and use it to display color values.
import { ColorSwatch } from "@/components/ui/color-swatch";
<ColorSwatch value="#3b82f6" />
Examples
Different Sizes
The color swatch component supports three different sizes: sm
, default
, and lg
.
import { ColorSwatch } from "@/components/ui/color-swatch";
const colors = [
"#ef4444", // red
"#f97316", // orange
"#eab308", // yellow
"#22c55e", // green
"#3b82f6", // blue
];
export function ColorSwatchSizesDemo() {
return (
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-2">
<span className="font-medium text-sm">Small (sm)</span>
<div className="flex gap-2">
{colors.map((color, index) => (
<ColorSwatch key={index} color={color} size="sm" />
))}
</div>
</div>
<div className="flex flex-col gap-2">
<span className="font-medium text-sm">Default</span>
<div className="flex gap-2">
{colors.map((color, index) => (
<ColorSwatch key={index} color={color} size="default" />
))}
</div>
</div>
<div className="flex flex-col gap-2">
<span className="font-medium text-sm">Large (lg)</span>
<div className="flex gap-2">
{colors.map((color, index) => (
<ColorSwatch key={index} color={color} size="lg" />
))}
</div>
</div>
</div>
);
}
Transparency Support
The color swatch automatically detects transparent colors and displays them with a checkerboard background pattern.
import { ColorSwatch } from "@/components/ui/color-swatch";
export function ColorSwatchTransparencyDemo() {
return (
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-2">
<span className="font-medium text-sm">Alpha Transparency</span>
<div className="flex gap-2">
<ColorSwatch color="rgba(59, 130, 246, 1)" />
<ColorSwatch color="rgba(59, 130, 246, 0.8)" />
<ColorSwatch color="rgba(59, 130, 246, 0.6)" />
<ColorSwatch color="rgba(59, 130, 246, 0.4)" />
<ColorSwatch color="rgba(59, 130, 246, 0.2)" />
</div>
</div>
<div className="flex flex-col gap-2">
<span className="font-medium text-sm">HSLA Colors</span>
<div className="flex gap-2">
<ColorSwatch color="hsla(220, 91%, 60%, 1)" />
<ColorSwatch color="hsla(220, 91%, 60%, 0.75)" />
<ColorSwatch color="hsla(220, 91%, 60%, 0.5)" />
<ColorSwatch color="hsla(220, 91%, 60%, 0.25)" />
<ColorSwatch color="hsla(220, 91%, 60%, 0.1)" />
</div>
</div>
<div className="flex flex-col gap-2">
<span className="font-medium text-sm">
Without Transparency Pattern
</span>
<div className="flex gap-2">
<ColorSwatch color="rgba(239, 68, 68, 0.8)" withoutTransparency />
<ColorSwatch color="rgba(34, 197, 94, 0.6)" withoutTransparency />
<ColorSwatch color="rgba(139, 92, 246, 0.4)" withoutTransparency />
</div>
</div>
<div className="flex flex-col gap-2">
<span className="font-medium text-sm">
With Transparency Pattern (Default)
</span>
<div className="flex gap-2">
<ColorSwatch color="rgba(239, 68, 68, 0.8)" />
<ColorSwatch color="rgba(34, 197, 94, 0.6)" />
<ColorSwatch color="rgba(139, 92, 246, 0.4)" />
</div>
</div>
</div>
);
}
API Reference
ColorSwatch
A color swatch component that displays a color value with optional transparency support.
Prop
Type
Data Attribute | Value |
---|---|
[data-disabled] | Present when the component is disabled. |
[data-slot] | Always set to 'color-swatch' for identification. |
Accessibility
The color swatch component includes proper accessibility features:
- ARIA Label: Automatically generates descriptive
aria-label
text based on the color value - Role: Uses
role="img"
to indicate it's an image representation of a color - Disabled State: Properly handles disabled state with appropriate visual and interaction changes
Screen Reader Support
- When a color value is provided, the
aria-label
reads "Color swatch: [color-value]" - When no color is selected, the
aria-label
reads "No color selected"
Color Format Support
The color swatch component supports various color formats:
- HEX:
#3b82f6
- RGB:
rgb(59, 130, 246)
- RGBA:
rgba(59, 130, 246, 0.5)
- HSL:
hsl(217, 91%, 60%)
- HSLA:
hsla(217, 91%, 60%, 0.5)
- Named Colors:
blue
,red
, etc.
Transparency Detection
The component automatically detects transparent colors by checking for:
rgba()
orhsla()
function notation- RGB/HSL with 4 values (including alpha)
- Any color format that includes transparency information
When transparency is detected, a checkerboard pattern is displayed behind the color to show the transparency effect. Use the withoutTransparency
prop to disable this behavior.