UNPKG

opencode-agent-kit

Version:

Multi-stack OpenCode agent toolkit — 33+ specialized AI agents, 200+ skills, 46 commands, 8 MCP servers (Nuxt, React, Node.js, Laravel, CI3, Android, Flutter, DevOps, SEO, SonarQube, and more)

464 lines (373 loc) 10.9 kB
# Migration Guide to shadcn/ui This guide helps you migrate from other UI libraries to shadcn/ui. ## Why Migrate to shadcn/ui? - **Full ownership**: Code lives in your project, not node_modules - **Customizable**: Modify any component to fit your needs - **No breaking changes**: Update components individually - **Smaller bundles**: Only include what you use - **Modern stack**: Built with Radix UI and Tailwind CSS - **Type-safe**: Full TypeScript support ## Migration Strategies ### Strategy 1: Incremental Migration (Recommended) Gradually replace components over time: 1. Install shadcn/ui alongside existing library 2. Replace components page by page or feature by feature 3. Remove old library once migration is complete **Pros**: Low risk, can be done alongside feature work **Cons**: Temporary bundle size increase ### Strategy 2: Big Bang Migration Replace all components at once: 1. Set up shadcn/ui 2. Create component mapping document 3. Replace all components in one effort 4. Test thoroughly **Pros**: Clean cutover, no mixed UI **Cons**: High risk, requires dedicated time ## Internal Migrations (shadcn specific) ### RTL Support Migration If you need to support RTL languages (like Arabic or Hebrew) in an existing shadcn/ui project: ```bash npx shadcn@latest migrate rtl ``` This CLI command transforms your components to use **logical properties**: - `ml-4` -> `ms-4` (margin-start) - `pl-4` -> `ps-4` (padding-start) - `text-left` -> `text-start` It ensures your UI adapts correctly to layout direction without manual refactoring. ## From Material-UI (MUI) ### Component Mapping | MUI Component | shadcn/ui Equivalent | Notes | |---------------|----------------------|-------| | Button | Button | Similar API | | TextField | Input + Label | Separate components | | Select | Select | Different structure | | Dialog | Dialog | Similar concept | | Drawer | Sheet | Side panel | | Card | Card | Very similar | | Table | Table | Use with TanStack Table | | Checkbox | Checkbox | Similar API | | Switch | Switch | Similar API | | Tabs | Tabs | Similar structure | | Tooltip | Tooltip | Simpler API | | Menu | Dropdown Menu | Different trigger model | | Snackbar | Toast | Different implementation | | Autocomplete | Combobox | Use with Command | ### Key Differences **1. Import Structure** ```tsx // MUI import Button from '@mui/material/Button' // shadcn/ui import { Button } from '@/components/ui/button' ``` **2. Form Components** ```tsx // MUI <TextField label="Email" value={email} onChange={(e) => setEmail(e.target.value)} error={!!errors.email} helperText={errors.email} /> // shadcn/ui <div className="space-y-2"> <Label htmlFor="email">Email</Label> <Input id="email" value={email} onChange={(e) => setEmail(e.target.value)} /> {errors.email && ( <p className="text-sm text-destructive">{errors.email}</p> )} </div> // Or with Form component <FormField control={form.control} name="email" render={({ field }) => ( <FormItem> <FormLabel>Email</FormLabel> <FormControl> <Input {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> ``` **3. Theming** ```tsx // MUI import { ThemeProvider, createTheme } from '@mui/material/styles' const theme = createTheme({ palette: { primary: { main: '#1976d2' }, }, }) <ThemeProvider theme={theme}> <App /> </ThemeProvider> // shadcn/ui // Edit globals.css :root { --primary: 215 100% 50%; } ``` **4. Styling Approach** ```tsx // MUI (sx prop) <Button sx={{ px: 4, py: 2, borderRadius: 2 }}> Click me </Button> // shadcn/ui (Tailwind classes) <Button className="px-4 py-2 rounded-lg"> Click me </Button> ``` ### Migration Example: Login Form **Before (MUI)**: ```tsx import { TextField, Button, Box } from '@mui/material' export function LoginForm() { return ( <Box component="form" sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}> <TextField label="Email" type="email" required /> <TextField label="Password" type="password" required /> <Button variant="contained" type="submit"> Sign In </Button> </Box> ) } ``` **After (shadcn/ui)**: ```tsx import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Button } from '@/components/ui/button' export function LoginForm() { return ( <form className="flex flex-col gap-4"> <div className="space-y-2"> <Label htmlFor="email">Email</Label> <Input id="email" type="email" required /> </div> <div className="space-y-2"> <Label htmlFor="password">Password</Label> <Input id="password" type="password" required /> </div> <Button type="submit">Sign In</Button> </form> ) } ``` ## From Chakra UI ### Component Mapping | Chakra UI | shadcn/ui | Notes | |-----------|-----------|-------| | Button | Button | Similar variants | | Input | Input | More basic | | Select | Select | Different structure | | Modal | Dialog | Similar concept | | Drawer | Sheet | Very similar | | Box | div | Use Tailwind classes | | Flex | div | Use flex utilities | | Stack | div | Use space-y-* classes | | Text | p/span | Use typography classes | | Heading | h1/h2/etc | Use typography classes | | useToast | useToast | Different API | | Menu | Dropdown Menu | Similar | ### Key Differences **1. Layout Components** ```tsx // Chakra UI <Stack spacing={4} direction="column"> <Box>Item 1</Box> <Box>Item 2</Box> </Stack> // shadcn/ui <div className="flex flex-col space-y-4"> <div>Item 1</div> <div>Item 2</div> </div> ``` **2. Responsive Styles** ```tsx // Chakra UI <Box display={{ base: 'block', md: 'flex' }} /> // shadcn/ui <div className="block md:flex" /> ``` **3. Color Mode** ```tsx // Chakra UI import { useColorMode } from '@chakra-ui/react' const { colorMode, toggleColorMode } = useColorMode() // shadcn/ui (with next-themes) import { useTheme } from 'next-themes' const { theme, setTheme } = useTheme() ``` ## From Ant Design ### Component Mapping | Ant Design | shadcn/ui | Notes | |------------|-----------|-------| | Button | Button | Similar | | Input | Input | More basic | | Form | Form | Different approach | | Table | Table | Use TanStack Table | | Modal | Dialog | Similar | | Drawer | Sheet | Similar | | Select | Select | Different API | | DatePicker | Calendar + Popover | More manual | | Menu | Navigation Menu | Different | | message | Toast | Different API | | notification | Toast | Similar concept | ### Key Differences **1. Form Handling** ```tsx // Ant Design <Form form={form} onFinish={onSubmit} > <Form.Item name="email" rules={[{ required: true }]}> <Input /> </Form.Item> <Form.Item> <Button type="primary" htmlType="submit">Submit</Button> </Form.Item> </Form> // shadcn/ui (with react-hook-form) <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)}> <FormField control={form.control} name="email" render={({ field }) => ( <FormItem> <FormControl> <Input {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> <Button type="submit">Submit</Button> </form> </Form> ``` **2. Notifications** ```tsx // Ant Design import { message } from 'antd' message.success('Success!') // shadcn/ui import { useToast } from '@/components/ui/use-toast' const { toast } = useToast() toast({ title: "Success!", description: "Operation completed.", }) ``` ## From Bootstrap ### Component Mapping | Bootstrap | shadcn/ui | Notes | |-----------|-----------|-------| | btn | Button | Similar variants | | form-control | Input | Similar | | card | Card | Very similar structure | | modal | Dialog | Different API | | dropdown | Dropdown Menu | Similar concept | | nav/navbar | Navigation Menu | Different | | alert | Alert | Similar | | badge | Badge | Similar | | table | Table | Use with TanStack Table | ### Key Differences **1. Class-Based vs Component-Based** ```tsx // Bootstrap <button className="btn btn-primary btn-lg"> Click me </button> // shadcn/ui <Button variant="default" size="lg"> Click me </Button> ``` **2. Cards** ```html <!-- Bootstrap --> <div class="card"> <div class="card-header">Title</div> <div class="card-body">Content</div> <div class="card-footer">Footer</div> </div> <!-- shadcn/ui --> <Card> <CardHeader> <CardTitle>Title</CardTitle> </CardHeader> <CardContent>Content</CardContent> <CardFooter>Footer</CardFooter> </Card> ``` ## Migration Checklist ### Before Migration - [ ] Audit current component usage - [ ] Set up shadcn/ui in a test branch - [ ] Create component mapping document - [ ] Plan migration order (start with simple components) - [ ] Set up Tailwind CSS properly - [ ] Configure path aliases ### During Migration - [ ] Install shadcn/ui components as needed - [ ] Replace components incrementally - [ ] Update styling to use Tailwind classes - [ ] Test each page/feature after migration - [ ] Update tests to match new components - [ ] Handle form validation (switch to react-hook-form + zod) - [ ] Migrate theme/color variables ### After Migration - [ ] Remove old UI library dependencies - [ ] Clean up unused imports - [ ] Optimize bundle size - [ ] Update documentation - [ ] Review and update design system - [ ] Train team on new components ## Common Pitfalls ### 1. Not Setting Up Tailwind Properly shadcn/ui requires Tailwind. Ensure: - `tailwind.config.js` includes correct content paths - CSS variables are defined in `globals.css` - Tailwind plugins are installed (e.g., `tailwindcss-animate`) ### 2. Forgetting Path Aliases Components use `@/` imports. Configure: - `tsconfig.json` with path aliases - Vite/Next.js config for runtime resolution ### 3. Trying to Match Old Library Exactly Don't force shadcn/ui to work like your old library. Embrace the new patterns: - Use composition over configuration - Leverage Tailwind utilities - Create wrapper components for custom needs ### 4. Not Using Form Libraries shadcn/ui form components are basic. For complex forms, use: - `react-hook-form` for form state - `zod` for validation - shadcn's `Form` component for integration ### 5. Ignoring Accessibility While shadcn/ui is accessible by default, custom modifications can break this. Test with: - Keyboard navigation - Screen readers - ARIA attribute validation ## Getting Help - **Discord**: [shadcn/ui Discord](https://discord.com/invite/vNvTqVaWm6) - **GitHub Discussions**: [shadcn/ui Discussions](https://github.com/shadcn-ui/ui/discussions) - **Documentation**: [ui.shadcn.com](https://ui.shadcn.com) ## Next Steps After migration: 1. Review the [Customization Guide](./customization-guide.md) 2. Explore the [Component Catalog](./component-catalog.md) 3. Check out [Examples](../examples/) 4. Consider building a component library on top of shadcn/ui