Components
Adding and customizing UI components
StartupKit includes commonly used Shadcn UI components out of the box. This guide covers how to add more components and use the included helpers.
Adding Components
Add any Shadcn component with a single command:
pnpm shadcn add <component>For example:
pnpm shadcn add calendar
pnpm shadcn add command
pnpm shadcn add carouselComponents are installed to packages/ui/src/components/ and immediately available across all apps.
Browse available components
See the full list of components at ui.shadcn.com/docs/components.
Add multiple components
pnpm shadcn add dialog dropdown-menu tooltipImport Pattern
Components use direct path imports from @repo/ui:
import { Button } from "@repo/ui/components/button"
import { Card, CardHeader, CardContent } from "@repo/ui/components/card"
import { Dialog, DialogContent, DialogTrigger } from "@repo/ui/components/dialog"Helpers
cn() utility
The cn() function merges Tailwind classes with proper precedence. It combines clsx and tailwind-merge:
import { cn } from "@repo/ui/utils"
function MyComponent({ className, isActive }) {
return (
<div className={cn(
"rounded-lg border p-4",
isActive && "border-primary bg-primary/10",
className
)}>
Content
</div>
)
}Use cn() when:
- Merging conditional classes
- Accepting
classNameas a prop - Overriding default component styles
useIsMobile hook
Detect mobile viewport for responsive behavior:
"use client"
import { useIsMobile } from "@repo/ui/hooks"
export function ResponsiveComponent() {
const isMobile = useIsMobile()
if (isMobile) {
return <MobileView />
}
return <DesktopView />
}useAlert hook
Programmatic confirmation dialogs:
"use client"
import { useAlert } from "@repo/ui/providers"
export function DeleteButton() {
const { confirm } = useAlert()
async function handleDelete() {
const confirmed = await confirm({
title: "Delete item?",
description: "This action cannot be undone.",
confirmText: "Delete",
cancelText: "Cancel"
})
if (confirmed) {
await deleteItem()
}
}
return <Button onClick={handleDelete}>Delete</Button>
}Toast notifications
Show toast messages with Sonner:
"use client"
import { toast } from "sonner"
function handleSave() {
toast.success("Changes saved!")
}
function handleError() {
toast.error("Something went wrong")
}
function handleWithAction() {
toast("File deleted", {
action: {
label: "Undo",
onClick: () => restoreFile()
}
})
}The Toaster component is included in UIProvider.
Customizing Components
Since components live in packages/ui/src/components/, you can modify them directly:
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md...",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground",
// Add your own variant
brand: "bg-gradient-to-r from-purple-500 to-pink-500 text-white",
},
// ...
},
}
)Changes apply across all apps in the monorepo.
Storybook
Preview components in isolation:
pnpm storybookOpens at http://localhost:6006 with all components and their variants.