refactor(nexus): restyle theme palette grid with design.md language

This commit is contained in:
Nexus Dev 2026-04-11 16:27:24 +00:00
parent 0c1496d2fe
commit d3141ac534

View file

@ -1,6 +1,11 @@
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
/**
* Palette role shape emitted by the theme-generation workshop.
* Each role carries both a dark and light variant resolved as OKLCH + hex
* alongside a WCAG AA pass/fail flag computed against the generated
* background.
*/
export interface PaletteRole { export interface PaletteRole {
name: string; name: string;
dark: { oklch: string; hex: string; wcagAA: boolean }; dark: { oklch: string; hex: string; wcagAA: boolean };
@ -18,9 +23,9 @@ const ROLE_LABELS: Record<string, string> = {
surface: "Surface", surface: "Surface",
overlay: "Overlay", overlay: "Overlay",
text: "Text", text: "Text",
"accent-1": "Accent-1", "accent-1": "Accent 1",
"accent-2": "Accent-2", "accent-2": "Accent 2",
"accent-3": "Accent-3", "accent-3": "Accent 3",
}; };
function Swatch({ function Swatch({
@ -34,34 +39,35 @@ function Swatch({
const label = ROLE_LABELS[role.name] ?? role.name; const label = ROLE_LABELS[role.name] ?? role.name;
return ( return (
<div className="flex flex-col items-center gap-1" style={{ minWidth: 56 }}> <div
className="flex flex-col gap-2 rounded-sm border border-border bg-card p-2"
style={{ minWidth: 96 }}
>
<div <div
className="rounded-md border border-border" className="rounded-sm border border-border"
style={{ style={{
width: 40, height: 44,
height: 40,
backgroundColor: entry.hex, backgroundColor: entry.hex,
minWidth: 40,
minHeight: 40,
}} }}
title={`${label}: ${entry.hex}`} title={`${label}: ${entry.hex}`}
aria-label={`${label} swatch ${entry.hex}`} aria-label={`${label} swatch ${entry.hex}`}
/> />
<span className="font-mono text-xs text-muted-foreground"> <div className="flex flex-col gap-0.5">
{entry.hex} <span className="text-[11px] font-semibold uppercase tracking-[0.1em] text-foreground">
</span> {label}
{entry.wcagAA ? ( </span>
<Badge <span className="font-mono text-[11px] text-muted-foreground">
variant="default" {entry.hex}
className="bg-[#40a02b] dark:bg-[#a6e3a1] text-white dark:text-black border-0 text-[10px] px-1.5 py-0" </span>
<span
className={cn(
"text-[10px] font-semibold uppercase tracking-[0.08em]",
entry.wcagAA ? "text-primary" : "text-destructive",
)}
> >
AA {entry.wcagAA ? "AA" : "Fails AA"}
</Badge> </span>
) : ( </div>
<Badge variant="destructive" className="text-[10px] px-1.5 py-0">
Fails AA
</Badge>
)}
</div> </div>
); );
} }
@ -75,8 +81,8 @@ function PaletteRow({
}) { }) {
return ( return (
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<span className="text-xs font-medium text-muted-foreground capitalize"> <span className="text-[12px] font-semibold uppercase tracking-[0.1em] text-muted-foreground">
{variant} {variant === "dark" ? "Dark mode" : "Light mode"}
</span> </span>
<div className="flex flex-row flex-wrap gap-2"> <div className="flex flex-row flex-wrap gap-2">
{palette.map((role) => ( {palette.map((role) => (
@ -89,28 +95,36 @@ function PaletteRow({
export function ThemePaletteGrid({ export function ThemePaletteGrid({
palette, palette,
variant = "dark", variant,
className, className,
}: ThemePaletteGridProps) { }: ThemePaletteGridProps) {
if (palette.length === 0) { if (palette.length === 0) {
return ( return (
<div <div
className={cn( className={cn(
"flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border p-8 text-center", "flex flex-col items-center justify-center gap-2 rounded-sm border border-dashed border-border p-8 text-center",
className, className,
)} )}
> >
<h3 className="text-base font-semibold text-foreground"> <h3 className="text-base font-bold text-foreground">No palette yet</h3>
No palette yet <p className="max-w-xs text-sm text-muted-foreground">
</h3> Pick a seed color to generate a full OKLCH palette with dark and
<p className="text-sm text-muted-foreground max-w-xs"> light variants.
Pick a seed color to generate a full OKLCH palette with dark and light
variants.
</p> </p>
</div> </div>
); );
} }
// When variant is passed explicitly, render only that row. Otherwise show
// both dark and light, so reviewers can compare the generated bundle.
if (variant) {
return (
<div className={cn("flex flex-col gap-4", className)}>
<PaletteRow palette={palette} variant={variant} />
</div>
);
}
return ( return (
<div className={cn("flex flex-col gap-4", className)}> <div className={cn("flex flex-col gap-4", className)}>
<PaletteRow palette={palette} variant="dark" /> <PaletteRow palette={palette} variant="dark" />