- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- Menubar
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
Setup
Connect your portal to the SD registry. Five steps, then every component is one command away.
Step 1: Install Dependencies
SD components use Radix UI primitives via the radix-ui package. Install it:
pnpm add radix-ui
You can keep your existing @radix-ui/react-* packages — both work simultaneously. New components pulled from the registry will use radix-ui.
Step 2: Add components.json
Create components.json in your portal's root directory. This tells the CLI where your project is structured and where to find the SD registry.
{
"$schema": "https://ui.styledriven.com/schema.json",
"style": "radix-sd",
"rsc": true,
"tsx": true,
"tailwind": {
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide",
"registries": {
"@sd": "http://localhost:4000/r/styles/radix-sd/{name}.json"
}
}When deploying, change the registry URL to production:
{
"registries": {
"@sd": "https://ui.styledriven.com/r/styles/radix-sd/{name}.json"
}
}Step 3: Add Registry CSS Variables
SD components use semantic color tokens like bg-primary, text-muted-foreground, border-border. Your portal needs to define what these resolve to.
Add this to your globals.css @theme block:
@theme {
/* ... your existing SD brand tokens ... */
/* Registry compatibility */
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--radius-sm: calc(var(--radius) * 0.6);
--radius-md: calc(var(--radius) * 0.8);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) * 1.4);
--radius-2xl: calc(var(--radius) * 1.8);
}Then add the actual values in your :root and .dark blocks. These map shadcn's semantic tokens to SD brand values:
:root {
--radius: 0.5rem;
/* ... your existing --brand, --on-brand, etc. ... */
/* Registry semantic tokens mapped to SD brand */
--card: var(--background);
--card-foreground: var(--foreground);
--popover: var(--background);
--popover-foreground: var(--foreground);
--primary: var(--brand);
--primary-foreground: var(--on-brand);
--secondary: #f0f0f0;
--secondary-foreground: var(--foreground);
--muted: #f5f5f0;
--muted-foreground: var(--gray);
--accent-foreground: var(--foreground);
--destructive: var(--accent);
--destructive-foreground: #ffffff;
--border: color-mix(in srgb, var(--foreground) 15%, transparent);
--input: color-mix(in srgb, var(--foreground) 15%, transparent);
--ring: var(--brand);
--sidebar: #fafafa;
--sidebar-foreground: var(--foreground);
--sidebar-primary: var(--brand);
--sidebar-primary-foreground: var(--on-brand);
--sidebar-accent: #f5f5f0;
--sidebar-accent-foreground: var(--foreground);
--sidebar-border: color-mix(in srgb, var(--foreground) 10%, transparent);
--sidebar-ring: var(--brand);
}
.dark {
/* ... your existing dark mode --brand, --on-brand, etc. ... */
/* Registry semantic tokens — dark mode */
--card: #1a1a1a;
--card-foreground: #ffffff;
--popover: #1a1a1a;
--popover-foreground: #ffffff;
--primary: var(--brand);
--primary-foreground: var(--on-brand);
--secondary: #1f1f1f;
--secondary-foreground: #ffffff;
--muted: #1f1f1f;
--muted-foreground: var(--gray);
--accent-foreground: #ffffff;
--destructive: var(--accent);
--destructive-foreground: #ffffff;
--border: color-mix(in srgb, #ffffff 10%, transparent);
--input: color-mix(in srgb, #ffffff 15%, transparent);
--ring: var(--brand);
--sidebar: #1a1a1a;
--sidebar-foreground: #ffffff;
--sidebar-primary: var(--brand);
--sidebar-primary-foreground: var(--on-brand);
--sidebar-accent: #1f1f1f;
--sidebar-accent-foreground: #ffffff;
--sidebar-border: color-mix(in srgb, #ffffff 10%, transparent);
--sidebar-ring: var(--brand);
}The key mapping: --primary points to --brand, --destructive points to --accent (red), --muted-foreground points to --gray. This is how SD brand colors flow through to every registry component.
Step 4: Set the Registry URL
For local development, the SD registry serves from localhost:4000. Set this env var so dependency resolution works:
REGISTRY_URL=http://localhost:4000/rAdd it to your .env.local:
REGISTRY_URL=http://localhost:4000/r
Make sure the sd-ui dev server is running (pnpm dev in the sd-ui directory).
Step 5: Pull Components
Always use the @sd/ prefix to pull from the SD registry:
# Single component
REGISTRY_URL=http://localhost:4000/r npx shadcn@latest add @sd/button
# Multiple components
REGISTRY_URL=http://localhost:4000/r npx shadcn@latest add @sd/badge @sd/card @sd/dialog
# Custom SD components (not in upstream shadcn)
REGISTRY_URL=http://localhost:4000/r npx shadcn@latest add @sd/date-picker @sd/phone-inputComponents land in components/ui/. You own the code.
The @sd/ prefix is required — without it, the CLI looks in the default shadcn registry which doesn't have the SD style.
Using It
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { DatePicker } from "@/components/ui/date-picker"
export function Example() {
return (
<div>
<Button>Get Started</Button>
<Badge variant="destructive">Urgent</Badge>
<DatePicker value={date} onChange={setDate} />
</div>
)
}MCP Server
The registry supports MCP. Claude Code, Cursor, and VS Code can add components through the MCP server:
pnpm dlx shadcn@latest mcp init --client claude
After setup, Claude can search and add components conversationally.
Updating Components
To see what changed upstream before updating:
pnpm dlx shadcn@latest add @sd/button --dry-run npx shadcn@latest add @sd/button --diff button.tsx
To overwrite with the latest version:
REGISTRY_URL=http://localhost:4000/r npx shadcn@latest add @sd/button --overwriteTech Stack
Every portal runs the same stack. SD components are built for this:
| Tool | Version |
|---|---|
| Next.js | 16 |
| React | 19 |
| Tailwind CSS | v4 |
| Radix UI | Latest |
| TypeScript | 5.x |
| class-variance-authority | Latest |
Troubleshooting
"Item was not found" error: Make sure you're using the @sd/ prefix and the sd-ui dev server is running on port 4000. Set REGISTRY_URL=http://localhost:4000/r before the command.
Components render unstyled: Your globals.css is missing the semantic CSS variables. Add the --primary, --muted, --border etc. mappings from Step 3.
Import error for radix-ui: Run npm install radix-ui in your portal. Registry components use the monolithic package.