Shadcn/ui theming and component customization — CSS variables, OKLCH colors, dark mode, variants, wrappers. Load for any ticket involving colors, theme, UI layout, or component styling.
75
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Reference for theming and component customization. Components reference semantic CSS variable tokens change the variables to change every component. Read the relevant section, then check the Red Flags and Verification list.
For component architecture and where to import from, see Skill({skill: "frontend-dev"}).
:root (light) and .dark (dark mode).bg-primary, text-muted-foreground, etc.Every color follows the name / name-foreground convention. The base variable is for backgrounds, -foreground is for text/icons on that background.
| Variable | Purpose |
|---|---|
--background / --foreground | Page background and default text |
--card / --card-foreground | Card surfaces |
--primary / --primary-foreground | Primary buttons and actions |
--secondary / --secondary-foreground | Secondary actions |
--muted / --muted-foreground | Muted/disabled states |
--accent / --accent-foreground | Hover and accent states |
--destructive / --destructive-foreground | Error and destructive actions |
--border | Default border color |
--input | Form input borders |
--ring | Focus ring color |
--chart-1 through --chart-5 | Chart/data visualization |
--sidebar-* | Sidebar-specific colors |
--surface / --surface-foreground | Secondary surface |
Colors use OKLCH: --primary: oklch(0.205 0 0) where values are lightness (0–1), chroma (0 = gray), and hue (0–360).
Class-based toggle via .dark on the root element. Atomic CRM wires this
through its own ThemeProvider at src/components/admin/theme-provider.tsx,
which is already mounted from src/components/admin/admin.tsx. To customize
the palette, pass lightTheme / darkTheme props to the <CRM> component
(see src/App.tsx).
# Apply a preset from ui.shadcn.com.
npx shadcn@latest apply --preset a2r6bw
# Positional shorthand also works.
npx shadcn@latest apply a2r6bw
# Switch to a named preset, overwrite existing components.
npx shadcn@latest apply --preset nova
# Preserve existing components instead.
npx shadcn@latest init --preset nova --force --no-reinstall
# Use a custom theme URL.
npx shadcn@latest apply --preset "https://ui.shadcn.com/init?base=radix&style=nova&theme=blue&..."Or edit CSS variables directly in globals.css.
Add variables to the file at tailwindCssFile from npx shadcn@latest info (typically globals.css). Never create a new CSS file for this.
/* 1. Define in the global CSS file. */
:root {
--warning: oklch(0.84 0.16 84);
--warning-foreground: oklch(0.28 0.07 46);
}
.dark {
--warning: oklch(0.41 0.11 46);
--warning-foreground: oklch(0.99 0.02 95);
}/* 2. Register with Tailwind v4 (@theme inline). */
@theme inline {
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
}// 3. Use in components.
<div className="bg-warning text-warning-foreground">Warning</div>--radius controls border radius globally. Components derive values from it (rounded-lg = var(--radius), rounded-md = calc(var(--radius) - 2px)).
Prefer these approaches in order:
<Button variant="outline" size="sm">Click</Button>className<Card className="mx-auto max-w-md">...</Card>Edit the component source to add a variant via cva:
// components/ui/button.tsx
warning: "bg-warning text-warning-foreground hover:bg-warning/90",Compose shadcn/ui primitives into higher-level components:
export function ConfirmDialog({ title, description, onConfirm, children }) {
return (
<AlertDialog>
<AlertDialogTrigger asChild>{children}</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{title}</AlertDialogTitle>
<AlertDialogDescription>{description}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={onConfirm}>Confirm</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
}npx shadcn@latest add button --diff
npx shadcn@latest add button --dry-run # see all affected files
npx shadcn@latest add button --diff button.tsx # diff for a specific filebg-primary, text-muted-foreground).@theme inline for Tailwind v4.variant or className would do.lightTheme/darkTheme props on <CRM>.:root but not in .dark (or vice versa) — one mode is left broken.@theme inline.:root and .dark.className → new variant → wrapper).lightTheme/darkTheme on <CRM>.64e2163
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.