The Starter Kit includes a comprehensive component library built on Radix UI primitives with Tailwind CSS styling. These components provide a consistent design system and accelerate development of your AI-powered application.
Component Organization
The components/ directory follows a structured organization pattern:
components/
├── ui/ # Base UI primitives (Radix UI wrappers)
├── generic/ # Reusable cross-project components
├── project/ # Project-specific chrome (header, footer)
├── starter/ # Homepage marketing sections
├── auth/ # Authentication-related components
└── devkit/ # Development tooling components
UI Components (components/ui/)
Base UI primitives wrapped from Radix UI with Tailwind styling and class-variance-authority for variants.
Button (button.tsx)
import { Button } from "@/components/ui/button";
<Button variant="default">Click me</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Cancel</Button>
<Button variant="ghost">Menu</Button>
<Button variant="link">Learn more</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
Variants: default, destructive, outline, secondary, ghost, link
Sizes: default, sm, lg, icon
Input (input.tsx)
import { Input } from "@/components/ui/input";
<Input type="email" placeholder="Email" />
<Input type="password" placeholder="Password" />
<Input disabled placeholder="Disabled" />
Textarea (textarea.tsx)
import { Textarea } from "@/components/ui/textarea";
<Textarea placeholder="Enter your message..." rows={4} />
<Textarea disabled placeholder="Read-only content" />
Checkbox (checkbox.tsx)
import { Checkbox } from "@/components/ui/checkbox";
<Checkbox id="terms" />
<label htmlFor="terms">Accept terms</label>
Label (label.tsx)
import { Label } from "@/components/ui/label";
<Label htmlFor="email">Email Address</Label>
<Input id="email" type="email" />
Select (select.tsx)
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
<Select>
<SelectTrigger>
<SelectValue placeholder="Select option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="option1">Option 1</SelectItem>
<SelectItem value="option2">Option 2</SelectItem>
</SelectContent>
</Select>
Layout Components
Card (card.tsx)
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from "@/components/ui/card";
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card description text</CardDescription>
</CardHeader>
<CardContent>
<p>Card content goes here</p>
</CardContent>
<CardFooter>
<Button>Action</Button>
</CardFooter>
</Card>
Separator (separator.tsx)
import { Separator } from "@/components/ui/separator";
<Separator />
<Separator orientation="vertical" />
Sheet (sheet.tsx)
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet";
<Sheet>
<SheetTrigger>Open</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Sheet Title</SheetTitle>
<SheetDescription>Sheet description</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
Tabs (tabs.tsx)
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
<Tabs defaultValue="tab1">
<TabsList>
<TabsTrigger value="tab1">Tab 1</TabsTrigger>
<TabsTrigger value="tab2">Tab 2</TabsTrigger>
</TabsList>
<TabsContent value="tab1">Content 1</TabsContent>
<TabsContent value="tab2">Content 2</TabsContent>
</Tabs>
Display Components
Avatar (avatar.tsx)
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
<Avatar>
<AvatarImage src="/avatar.jpg" alt="User" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
Badge (badge.tsx)
import { Badge } from "@/components/ui/badge";
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Error</Badge>
<Badge variant="outline">Outline</Badge>
Skeleton (skeleton.tsx)
import { Skeleton } from "@/components/ui/skeleton";
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-12 w-12 rounded-full" />
Table (table.tsx)
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Email</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>John Doe</TableCell>
<TableCell>john@example.com</TableCell>
</TableRow>
</TableBody>
</Table>
Interactive Components
Dropdown Menu (dropdown-menu.tsx)
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
<DropdownMenu>
<DropdownMenuTrigger>Menu</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Settings</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
Tooltip (tooltip.tsx)
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
<TooltipProvider>
<Tooltip>
<TooltipTrigger>Hover me</TooltipTrigger>
<TooltipContent>
<p>Tooltip content</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
Alert Dialog (alert-dialog.tsx)
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
<AlertDialog>
<AlertDialogTrigger>Delete</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
Generic Components (components/generic/)
Reusable cross-project components designed for portability:
CodeBlock (code-block.tsx) - Syntax-highlighted code display
CategoryGrid (category-grid.tsx) - Grid layout for categories
CtaButton (cta-button.tsx) - Call-to-action button
FloatingNav (floating-nav.tsx) - Floating navigation bar
InfoBox (info-box.tsx) - Information display box
PageHeader (page-header.tsx) - Consistent page headers
ScrollIndicator (scroll-indicator.tsx) - Scroll progress indicator
ThemeToggle (theme-toggle.tsx) - Light/dark mode switcher
ToC (toc.tsx) - Table of contents generator
Project Components (components/project/)
Project-specific chrome components:
Header (header.tsx) - Main navigation header with mobile menu, theme switcher, CTA button
Footer (footer.tsx) - Site footer with links and copyright
Pricing (pricing/) - Pricing table components
Shared Components
FormMessage (form-message.tsx) - Form validation message display
import FormMessage from "@/components/form-message";
<FormMessage message={{ success: "Saved!", error: null }} />
<FormMessage message={{ success: null, error: "Invalid input" }} />
SubmitButton (submit-button.tsx) - Form submit button with loading state
import { SubmitButton } from "@/components/submit-button";
<form>
<SubmitButton>Submit</SubmitButton>
<SubmitButton pendingText="Saving...">Save</SubmitButton>
</form>
ThemeSwitcher (theme-switcher.tsx) - Theme selection dropdown
import { ThemeSwitcher } from "@/components/theme-switcher";
<ThemeSwitcher />
Styling System
Tailwind CSS
All components use Tailwind utility classes:
<div className="flex items-center gap-4 p-4 rounded-lg border">
<Avatar />
<div className="flex-1">
<p className="font-medium">User Name</p>
<p className="text-sm text-muted-foreground">user@example.com</p>
</div>
</div>
Dark Mode Support
Components automatically support dark mode via dark: prefix:
<Card className="bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-800">
<CardContent className="text-gray-900 dark:text-gray-100">
Content with dark mode support
</CardContent>
</Card>
Class Variance Authority
Component variants managed with class-variance-authority:
// button.tsx
import { cva } from "class-variance-authority";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground",
outline: "border border-input bg-background hover:bg-accent",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);
Utility Functions
cn() Helper
Conditional class merging utility:
import { cn } from "@/lib/utils";
<div className={cn(
"base-classes",
condition && "conditional-class",
variant === "primary" && "primary-class"
)}>
Content
</div>
Component Dependencies
Radix UI Packages:
- @radix-ui/react-alert-dialog
- @radix-ui/react-avatar
- @radix-ui/react-checkbox
- @radix-ui/react-dropdown-menu
- @radix-ui/react-label
- @radix-ui/react-select
- @radix-ui/react-separator
- @radix-ui/react-slot
- @radix-ui/react-tabs
- @radix-ui/react-tooltip
Styling:
- tailwindcss
- class-variance-authority
- tailwind-merge
- clsx
Icons:
Customization Guidelines
Extending Components
Create custom variants by extending existing components:
// Custom button variant
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
export function CustomButton({ className, ...props }) {
return (
<Button
className={cn("bg-gradient-to-r from-blue-500 to-purple-600", className)}
{...props}
/>
);
}
Creating New Components
Follow the established patterns:
// components/ui/custom-component.tsx
import * as React from "react";
import { cn } from "@/lib/utils";
export interface CustomComponentProps
extends React.HTMLAttributes<HTMLDivElement> {
variant?: "default" | "special";
}
const CustomComponent = React.forwardRef<HTMLDivElement, CustomComponentProps>(
({ className, variant = "default", ...props }, ref) => {
return (
<div
ref={ref}
className={cn(
"base-styles",
variant === "special" && "special-styles",
className
)}
{...props}
/>
);
}
);
CustomComponent.displayName = "CustomComponent";
export { CustomComponent };
Theming
Customize colors in tailwind.config.ts:
theme: {
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
// ... more colors
},
},
}
Define CSS variables in globals.css:
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 142 86% 28%;
/* ... more variables */
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--primary: 142 76% 36%;
/* ... more variables */
}
Best Practices
Always use the cn() utility when combining class names to ensure proper Tailwind class merging.
Component Usage:
- Import components from
@/components/ui/* for base primitives
- Use semantic HTML elements where appropriate
- Provide accessible labels and ARIA attributes
- Test components in both light and dark modes
- Keep component props minimal and focused
Performance:
- Use
React.forwardRef for components that need refs
- Memoize expensive computations with
useMemo
- Avoid inline function definitions in render
- Use
React.memo for pure components
Accessibility:
- Include proper ARIA labels
- Ensure keyboard navigation works
- Test with screen readers
- Maintain sufficient color contrast
- Provide focus indicators
Related Pages