Dice UI
Components

Color Swatch

A color swatch component for displaying color values with support for transparency and various sizes.

API
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 AttributeValue
[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() or hsla() 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.