mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 06:14:59 +00:00
- Introduced a new Table component with TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, and TableCaption for better UI consistency. - Refactored Select component to utilize MUI's Select, MenuItem, and FormControl for improved accessibility and styling. - Created a centralized MUI theme with design tokens, typography, spacing, and component overrides for light and dark modes.
9.4 KiB
9.4 KiB
UI Migration Guide: From Radix UI + Tailwind to Material-UI + SASS
⚠️ IMPORTANT: Project UI Standards
This project does NOT use:
- ❌ Radix UI (removed)
- ❌ Tailwind CSS (removed)
- ❌ inline
classNamestyling with utility classes
This project DOES use:
- ✅ Material-UI (MUI) for all UI components
- ✅ SASS/SCSS for custom styling
- ✅ MUI's theme system for consistent design
Overview
All UI components have been migrated from Radix UI + Tailwind to Material-UI (MUI) with SASS. This document explains how to work with the new system.
Quick Reference: Component Mapping
Radix UI → Material-UI
| Old (Radix UI) | New (Material-UI) |
|---|---|
<AlertDialog> |
<Dialog> with <DialogTitle> and <DialogActions> |
<Accordion> |
<Accordion> with <AccordionSummary> |
<Avatar> |
<Avatar> |
<Checkbox> |
<Checkbox> with <FormControlLabel> |
<Dialog> |
<Dialog> with <DialogTitle>, <DialogContent> |
<DropdownMenu> |
<Menu> with <MenuItem> |
<HoverCard> |
<Popover> with hover trigger |
<Label> |
<FormLabel> or <InputLabel> |
<Popover> |
<Popover> |
<Progress> |
<LinearProgress> or <CircularProgress> |
<RadioGroup> |
<RadioGroup> with <FormControlLabel> |
<ScrollArea> |
Native overflow or <Box> with sx |
<Select> |
<Select> with <MenuItem> |
<Separator> |
<Divider> |
<Sheet> |
<Drawer> |
<Slider> |
<Slider> |
<Switch> |
<Switch> with <FormControlLabel> |
<Tabs> |
<Tabs> with <Tab> |
<Toast> |
<Snackbar> with <Alert> |
<Toggle> |
<ToggleButton> |
<Tooltip> |
<Tooltip> |
Tailwind Classes → MUI/SASS
| Old (Tailwind) | New (MUI/SASS) |
|---|---|
className="flex items-center" |
sx={{ display: 'flex', alignItems: 'center' }} |
className="grid grid-cols-2 gap-4" |
sx={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 2 }} |
className="text-lg font-bold" |
<Typography variant="h6" fontWeight="bold"> |
className="bg-primary text-white" |
sx={{ bgcolor: 'primary.main', color: 'primary.contrastText' }} |
className="p-4 m-2" |
sx={{ p: 2, m: 1 }} (MUI uses 8px spacing units) |
className="rounded-lg shadow" |
<Paper elevation={2} sx={{ borderRadius: 2 }}> |
| Custom classes | Create .module.scss files and import |
Using Material-UI Components
Basic Button Example
import { Button } from '@mui/material'
import AddIcon from '@mui/icons-material/Add'
// Old (Radix + Tailwind):
<button className="bg-blue-500 text-white px-4 py-2 rounded">
Click me
</button>
// New (MUI):
<Button variant="contained" color="primary" startIcon={<AddIcon />}>
Click me
</Button>
Dialog Example
import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from '@mui/material'
// Old (Radix):
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogTrigger>Open</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>Title</AlertDialogHeader>
<AlertDialogDescription>Content</AlertDialogDescription>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>OK</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
// New (MUI):
<>
<Button onClick={() => setOpen(true)}>Open</Button>
<Dialog open={open} onClose={() => setOpen(false)}>
<DialogTitle>Title</DialogTitle>
<DialogContent>
Content
</DialogContent>
<DialogActions>
<Button onClick={() => setOpen(false)}>Cancel</Button>
<Button onClick={handleOk} variant="contained">OK</Button>
</DialogActions>
</Dialog>
</>
Form with Input
import { TextField, FormControl, FormLabel } from '@mui/material'
// Old (Radix + Tailwind):
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" className="w-full" />
</div>
// New (MUI):
<TextField
fullWidth
label="Email"
type="email"
id="email"
variant="outlined"
/>
Icons
import { Add, Delete, Edit, Settings } from '@mui/icons-material'
// Old:
import { Plus, Trash, Edit, Settings } from 'lucide-react'
// or
import { PlusIcon } from '@heroicons/react/24/outline'
// New:
<Add />
<Delete />
<Edit />
<Settings />
Using SASS for Custom Styling
Module SCSS Files
Create component-specific SCSS files using CSS modules:
// UserCard.module.scss
.userCard {
padding: 16px;
border-radius: 12px;
background: var(--mui-palette-background-paper);
.header {
display: flex;
align-items: center;
gap: 12px;
}
.avatar {
width: 48px;
height: 48px;
}
}
// UserCard.tsx
import styles from './UserCard.module.scss'
import { Card } from '@mui/material'
export function UserCard() {
return (
<Card className={styles.userCard}>
<div className={styles.header}>
{/* content */}
</div>
</Card>
)
}
Using Theme Variables in SASS
Access MUI theme values in SCSS:
.myComponent {
// Colors from theme
color: var(--mui-palette-text-primary);
background: var(--mui-palette-background-default);
// Spacing (8px base unit)
padding: var(--mui-spacing-2); // 16px
margin: var(--mui-spacing-3); // 24px
// Typography
font-family: var(--mui-typography-fontFamily);
}
Using MUI's sx Prop
The sx prop is MUI's shorthand for inline styling with theme access:
import { Box, Typography } from '@mui/material'
// Responsive design
<Box
sx={{
display: 'flex',
flexDirection: { xs: 'column', md: 'row' },
gap: 2,
p: 3,
bgcolor: 'background.paper',
borderRadius: 2,
}}
>
<Typography variant="h6" color="primary.main">
Title
</Typography>
</Box>
Spacing System
MUI uses an 8px base spacing unit:
sx={{
p: 1, // padding: 8px
p: 2, // padding: 16px
p: 3, // padding: 24px
pt: 2, // padding-top: 16px
px: 3, // padding-left & padding-right: 24px
m: 2, // margin: 16px
gap: 2, // gap: 16px
}}
Theme Customization
The theme is defined in mui-theme.ts:
import { useTheme } from '@/app/providers'
function MyComponent() {
const { mode, setMode, toggleTheme } = useTheme()
return (
<Button onClick={toggleTheme}>
Current mode: {mode}
</Button>
)
}
Accessing Theme in Components
import { useTheme } from '@mui/material/styles'
function MyComponent() {
const theme = useTheme()
return (
<Box sx={{
color: theme.palette.primary.main,
[theme.breakpoints.down('md')]: {
fontSize: '0.875rem',
},
}}>
Content
</Box>
)
}
Data Display Components
Tables
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Paper
} from '@mui/material'
<Paper>
<Table>
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell>Email</TableCell>
</TableRow>
</TableHead>
<TableBody>
{users.map(user => (
<TableRow key={user.id}>
<TableCell>{user.name}</TableCell>
<TableCell>{user.email}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
For advanced features, use @mui/x-data-grid:
import { DataGrid } from '@mui/x-data-grid'
const columns = [
{ field: 'id', headerName: 'ID', width: 90 },
{ field: 'name', headerName: 'Name', width: 150 },
{ field: 'email', headerName: 'Email', width: 200 },
]
<DataGrid
rows={users}
columns={columns}
pageSize={10}
checkboxSelection
/>
Common Patterns
Loading States
import { CircularProgress, Box } from '@mui/material'
{isLoading ? (
<Box display="flex" justifyContent="center" p={3}>
<CircularProgress />
</Box>
) : (
<Content />
)}
Error Display
import { Alert, AlertTitle } from '@mui/material'
<Alert severity="error">
<AlertTitle>Error</AlertTitle>
{errorMessage}
</Alert>
Cards
import { Card, CardHeader, CardContent, CardActions, IconButton } from '@mui/material'
import { MoreVert } from '@mui/icons-material'
<Card>
<CardHeader
title="Card Title"
subheader="Subtitle"
action={
<IconButton>
<MoreVert />
</IconButton>
}
/>
<CardContent>
Content goes here
</CardContent>
<CardActions>
<Button>Action</Button>
</CardActions>
</Card>
Migration Checklist
When migrating a component:
- Remove all Radix UI imports
- Remove all Tailwind
classNameprops with utility classes - Replace with appropriate MUI components
- Use
sxprop for simple inline styles - Create
.module.scssfor complex custom styling - Update icon imports to
@mui/icons-material - Test responsive behavior
- Verify theme consistency (light/dark mode)
- Update tests to work with MUI components
Resources
Need Help?
- Check mui-theme.ts for theme configuration
- Look at existing migrated components for patterns
- Use MUI's comprehensive documentation
- Create
.module.scssfiles for complex component-specific styles