tokenui
componentcolor-swatchsource: ok · hit
ColorSwatch
A primitive component for displaying a single color swatch with an optional hover label.
npx shadcn add "https://www.tokenui.dev/r/color-swatch.json"free
No selection tags yet — empty means no evidence, not lack of support.
Files1 · source cached 10/8/2026, 4:04:45 PM
registry/components/color-swatch.tsx
"use client";
import type { HTMLAttributes } from "react";
import * as React from "react";
import { cn } from "@/lib/utils";
type ColorSwatchProps = HTMLAttributes<HTMLDivElement> & {
/** Color value (hex, rgb, hsl, etc.) */
value: string;
/** Optional name/label for the color */
name?: string;
};
const ColorSwatchContext = React.createContext<{
value: string;
name?: string;
} | null>(null);
function useColorSwatch() {
return React.useContext(ColorSwatchContext);
}
const ColorSwatch = React.forwardRef<HTMLDivElement, ColorSwatchProps>(
({ value, name, className, children, ...props }, forwardedRef) => {
return (
<div
ref={forwardedRef}
className={cn(
"group relative flex-1 transition-all duration-200 ease-out",
className,
)}
style={{ backgroundColor: value }}
title={name || value}
{...props}
>
<ColorSwatchContext.Provider value={{ value, name }}>
{children}
</ColorSwatchContext.Provider>
</div>
);
},
);
ColorSwatch.displayName = "ColorSwatch";
type ColorSwatchLabelProps = HTMLAttributes<HTMLDivElement>;
const ColorSwatchLabel = React.forwardRef<
HTMLDivElement,
ColorSwatchLabelProps
>(({ className, children, ...props }, forwardedRef) => {
return (
<div
ref={forwardedRef}
className={cn(
"pointer-events-none absolute inset-0 flex items-center justify-center",
"opacity-0 transition-opacity group-hover:opacity-100",
className,
)}
{...props}
>
<div className="rounded bg-black/70 px-2 py-1 font-mono text-xs text-white shadow-sm">
{children}
</div>
</div>
);
});
ColorSwatchLabel.displayName = "ColorSwatchLabel";
type ColorSwatchPartPosition =
| "top-left"
| "top-right"
| "bottom-left"
| "bottom-right"
| "center";
type ColorSwatchPartProps = HTMLAttributes<HTMLDivElement> & {
position?: ColorSwatchPartPosition;
};
const positionVariants: Record<ColorSwatchPartPosition, string> = {
"top-left": "top-2 left-2 text-left",
"top-right": "top-2 right-2 text-right",
"bottom-left": "bottom-2 left-2 text-left",
"bottom-right": "bottom-2 right-2 text-right",
center: "top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center",
};
const ColorSwatchPart = React.forwardRef<HTMLDivElement, ColorSwatchPartProps>(
(
{ className, position = "bottom-right", children, ...props },
forwardedRef,
) => {
return (
<div
ref={forwardedRef}
className={cn(
"absolute flex flex-col p-1 text-sm font-medium",
positionVariants[position],
className,
)}
{...props}
>
{children}
</div>
);
},
);
ColorSwatchPart.displayName = "ColorSwatchPart";
export {
ColorSwatch,
useColorSwatch,
ColorSwatchLabel,
ColorSwatchPart,
type ColorSwatchProps,
type ColorSwatchLabelProps,
type ColorSwatchPartProps,
};