Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Integrate and customize shadcn/ui components—discovery, installation, theming, and Radix/Base UI best practices
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
resources/migration-guide.md
1# Migration Guide to shadcn/ui23This guide helps you migrate from other UI libraries to shadcn/ui.45## Why Migrate to shadcn/ui?67- **Full ownership**: Code lives in your project, not node_modules8- **Customizable**: Modify any component to fit your needs9- **No breaking changes**: Update components individually10- **Smaller bundles**: Only include what you use11- **Modern stack**: Built with Radix UI and Tailwind CSS12- **Type-safe**: Full TypeScript support1314## Migration Strategies1516### Strategy 1: Incremental Migration (Recommended)1718Gradually replace components over time:19201. Install shadcn/ui alongside existing library212. Replace components page by page or feature by feature223. Remove old library once migration is complete2324**Pros**: Low risk, can be done alongside feature work25**Cons**: Temporary bundle size increase2627### Strategy 2: Big Bang Migration2829Replace all components at once:30311. Set up shadcn/ui322. Create component mapping document333. Replace all components in one effort344. Test thoroughly3536**Pros**: Clean cutover, no mixed UI37**Cons**: High risk, requires dedicated time3839## Internal Migrations (shadcn specific)4041### RTL Support Migration42If you need to support RTL languages (like Arabic or Hebrew) in an existing shadcn/ui project:4344```bash45npx shadcn@latest migrate rtl46```4748This CLI command transforms your components to use **logical properties**:49- `ml-4` -> `ms-4` (margin-start)50- `pl-4` -> `ps-4` (padding-start)51- `text-left` -> `text-start`5253It ensures your UI adapts correctly to layout direction without manual refactoring.5455## From Material-UI (MUI)5657### Component Mapping5859| MUI Component | shadcn/ui Equivalent | Notes |60|---------------|----------------------|-------|61| Button | Button | Similar API |62| TextField | Input + Label | Separate components |63| Select | Select | Different structure |64| Dialog | Dialog | Similar concept |65| Drawer | Sheet | Side panel |66| Card | Card | Very similar |67| Table | Table | Use with TanStack Table |68| Checkbox | Checkbox | Similar API |69| Switch | Switch | Similar API |70| Tabs | Tabs | Similar structure |71| Tooltip | Tooltip | Simpler API |72| Menu | Dropdown Menu | Different trigger model |73| Snackbar | Toast | Different implementation |74| Autocomplete | Combobox | Use with Command |7576### Key Differences7778**1. Import Structure**79```tsx80// MUI81import Button from '@mui/material/Button'8283// shadcn/ui84import { Button } from '@/components/ui/button'85```8687**2. Form Components**88```tsx89// MUI90<TextField91label="Email"92value={email}93onChange={(e) => setEmail(e.target.value)}94error={!!errors.email}95helperText={errors.email}96/>9798// shadcn/ui99<div className="space-y-2">100<Label htmlFor="email">Email</Label>101<Input102id="email"103value={email}104onChange={(e) => setEmail(e.target.value)}105/>106{errors.email && (107<p className="text-sm text-destructive">{errors.email}</p>108)}109</div>110111// Or with Form component112<FormField113control={form.control}114name="email"115render={({ field }) => (116<FormItem>117<FormLabel>Email</FormLabel>118<FormControl>119<Input {...field} />120</FormControl>121<FormMessage />122</FormItem>123)}124/>125```126127**3. Theming**128```tsx129// MUI130import { ThemeProvider, createTheme } from '@mui/material/styles'131132const theme = createTheme({133palette: {134primary: { main: '#1976d2' },135},136})137138<ThemeProvider theme={theme}>139<App />140</ThemeProvider>141142// shadcn/ui143// Edit globals.css144:root {145--primary: 215 100% 50%;146}147```148149**4. Styling Approach**150```tsx151// MUI (sx prop)152<Button sx={{ px: 4, py: 2, borderRadius: 2 }}>153Click me154</Button>155156// shadcn/ui (Tailwind classes)157<Button className="px-4 py-2 rounded-lg">158Click me159</Button>160```161162### Migration Example: Login Form163164**Before (MUI)**:165```tsx166import { TextField, Button, Box } from '@mui/material'167168export function LoginForm() {169return (170<Box component="form" sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>171<TextField label="Email" type="email" required />172<TextField label="Password" type="password" required />173<Button variant="contained" type="submit">174Sign In175</Button>176</Box>177)178}179```180181**After (shadcn/ui)**:182```tsx183import { Input } from '@/components/ui/input'184import { Label } from '@/components/ui/label'185import { Button } from '@/components/ui/button'186187export function LoginForm() {188return (189<form className="flex flex-col gap-4">190<div className="space-y-2">191<Label htmlFor="email">Email</Label>192<Input id="email" type="email" required />193</div>194<div className="space-y-2">195<Label htmlFor="password">Password</Label>196<Input id="password" type="password" required />197</div>198<Button type="submit">Sign In</Button>199</form>200)201}202```203204## From Chakra UI205206### Component Mapping207208| Chakra UI | shadcn/ui | Notes |209|-----------|-----------|-------|210| Button | Button | Similar variants |211| Input | Input | More basic |212| Select | Select | Different structure |213| Modal | Dialog | Similar concept |214| Drawer | Sheet | Very similar |215| Box | div | Use Tailwind classes |216| Flex | div | Use flex utilities |217| Stack | div | Use space-y-* classes |218| Text | p/span | Use typography classes |219| Heading | h1/h2/etc | Use typography classes |220| useToast | useToast | Different API |221| Menu | Dropdown Menu | Similar |222223### Key Differences224225**1. Layout Components**226```tsx227// Chakra UI228<Stack spacing={4} direction="column">229<Box>Item 1</Box>230<Box>Item 2</Box>231</Stack>232233// shadcn/ui234<div className="flex flex-col space-y-4">235<div>Item 1</div>236<div>Item 2</div>237</div>238```239240**2. Responsive Styles**241```tsx242// Chakra UI243<Box display={{ base: 'block', md: 'flex' }} />244245// shadcn/ui246<div className="block md:flex" />247```248249**3. Color Mode**250```tsx251// Chakra UI252import { useColorMode } from '@chakra-ui/react'253254const { colorMode, toggleColorMode } = useColorMode()255256// shadcn/ui (with next-themes)257import { useTheme } from 'next-themes'258259const { theme, setTheme } = useTheme()260```261262## From Ant Design263264### Component Mapping265266| Ant Design | shadcn/ui | Notes |267|------------|-----------|-------|268| Button | Button | Similar |269| Input | Input | More basic |270| Form | Form | Different approach |271| Table | Table | Use TanStack Table |272| Modal | Dialog | Similar |273| Drawer | Sheet | Similar |274| Select | Select | Different API |275| DatePicker | Calendar + Popover | More manual |276| Menu | Navigation Menu | Different |277| message | Toast | Different API |278| notification | Toast | Similar concept |279280### Key Differences281282**1. Form Handling**283```tsx284// Ant Design285<Form286form={form}287onFinish={onSubmit}288>289<Form.Item name="email" rules={[{ required: true }]}>290<Input />291</Form.Item>292<Form.Item>293<Button type="primary" htmlType="submit">Submit</Button>294</Form.Item>295</Form>296297// shadcn/ui (with react-hook-form)298<Form {...form}>299<form onSubmit={form.handleSubmit(onSubmit)}>300<FormField301control={form.control}302name="email"303render={({ field }) => (304<FormItem>305<FormControl>306<Input {...field} />307</FormControl>308<FormMessage />309</FormItem>310)}311/>312<Button type="submit">Submit</Button>313</form>314</Form>315```316317**2. Notifications**318```tsx319// Ant Design320import { message } from 'antd'321322message.success('Success!')323324// shadcn/ui325import { useToast } from '@/components/ui/use-toast'326327const { toast } = useToast()328329toast({330title: "Success!",331description: "Operation completed.",332})333```334335## From Bootstrap336337### Component Mapping338339| Bootstrap | shadcn/ui | Notes |340|-----------|-----------|-------|341| btn | Button | Similar variants |342| form-control | Input | Similar |343| card | Card | Very similar structure |344| modal | Dialog | Different API |345| dropdown | Dropdown Menu | Similar concept |346| nav/navbar | Navigation Menu | Different |347| alert | Alert | Similar |348| badge | Badge | Similar |349| table | Table | Use with TanStack Table |350351### Key Differences352353**1. Class-Based vs Component-Based**354```tsx355// Bootstrap356<button className="btn btn-primary btn-lg">357Click me358</button>359360// shadcn/ui361<Button variant="default" size="lg">362Click me363</Button>364```365366**2. Cards**367```html368<!-- Bootstrap -->369<div class="card">370<div class="card-header">Title</div>371<div class="card-body">Content</div>372<div class="card-footer">Footer</div>373</div>374375<!-- shadcn/ui -->376<Card>377<CardHeader>378<CardTitle>Title</CardTitle>379</CardHeader>380<CardContent>Content</CardContent>381<CardFooter>Footer</CardFooter>382</Card>383```384385## Migration Checklist386387### Before Migration388389- [ ] Audit current component usage390- [ ] Set up shadcn/ui in a test branch391- [ ] Create component mapping document392- [ ] Plan migration order (start with simple components)393- [ ] Set up Tailwind CSS properly394- [ ] Configure path aliases395396### During Migration397398- [ ] Install shadcn/ui components as needed399- [ ] Replace components incrementally400- [ ] Update styling to use Tailwind classes401- [ ] Test each page/feature after migration402- [ ] Update tests to match new components403- [ ] Handle form validation (switch to react-hook-form + zod)404- [ ] Migrate theme/color variables405406### After Migration407408- [ ] Remove old UI library dependencies409- [ ] Clean up unused imports410- [ ] Optimize bundle size411- [ ] Update documentation412- [ ] Review and update design system413- [ ] Train team on new components414415## Common Pitfalls416417### 1. Not Setting Up Tailwind Properly418419shadcn/ui requires Tailwind. Ensure:420- `tailwind.config.js` includes correct content paths421- CSS variables are defined in `globals.css`422- Tailwind plugins are installed (e.g., `tailwindcss-animate`)423424### 2. Forgetting Path Aliases425426Components use `@/` imports. Configure:427- `tsconfig.json` with path aliases428- Vite/Next.js config for runtime resolution429430### 3. Trying to Match Old Library Exactly431432Don't force shadcn/ui to work like your old library. Embrace the new patterns:433- Use composition over configuration434- Leverage Tailwind utilities435- Create wrapper components for custom needs436437### 4. Not Using Form Libraries438439shadcn/ui form components are basic. For complex forms, use:440- `react-hook-form` for form state441- `zod` for validation442- shadcn's `Form` component for integration443444### 5. Ignoring Accessibility445446While shadcn/ui is accessible by default, custom modifications can break this. Test with:447- Keyboard navigation448- Screen readers449- ARIA attribute validation450451## Getting Help452453- **Discord**: [shadcn/ui Discord](https://discord.com/invite/vNvTqVaWm6)454- **GitHub Discussions**: [shadcn/ui Discussions](https://github.com/shadcn-ui/ui/discussions)455- **Documentation**: [ui.shadcn.com](https://ui.shadcn.com)456457## Next Steps458459After migration:4601. Review the [Customization Guide](./customization-guide.md)4612. Explore the [Component Catalog](./component-catalog.md)4623. Check out [Examples](../examples/)4634. Consider building a component library on top of shadcn/ui464