Customizing Toro UI components to match your design system.
Toro UI components live in your project. There's no node_modules abstraction between you and the code — you own it, and you can change anything.
Every component is a file in your components/ui/ directory. To customize a component, edit it directly:
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/80",
// Add your own variant
brand: "bg-blue-600 text-white hover:bg-blue-700",
},
},
}
)No wrapper components, no style overrides fighting specificity — just change the source.
The theme is defined with CSS custom properties in globals.css. Change the look of your entire app by updating the token values:
:root {
--primary: oklch(0.55 0.2 250); /* Blue primary */
--primary-foreground: oklch(1 0 0);
--radius: 0.75rem; /* Rounder corners */
}
.dark {
--primary: oklch(0.7 0.15 250);
--primary-foreground: oklch(0.1 0 0);
}All components reference these tokens, so a single change propagates everywhere.
Components use class-variance-authority (CVA) for type-safe variants. Add new variants or sizes by extending the variants object:
const buttonVariants = cva("...", {
variants: {
variant: {
// existing variants...
default: "bg-primary text-primary-foreground",
outline: "border border-border bg-background",
// new variant
gradient: "bg-gradient-to-r from-blue-500 to-purple-500 text-white",
},
size: {
// existing sizes...
default: "h-9 px-2.5",
// new size
xl: "h-12 px-6 text-base",
},
},
})TypeScript will automatically infer the new variant values — no extra type definitions needed.
Every component accepts a className prop. Thanks to tailwind-merge, your classes override conflicting defaults:
// The component has rounded-md by default.
// Your rounded-none wins.
<Button className="rounded-none">Square Button</Button>Toro UI uses Lucide React for icons. To use a different icon library, update the icon imports in the components that use them:
// Before
import { XIcon } from "lucide-react"
// After — using your preferred icon library
import { CloseIcon } from "@/icons"Toro UI uses OKLCH colors for perceptually uniform color mixing. To build a branded palette:
--primary--primary-foreground--accent, --muted, and other tokens to complement:root {
/* Indigo brand */
--primary: oklch(0.45 0.2 280);
--primary-foreground: oklch(0.98 0 0);
--accent: oklch(0.94 0.02 280);
--accent-foreground: oklch(0.25 0.1 280);
}All border radius values derive from a single --radius token:
| Token | Value |
|---|---|
--radius-sm | calc(var(--radius) - 4px) |
--radius-md | calc(var(--radius) - 2px) |
--radius-lg | var(--radius) |
--radius-xl | calc(var(--radius) + 4px) |
Set --radius: 0 for sharp corners, --radius: 1rem for rounder elements.