@matteoaliano/forest-ui 0.2.10 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -0
- package/bin/sync.mjs +18 -34
- package/dist/{chunk-7B6NCKX3.mjs → chunk-EULMNCHH.mjs} +1039 -498
- package/dist/chunk-EULMNCHH.mjs.map +1 -0
- package/dist/{index-DiI9xbOM.d.mts → index-EkBIDmEu.d.mts} +109 -12
- package/dist/{index-DiI9xbOM.d.ts → index-EkBIDmEu.d.ts} +109 -12
- package/dist/index.d.mts +83 -20
- package/dist/index.d.ts +83 -20
- package/dist/index.js +1306 -571
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +233 -69
- package/dist/index.mjs.map +1 -1
- package/dist/theme.d.mts +1 -1
- package/dist/theme.d.ts +1 -1
- package/dist/theme.js +1039 -497
- package/dist/theme.js.map +1 -1
- package/dist/theme.mjs +1 -1
- package/guidelines/FOREST_BE_GUIDELINES.md +90 -0
- package/guidelines/FOREST_FE_GUIDELINES.md +543 -0
- package/guidelines/FOREST_UI_GUIDELINES.md +372 -0
- package/package.json +16 -4
- package/dist/chunk-7B6NCKX3.mjs.map +0 -1
- package/guidelines/FOREST_AI_GUIDELINES.md +0 -344
- package/guidelines/FOREST_DEV_GUIDELINES.md +0 -47
- package/guidelines/themes/FOREST_THEME_ALKEMY_PLUS.md +0 -139
- package/guidelines/themes/FOREST_THEME_DEFAULT.md +0 -70
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# Forest UI — AI Development Guidelines
|
|
2
|
+
|
|
3
|
+
> **forest-ui v0.3.0**
|
|
4
|
+
|
|
5
|
+
> **This file is auto-generated from the `forest-ui` package.**
|
|
6
|
+
> Run `npx forest-ui sync` to update it.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Golden Rules
|
|
11
|
+
|
|
12
|
+
1. **NEVER import from `@mui/material` directly.** Always import from `forest-ui`.
|
|
13
|
+
2. **ALWAYS wrap your app root with `<ForestProvider>`** — it applies the theme and CSS baseline.
|
|
14
|
+
3. **NEVER use inline colors or spacing values.** Use the exported design tokens or MUI's `sx` prop with theme values.
|
|
15
|
+
4. **NEVER create custom component wrappers** for things Forest UI already provides.
|
|
16
|
+
5. **TypeScript is required.** All components export their prop types.
|
|
17
|
+
6. **ALWAYS use the Outlined variant of MUI icons.** Import from `@mui/icons-material/*Outlined` (e.g. `CloseOutlined`, `MailOutlined`). Never use the default (filled), Rounded, Sharp, or TwoTone variants.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 2. Installation & Setup
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @matteoaliano/forest-ui @mui/material @mui/x-data-grid @mui/x-date-pickers @mui/x-charts dayjs @emotion/react @emotion/styled
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
// App root — REQUIRED
|
|
29
|
+
import { ForestProvider } from "@matteoaliano/forest-ui";
|
|
30
|
+
|
|
31
|
+
function App() {
|
|
32
|
+
return (
|
|
33
|
+
<ForestProvider>
|
|
34
|
+
{/* All app content here */}
|
|
35
|
+
</ForestProvider>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 3. Component Reference
|
|
43
|
+
|
|
44
|
+
### Import Pattern
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
// ✅ CORRECT — import from forest-ui
|
|
48
|
+
import { Button, TextField, Alert } from "@matteoaliano/forest-ui";
|
|
49
|
+
|
|
50
|
+
// ❌ WRONG — never import from @mui/material
|
|
51
|
+
import Button from "@mui/material/Button";
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Available Components
|
|
55
|
+
|
|
56
|
+
#### Inputs
|
|
57
|
+
|
|
58
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
59
|
+
|-----------|--------|----------------------|---------------|
|
|
60
|
+
| `Button` | `import { Button } from "forest-ui"` | `variant: "contained" \| "outlined" \| "text"`, `color`, `disabled`, `startIcon`, `endIcon`, `loading`, `fullWidth`, `href` | `variant="contained"`, `size` prop removed |
|
|
61
|
+
| `ButtonGroup` | `import { ButtonGroup } from "forest-ui"` | `variant: "contained" \| "outlined" \| "text"`, `size: "small" \| "medium" \| "large"`, `orientation: "horizontal" \| "vertical"`, `color`, `disabled`, `fullWidth` | `variant="contained"` |
|
|
62
|
+
| `TextField` | `import { TextField } from "forest-ui"` | `variant: "outlined" \| "filled" \| "standard"`, `size: "small" \| "medium"`, `label`, `error`, `helperText`, `fullWidth`, `multiline`, `rows`, `type`, `placeholder`, `required`, `disabled` | — |
|
|
63
|
+
| `Select` + `MenuItem` | `import { Select, MenuItem } from "forest-ui"` | `variant: "outlined" \| "filled" \| "standard"`, `size: "small" \| "medium"`, `multiple`, `displayEmpty`, `label`, `labelId`, `renderValue`, `native`, `error`, `disabled` | — |
|
|
64
|
+
| `MultiSelect` | `import { MultiSelect } from "forest-ui"` | `options: { label, value }[]`, `value: string[]`, `onChange: (values) => void`, `selectAll: boolean`, `selectAllLabel: string`, `label` + all SelectProps | `selectAll={true}`, `selectAllLabel="Select All"` |
|
|
65
|
+
| `Checkbox` | `import { Checkbox } from "forest-ui"` | `color: "default" \| "primary" \| "secondary" \| "error" \| "info" \| "success" \| "warning"`, `size: "small" \| "medium"`, `checked`, `indeterminate`, `disabled` | — |
|
|
66
|
+
| `RadioGroup` + `Radio` | `import { RadioGroup, Radio } from "forest-ui"` | `row`, `value`, `onChange`; Radio: `color`, `size: "small" \| "medium" \| "large"`, `disabled` | — |
|
|
67
|
+
| `Switch` | `import { Switch } from "forest-ui"` | `color: "default" \| "primary" \| "secondary" \| "error" \| "info" \| "success" \| "warning"`, `size: "small" \| "medium"`, `checked`, `disabled` | — |
|
|
68
|
+
| `ToggleButton` + `ToggleButtonGroup` | `import { ToggleButton, ToggleButtonGroup } from "forest-ui"` | `value`, `exclusive`, `onChange`, `orientation: "horizontal" \| "vertical"`, `size: "small" \| "medium" \| "large"`, `color`, `fullWidth` | — |
|
|
69
|
+
| `Fab` | `import { Fab } from "forest-ui"` | `variant: "circular" \| "extended"`, `size: "small" \| "medium" \| "large"`, `color`, `disabled`, `href` | `color="primary"` |
|
|
70
|
+
| `Autocomplete` | `import { Autocomplete } from "forest-ui"` | `options`, `renderInput` (required), `multiple`, `freeSolo`, `disableClearable`, `loading`, `groupBy`, `limitTags`, `filterOptions` | — |
|
|
71
|
+
| `Search` | `import { Search } from "forest-ui"` | `onClear`, `placeholder`, all TextField props (except `variant`) | `variant="outlined"`, `placeholder="Search…"`, built-in search icon and clear button |
|
|
72
|
+
| `DatePicker` | `import { DatePicker } from "forest-ui"` | All MUI X DatePicker props (`value`, `onChange`, `label`, `format`, `minDate`, `maxDate`, `disabled`, `readOnly`) | Wraps with `LocalizationProvider` + `AdapterDayjs` automatically |
|
|
73
|
+
|
|
74
|
+
#### Data Display
|
|
75
|
+
|
|
76
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
77
|
+
|-----------|--------|----------------------|---------------|
|
|
78
|
+
| `Badge` | `import { Badge } from "forest-ui"` | `variant: "standard" \| "dot"`, `color: "default" \| "primary" \| "secondary" \| "error" \| "info" \| "success" \| "warning"`, `badgeContent`, `max`, `invisible`, `showZero`, `overlap: "rectangular" \| "circular"`, `anchorOrigin` | — |
|
|
79
|
+
| `Chip` | `import { Chip } from "forest-ui"` | `variant: "filled" \| "outlined"`, `color: "default" \| "primary" \| "secondary" \| "error" \| "info" \| "success" \| "warning"`, `size: "small" \| "medium"`, `label`, `onDelete`, `clickable`, `avatar`, `icon` | `deleteIcon={<CloseOutlined />}` |
|
|
80
|
+
| `Divider` | `import { Divider } from "forest-ui"` | `orientation: "horizontal" \| "vertical"`, `variant: "fullWidth" \| "inset" \| "middle"`, `textAlign: "center" \| "left" \| "right"`, `flexItem` | — |
|
|
81
|
+
| `Typography` | `import { Typography } from "forest-ui"` | `variant: "h1" \| "h2" \| "h3" \| "h4" \| "h5" \| "h6" \| "subtitle1" \| "subtitle2" \| "body1" \| "body2" \| "caption" \| "overline" \| "button"`, `align: "inherit" \| "left" \| "center" \| "right" \| "justify"`, `gutterBottom`, `noWrap` | — |
|
|
82
|
+
| `Tooltip` | `import { Tooltip } from "forest-ui"` | `title` (required), `placement` (12 positions: top/bottom/left/right + -start/-end), `arrow`, `followCursor`, `enterDelay`, `leaveDelay` | `arrow={true}` |
|
|
83
|
+
| `Table` family | `import { Table, TableHead, TableBody, TableRow, TableCell, TableContainer } from "forest-ui"` | Table: `size: "small" \| "medium"`, `stickyHeader`; TableCell: `align`, `padding`, `sortDirection`, `variant: "head" \| "body" \| "footer"`; TableRow: `hover`, `selected` | — |
|
|
84
|
+
| `DataGrid` | `import { DataGrid, type GridColDef } from "forest-ui"` | `rows`, `columns`, `paginationModel`, `sortModel`, `filterModel`, `checkboxSelection`, `loading`, `density: "compact" \| "standard" \| "comfortable"`. Requires `@mui/x-data-grid` peer dep | — |
|
|
85
|
+
| `List` family | `import { List, ListItem, ListItemButton, ListItemIcon, ListItemText, ListItemAvatar, ListSubheader } from "forest-ui"` | `dense`, `disablePadding`; ListItemButton: `selected`, `disabled`; ListItemText: `primary`, `secondary` | — |
|
|
86
|
+
|
|
87
|
+
#### Surfaces
|
|
88
|
+
|
|
89
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
90
|
+
|-----------|--------|----------------------|---------------|
|
|
91
|
+
| `Accordion` family | `import { Accordion, AccordionSummary, AccordionDetails, AccordionActions } from "forest-ui"` | `expanded`, `defaultExpanded`, `onChange`, `disabled`, `disableGutters`, `square` | — |
|
|
92
|
+
| `AppBar` + `Toolbar` | `import { AppBar, Toolbar } from "forest-ui"` | `position: "fixed" \| "absolute" \| "sticky" \| "static" \| "relative"`, `color: "default" \| "primary" \| "secondary" \| "transparent"`, `elevation`; Toolbar: `variant: "dense" \| "regular"` | — |
|
|
93
|
+
| `Card` family | `import { Card, CardContent, CardHeader, CardActions, CardMedia } from "forest-ui"` | `variant: "elevation" \| "outlined"`, `elevation`, `raised`; CardHeader: `title`, `subheader`, `avatar`, `action` | — |
|
|
94
|
+
| `Paper` | `import { Paper } from "forest-ui"` | `variant: "elevation" \| "outlined"`, `elevation` (0–24), `square` | — |
|
|
95
|
+
|
|
96
|
+
#### Feedback
|
|
97
|
+
|
|
98
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
99
|
+
|-----------|--------|----------------------|---------------|
|
|
100
|
+
| `Alert` + `AlertTitle` | `import { Alert, AlertTitle } from "forest-ui"` | `severity: "success" \| "info" \| "warning" \| "error"`, `variant: "filled" \| "outlined" \| "standard"`, `color`, `icon`, `action`, `onClose` | — |
|
|
101
|
+
| `Dialog` family | `import { Dialog, DialogTitle, DialogContent, DialogActions, DialogContentText } from "forest-ui"` | `open` (required), `onClose`, `fullWidth`, `maxWidth: "xs" \| "sm" \| "md" \| "lg" \| "xl" \| false`, `fullScreen`, `scroll: "paper" \| "body"` | — |
|
|
102
|
+
| `Backdrop` | `import { Backdrop } from "forest-ui"` | `open` (required), `invisible`, `onClick` | — |
|
|
103
|
+
| `LinearProgress` | `import { LinearProgress } from "forest-ui"` | `variant: "indeterminate" \| "determinate" \| "buffer" \| "query"`, `value` (0–100), `color` | — |
|
|
104
|
+
| `CircularProgress` | `import { CircularProgress } from "forest-ui"` | `variant: "indeterminate" \| "determinate"`, `value` (0–100), `color`, `size`, `thickness` | — |
|
|
105
|
+
| `Skeleton` | `import { Skeleton } from "forest-ui"` | `variant: "text" \| "circular" \| "rectangular" \| "rounded"`, `animation: "pulse" \| "wave" \| false`, `width`, `height` | — |
|
|
106
|
+
| `Modal` | `import { Modal } from "forest-ui"` | `open` (required), `onClose`, `children`, `keepMounted`, `disableAutoFocus`, `disableEnforceFocus`, `disableEscapeKeyDown`, `disablePortal`, `disableScrollLock` | — |
|
|
107
|
+
| `Popover` | `import { Popover } from "forest-ui"` | `open` (required), `anchorEl`, `onClose`, `anchorOrigin`, `transformOrigin`, `elevation` | — |
|
|
108
|
+
| `Snackbar` | `import { Snackbar } from "forest-ui"` | `open`, `message`, `autoHideDuration`, `onClose`, `action`, `anchorOrigin: { vertical, horizontal }` | — |
|
|
109
|
+
|
|
110
|
+
#### Navigation
|
|
111
|
+
|
|
112
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
113
|
+
|-----------|--------|----------------------|---------------|
|
|
114
|
+
| `Breadcrumbs` | `import { Breadcrumbs } from "forest-ui"` | `separator`, `maxItems`, `itemsAfterCollapse`, `itemsBeforeCollapse` | — |
|
|
115
|
+
| `Link` | `import { Link } from "forest-ui"` | `href`, `underline: "none" \| "hover" \| "always"`, `color`, `variant` | — |
|
|
116
|
+
| `Menu` + `MenuList` | `import { Menu, MenuList } from "forest-ui"` | Menu: `open` (required), `anchorEl`, `onClose`; use with `MenuItem` from Select | — |
|
|
117
|
+
| `Pagination` | `import { Pagination } from "forest-ui"` | `count`, `page`, `onChange`, `variant: "text" \| "outlined"`, `shape: "circular" \| "rounded"`, `size: "small" \| "medium" \| "large"`, `color`, `showFirstButton`, `showLastButton` | — |
|
|
118
|
+
| `Stepper` family | `import { Stepper, Step, StepLabel } from "forest-ui"` | `activeStep`, `orientation: "horizontal" \| "vertical"`, `alternativeLabel`, `nonLinear`; Step: `completed`, `disabled`; StepLabel: `optional`, `error` | — |
|
|
119
|
+
| `Tabs` + `Tab` | `import { Tabs, Tab } from "forest-ui"` | Tabs: `value`, `onChange`, `variant: "standard" \| "scrollable" \| "fullWidth"`, `orientation`, `centered`; Tab: `label`, `icon`, `iconPosition`, `disabled`, `value` | — |
|
|
120
|
+
| `SidebarNav` | `import { SidebarNav, SidebarItem, useSidebar } from "forest-ui"` | `open`, `onOpenChange`, `behavior: "permanent" \| "hover"`, `expandedWidth`, `collapsedWidth`, `showToggle`, `header`, `footer` | `expandedWidth=240`, `collapsedWidth=48`, `behavior="permanent"` |
|
|
121
|
+
| `SidebarItem` | (same import) | `icon` (required), `label` (required), `endAdornment`, `selected`, `onClick`, `disabled` | — |
|
|
122
|
+
|
|
123
|
+
#### Charts
|
|
124
|
+
|
|
125
|
+
Requires `@mui/x-charts` peer dependency. Chart colors are automatically applied from the theme's 12-color series palette — no manual color assignment needed.
|
|
126
|
+
|
|
127
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
128
|
+
|-----------|--------|----------------------|---------------|
|
|
129
|
+
| `BarChart` | `import { BarChart } from "forest-ui"` | `series` (supports `variant: "solid" \| "striped"` per series), `colors`, `xAxis`, `yAxis`, `width`, `height` | `grid horizontal`, `borderRadius=4`, highlight/fade on hover |
|
|
130
|
+
| `LineChart` | `import { LineChart } from "forest-ui"` | `series`, `colors`, `xAxis`, `yAxis`, `width`, `height` | `curve="linear"`, `strokeWidth=3`, `grid horizontal`, highlight/fade on hover |
|
|
131
|
+
| `PieChart` | `import { PieChart } from "forest-ui"` | `series` (data: `{ id, value, label, color? }[]`), `colors`, `width`, `height` | highlight/fade on hover |
|
|
132
|
+
| `useChartColors` | `import { useChartColors } from "forest-ui"` | `useChartColors(count)` — returns `string[]` of theme chart series colors, sliced to the requested count (max 12) | — |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 4. Code Patterns
|
|
137
|
+
|
|
138
|
+
### Form Layout
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
import { TextField, Button, Select, MenuItem, Checkbox } from "@matteoaliano/forest-ui";
|
|
142
|
+
import Box from "@mui/material/Box"; // Box, Stack, Grid are OK from MUI
|
|
143
|
+
|
|
144
|
+
function ContactForm() {
|
|
145
|
+
return (
|
|
146
|
+
<Box sx={{ display: "flex", flexDirection: "column", gap: 3 }}>
|
|
147
|
+
<TextField label="Name" fullWidth />
|
|
148
|
+
<TextField label="Email" type="email" fullWidth />
|
|
149
|
+
<Select label="Subject" fullWidth>
|
|
150
|
+
<MenuItem value="support">Support</MenuItem>
|
|
151
|
+
<MenuItem value="sales">Sales</MenuItem>
|
|
152
|
+
</Select>
|
|
153
|
+
<Button variant="contained" type="submit">
|
|
154
|
+
Send
|
|
155
|
+
</Button>
|
|
156
|
+
</Box>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### MultiSelect with Select All
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
import { useState } from "react";
|
|
165
|
+
import { MultiSelect } from "@matteoaliano/forest-ui";
|
|
166
|
+
|
|
167
|
+
const options = [
|
|
168
|
+
{ label: "Bug", value: "bug" },
|
|
169
|
+
{ label: "Enhancement", value: "enhancement" },
|
|
170
|
+
{ label: "New Feature", value: "feature" },
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
function CategoryFilter() {
|
|
174
|
+
const [selected, setSelected] = useState<string[]>([]);
|
|
175
|
+
return (
|
|
176
|
+
<MultiSelect
|
|
177
|
+
label="Category"
|
|
178
|
+
options={options}
|
|
179
|
+
value={selected}
|
|
180
|
+
onChange={setSelected}
|
|
181
|
+
/>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Data Table
|
|
187
|
+
|
|
188
|
+
```tsx
|
|
189
|
+
import {
|
|
190
|
+
Table, TableContainer, TableHead, TableBody, TableRow, TableCell,
|
|
191
|
+
} from "@matteoaliano/forest-ui";
|
|
192
|
+
|
|
193
|
+
function UsersTable({ users }) {
|
|
194
|
+
return (
|
|
195
|
+
<TableContainer>
|
|
196
|
+
<Table>
|
|
197
|
+
<TableHead>
|
|
198
|
+
<TableRow>
|
|
199
|
+
<TableCell>Name</TableCell>
|
|
200
|
+
<TableCell>Email</TableCell>
|
|
201
|
+
</TableRow>
|
|
202
|
+
</TableHead>
|
|
203
|
+
<TableBody>
|
|
204
|
+
{users.map((u) => (
|
|
205
|
+
<TableRow key={u.id}>
|
|
206
|
+
<TableCell>{u.name}</TableCell>
|
|
207
|
+
<TableCell>{u.email}</TableCell>
|
|
208
|
+
</TableRow>
|
|
209
|
+
))}
|
|
210
|
+
</TableBody>
|
|
211
|
+
</Table>
|
|
212
|
+
</TableContainer>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### DataGrid
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import { DataGrid, type GridColDef } from "@matteoaliano/forest-ui";
|
|
221
|
+
|
|
222
|
+
const columns: GridColDef[] = [
|
|
223
|
+
{ field: "id", headerName: "ID", width: 70 },
|
|
224
|
+
{ field: "name", headerName: "Name", flex: 1 },
|
|
225
|
+
{ field: "email", headerName: "Email", flex: 1 },
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
function UsersGrid({ rows }) {
|
|
229
|
+
return <DataGrid rows={rows} columns={columns} />;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Feedback Pattern
|
|
234
|
+
|
|
235
|
+
```tsx
|
|
236
|
+
import { Alert, AlertTitle, Snackbar } from "@matteoaliano/forest-ui";
|
|
237
|
+
|
|
238
|
+
// Inline feedback
|
|
239
|
+
<Alert severity="error">
|
|
240
|
+
<AlertTitle>Error</AlertTitle>
|
|
241
|
+
Something went wrong.
|
|
242
|
+
</Alert>
|
|
243
|
+
|
|
244
|
+
// Toast notification
|
|
245
|
+
<Snackbar open={open} autoHideDuration={4000} onClose={handleClose}>
|
|
246
|
+
<Alert severity="success" variant="filled">Saved!</Alert>
|
|
247
|
+
</Snackbar>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Confirmation Dialog
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
import { Dialog, DialogTitle, DialogContent, DialogActions, DialogContentText, Button } from "@matteoaliano/forest-ui";
|
|
254
|
+
|
|
255
|
+
function ConfirmDialog({ open, onClose, onConfirm }) {
|
|
256
|
+
return (
|
|
257
|
+
<Dialog open={open} onClose={onClose}>
|
|
258
|
+
<DialogTitle>Confirm</DialogTitle>
|
|
259
|
+
<DialogContent>
|
|
260
|
+
<DialogContentText>Are you sure?</DialogContentText>
|
|
261
|
+
</DialogContent>
|
|
262
|
+
<DialogActions>
|
|
263
|
+
<Button variant="outlined" onClick={onClose}>Cancel</Button>
|
|
264
|
+
<Button onClick={onConfirm}>Confirm</Button>
|
|
265
|
+
</DialogActions>
|
|
266
|
+
</Dialog>
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Sidebar Navigation
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
import { SidebarNav, SidebarItem } from "@matteoaliano/forest-ui";
|
|
275
|
+
import DashboardOutlined from "@mui/icons-material/DashboardOutlined";
|
|
276
|
+
import SettingsOutlined from "@mui/icons-material/SettingsOutlined";
|
|
277
|
+
|
|
278
|
+
function AppShell() {
|
|
279
|
+
const [open, setOpen] = useState(true);
|
|
280
|
+
return (
|
|
281
|
+
<SidebarNav open={open} onOpenChange={setOpen}>
|
|
282
|
+
<SidebarItem icon={<DashboardOutlined />} label="Dashboard" selected />
|
|
283
|
+
<SidebarItem icon={<SettingsOutlined />} label="Settings" />
|
|
284
|
+
</SidebarNav>
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Charts
|
|
290
|
+
|
|
291
|
+
Colors are automatically assigned from the theme's 12-series palette. Override with the `colors` prop if needed.
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
import { BarChart, LineChart, PieChart, useChartColors } from "@matteoaliano/forest-ui";
|
|
295
|
+
|
|
296
|
+
// Bar chart with striped variant
|
|
297
|
+
<BarChart
|
|
298
|
+
series={[
|
|
299
|
+
{ data: [10, 20, 30], label: "Current", variant: "solid" },
|
|
300
|
+
{ data: [8, 15, 25], label: "Previous", variant: "striped" },
|
|
301
|
+
]}
|
|
302
|
+
xAxis={[{ data: ["Jan", "Feb", "Mar"], scaleType: "band" }]}
|
|
303
|
+
height={300}
|
|
304
|
+
/>
|
|
305
|
+
|
|
306
|
+
// Line chart
|
|
307
|
+
<LineChart
|
|
308
|
+
series={[{ data: [10, 20, 30], label: "Revenue" }]}
|
|
309
|
+
xAxis={[{ data: ["Jan", "Feb", "Mar"], scaleType: "band" }]}
|
|
310
|
+
height={300}
|
|
311
|
+
/>
|
|
312
|
+
|
|
313
|
+
// Pie chart
|
|
314
|
+
<PieChart
|
|
315
|
+
series={[{ data: [
|
|
316
|
+
{ id: 0, value: 40, label: "Desktop" },
|
|
317
|
+
{ id: 1, value: 30, label: "Mobile" },
|
|
318
|
+
{ id: 2, value: 30, label: "Tablet" },
|
|
319
|
+
]}]}
|
|
320
|
+
height={300}
|
|
321
|
+
/>
|
|
322
|
+
|
|
323
|
+
// Access chart colors programmatically
|
|
324
|
+
const colors = useChartColors(3); // ["#7c3aed", "#e36c09", "#5fe0d0"]
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## 5. Anti-Patterns
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
// ❌ WRONG: importing from @mui/material
|
|
333
|
+
import Button from "@mui/material/Button";
|
|
334
|
+
|
|
335
|
+
// ❌ WRONG: hardcoded colors
|
|
336
|
+
<Box sx={{ backgroundColor: "#7f56d9" }} />
|
|
337
|
+
|
|
338
|
+
// ❌ WRONG: hardcoded spacing
|
|
339
|
+
<Box sx={{ padding: "16px" }} />
|
|
340
|
+
|
|
341
|
+
// ❌ WRONG: forgetting ForestProvider
|
|
342
|
+
ReactDOM.render(<App />, root); // theme won't apply
|
|
343
|
+
|
|
344
|
+
// ❌ WRONG: using filled (default) icons
|
|
345
|
+
import CloseIcon from "@mui/icons-material/Close";
|
|
346
|
+
|
|
347
|
+
// ✅ CORRECT: always use Outlined variant
|
|
348
|
+
import CloseIcon from "@mui/icons-material/CloseOutlined";
|
|
349
|
+
|
|
350
|
+
// ✅ CORRECT: use theme tokens
|
|
351
|
+
<Box sx={{ backgroundColor: "primary.main", p: 4 }} />
|
|
352
|
+
|
|
353
|
+
// ❌ WRONG: manually building multi-select with Select + Checkbox
|
|
354
|
+
// ✅ CORRECT: use the MultiSelect component
|
|
355
|
+
<MultiSelect options={options} value={value} onChange={setValue} />
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
> **Note:** Layout primitives like `Box`, `Stack`, `Grid`, and `Container` should still be imported from `@mui/material` — Forest UI does not re-export these because they have no custom styling.
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## 6. TypeScript Props
|
|
363
|
+
|
|
364
|
+
Every component exports its props type:
|
|
365
|
+
|
|
366
|
+
```tsx
|
|
367
|
+
import { Button, type ButtonProps } from "@matteoaliano/forest-ui";
|
|
368
|
+
|
|
369
|
+
interface MyButtonProps extends ButtonProps {
|
|
370
|
+
analyticsId: string;
|
|
371
|
+
}
|
|
372
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matteoaliano/forest-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Forest Design System — themed MUI components",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -33,15 +33,20 @@
|
|
|
33
33
|
"build": "tsup",
|
|
34
34
|
"prepublishOnly": "node bin/stamp-version.mjs && tsup && node bin/sync.mjs",
|
|
35
35
|
"dev": "tsup --watch",
|
|
36
|
+
"test": "vitest",
|
|
37
|
+
"test:coverage": "vitest --coverage",
|
|
36
38
|
"storybook": "storybook dev -p 6006",
|
|
37
|
-
"build-storybook": "storybook build"
|
|
39
|
+
"build-storybook": "storybook build",
|
|
40
|
+
"chromatic": "chromatic --exit-zero-on-changes"
|
|
38
41
|
},
|
|
39
42
|
"peerDependencies": {
|
|
40
43
|
"@emotion/react": "^11.0.0",
|
|
41
44
|
"@emotion/styled": "^11.0.0",
|
|
42
45
|
"@mui/material": "^6.0.0 || ^7.0.0",
|
|
43
|
-
"@mui/x-data-grid": "^7.0.0",
|
|
44
46
|
"@mui/x-charts": "^7.0.0",
|
|
47
|
+
"@mui/x-data-grid": "^7.0.0",
|
|
48
|
+
"@mui/x-date-pickers": "^7.0.0 || ^8.0.0",
|
|
49
|
+
"dayjs": "^1.11.0",
|
|
45
50
|
"react": "^18.0.0 || ^19.0.0",
|
|
46
51
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
47
52
|
},
|
|
@@ -50,13 +55,20 @@
|
|
|
50
55
|
"@emotion/styled": "^11.0.0",
|
|
51
56
|
"@mui/icons-material": "^7.3.8",
|
|
52
57
|
"@mui/material": "^7.0.0",
|
|
53
|
-
"@mui/x-data-grid": "^7.0.0",
|
|
54
58
|
"@mui/x-charts": "^7.0.0",
|
|
59
|
+
"@mui/x-data-grid": "^7.0.0",
|
|
60
|
+
"@mui/x-date-pickers": "^8.27.2",
|
|
55
61
|
"@storybook/addon-essentials": "^8.6.17",
|
|
56
62
|
"@storybook/blocks": "^8.6.17",
|
|
57
63
|
"@storybook/react": "^8.6.17",
|
|
58
64
|
"@storybook/react-vite": "^8.6.17",
|
|
65
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
66
|
+
"@testing-library/react": "^16.3.2",
|
|
59
67
|
"@types/react": "^19.0.0",
|
|
68
|
+
"@vitejs/plugin-react": "^5.1.4",
|
|
69
|
+
"chromatic": "^15.2.0",
|
|
70
|
+
"dayjs": "^1.11.19",
|
|
71
|
+
"jsdom": "^28.1.0",
|
|
60
72
|
"react": "^19.0.0",
|
|
61
73
|
"react-dom": "^19.0.0",
|
|
62
74
|
"storybook": "^8.6.17",
|