@matteoaliano/forest-ui 0.4.0 → 0.4.1

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.
@@ -1,408 +0,0 @@
1
- # Forest UI — AI Development Guidelines
2
-
3
- > **forest-ui v0.4.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
- | `IconButton` | `import { IconButton } from "forest-ui"` | `color: "inherit" \| "primary" \| "secondary" \| "error" \| "info" \| "success" \| "warning" \| "default"`, `size: "small" \| "medium" \| "large"`, `disabled`, `disableRipple` | — |
71
- | `Autocomplete` | `import { Autocomplete } from "forest-ui"` | `options`, `renderInput` (required), `multiple`, `freeSolo`, `disableClearable`, `loading`, `groupBy`, `limitTags`, `filterOptions` | — |
72
- | `Search` | `import { Search } from "forest-ui"` | `onClear`, `placeholder`, all TextField props (except `variant`) | `variant="outlined"`, `placeholder="Search…"`, built-in search icon and clear button |
73
- | `DatePicker` | `import { DatePicker } from "forest-ui"` | All MUI X DatePicker props (`value`, `onChange`, `label`, `format`, `minDate`, `maxDate`, `disabled`, `readOnly`) | Wraps with `LocalizationProvider` + `AdapterDayjs` automatically |
74
-
75
- #### Data Display
76
-
77
- | Component | Import | Variants / Key Props | Default Props |
78
- |-----------|--------|----------------------|---------------|
79
- | `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` | — |
80
- | `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 />}` |
81
- | `Divider` | `import { Divider } from "forest-ui"` | `orientation: "horizontal" \| "vertical"`, `variant: "fullWidth" \| "inset" \| "middle"`, `textAlign: "center" \| "left" \| "right"`, `flexItem` | — |
82
- | `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` | — |
83
- | `Tooltip` | `import { Tooltip } from "forest-ui"` | `title` (required), `placement` (12 positions: top/bottom/left/right + -start/-end), `arrow`, `followCursor`, `enterDelay`, `leaveDelay` | `arrow={true}` |
84
- | `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` | — |
85
- | `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 | — |
86
- | `List` family | `import { List, ListItem, ListItemButton, ListItemIcon, ListItemText, ListItemAvatar, ListSubheader } from "forest-ui"` | `dense`, `disablePadding`; ListItemButton: `selected`, `disabled`; ListItemText: `primary`, `secondary` | — |
87
-
88
- #### Surfaces
89
-
90
- | Component | Import | Variants / Key Props | Default Props |
91
- |-----------|--------|----------------------|---------------|
92
- | `Accordion` family | `import { Accordion, AccordionSummary, AccordionDetails, AccordionActions } from "forest-ui"` | `expanded`, `defaultExpanded`, `onChange`, `disabled`, `disableGutters`, `square` | — |
93
- | `AppBar` + `Toolbar` + `AppBarNavItem` | `import { AppBar, Toolbar, AppBarNavItem } from "forest-ui"` | `position: "fixed" \| "absolute" \| "sticky" \| "static" \| "relative"`, `color: "default" \| "primary" \| "secondary" \| "transparent"`, `elevation`; Toolbar: `variant: "dense" \| "regular"`; AppBarNavItem: `label` (required), `icon`, `selected`, `href` | — |
94
- | `Card` family | `import { Card, CardContent, CardHeader, CardActions, CardMedia } from "forest-ui"` | `color: "primary" \| "secondary"`, `variant: "elevation" \| "outlined"`, `elevation`, `raised`; CardHeader: `title`, `subheader`, `avatar`, `action` | `color: "primary"` |
95
- | `Paper` | `import { Paper } from "forest-ui"` | `variant: "elevation" \| "outlined"`, `elevation` (0–24), `square` | — |
96
-
97
- #### Feedback
98
-
99
- | Component | Import | Variants / Key Props | Default Props |
100
- |-----------|--------|----------------------|---------------|
101
- | `Alert` + `AlertTitle` | `import { Alert, AlertTitle } from "forest-ui"` | `severity: "success" \| "info" \| "warning" \| "error"`, `variant: "filled" \| "outlined" \| "standard"`, `color`, `icon`, `action`, `onClose` | — |
102
- | `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"` | — |
103
- | `Backdrop` | `import { Backdrop } from "forest-ui"` | `open` (required), `invisible`, `onClick` | — |
104
- | `LinearProgress` | `import { LinearProgress } from "forest-ui"` | `variant: "indeterminate" \| "determinate" \| "buffer" \| "query"`, `value` (0–100), `color` | — |
105
- | `CircularProgress` | `import { CircularProgress } from "forest-ui"` | `variant: "indeterminate" \| "determinate"`, `value` (0–100), `color`, `size`, `thickness` | — |
106
- | `Skeleton` | `import { Skeleton } from "forest-ui"` | `variant: "text" \| "circular" \| "rectangular" \| "rounded"`, `animation: "pulse" \| "wave" \| false`, `width`, `height` | — |
107
- | `Modal` | `import { Modal } from "forest-ui"` | `open` (required), `onClose`, `children`, `keepMounted`, `disableAutoFocus`, `disableEnforceFocus`, `disableEscapeKeyDown`, `disablePortal`, `disableScrollLock` | — |
108
- | `Popover` | `import { Popover } from "forest-ui"` | `open` (required), `anchorEl`, `onClose`, `anchorOrigin`, `transformOrigin`, `elevation` | — |
109
- | `Snackbar` | `import { Snackbar } from "forest-ui"` | `open`, `message`, `autoHideDuration`, `onClose`, `action`, `anchorOrigin: { vertical, horizontal }` | — |
110
-
111
- #### Navigation
112
-
113
- | Component | Import | Variants / Key Props | Default Props |
114
- |-----------|--------|----------------------|---------------|
115
- | `Breadcrumbs` | `import { Breadcrumbs } from "forest-ui"` | `separator`, `maxItems`, `itemsAfterCollapse`, `itemsBeforeCollapse` | — |
116
- | `Link` | `import { Link } from "forest-ui"` | `href`, `underline: "none" \| "hover" \| "always"`, `color`, `variant` | — |
117
- | `Menu` + `MenuList` | `import { Menu, MenuList } from "forest-ui"` | Menu: `open` (required), `anchorEl`, `onClose`; use with `MenuItem` from Select | — |
118
- | `Pagination` | `import { Pagination } from "forest-ui"` | `count`, `page`, `onChange`, `variant: "text" \| "outlined"`, `shape: "circular" \| "rounded"`, `size: "small" \| "medium" \| "large"`, `color`, `showFirstButton`, `showLastButton` | — |
119
- | `Stepper` family | `import { Stepper, Step, StepLabel } from "forest-ui"` | `activeStep`, `orientation: "horizontal" \| "vertical"`, `alternativeLabel`, `nonLinear`; Step: `completed`, `disabled`; StepLabel: `optional`, `error` | — |
120
- | `Tabs` + `Tab` | `import { Tabs, Tab } from "forest-ui"` | Tabs: `value`, `onChange`, `variant: "standard" \| "scrollable" \| "fullWidth"`, `orientation`, `centered`; Tab: `label`, `icon`, `iconPosition`, `disabled`, `value` | — |
121
- | `SidebarNav` | `import { SidebarNav, SidebarItem, useSidebar } from "forest-ui"` | `open`, `onOpenChange`, `behavior: "permanent" \| "hover"`, `expandedWidth`, `collapsedWidth`, `showToggle`, `header`, `footer` | `expandedWidth=240`, `collapsedWidth=48`, `behavior="permanent"` |
122
- | `SidebarItem` | (same import) | `icon` (required), `label` (required), `endAdornment`, `selected`, `onClick`, `disabled` | — |
123
-
124
- #### Charts
125
-
126
- Requires `@mui/x-charts` peer dependency. Chart colors are automatically applied from the theme's 12-color series palette — no manual color assignment needed.
127
-
128
- | Component | Import | Variants / Key Props | Default Props |
129
- |-----------|--------|----------------------|---------------|
130
- | `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 |
131
- | `LineChart` | `import { LineChart } from "forest-ui"` | `series`, `colors`, `xAxis`, `yAxis`, `width`, `height` | `curve="linear"`, `strokeWidth=3`, `grid horizontal`, highlight/fade on hover |
132
- | `PieChart` | `import { PieChart } from "forest-ui"` | `series` (data: `{ id, value, label, color? }[]`), `colors`, `width`, `height` | highlight/fade on hover |
133
- | `useChartColors` | `import { useChartColors } from "forest-ui"` | `useChartColors(count)` — returns `string[]` of theme chart series colors, sliced to the requested count (max 12) | — |
134
-
135
- ---
136
-
137
- ## 4. Code Patterns
138
-
139
- ### Form Layout
140
-
141
- ```tsx
142
- import { TextField, Button, Select, MenuItem, Checkbox } from "@matteoaliano/forest-ui";
143
- import Box from "@mui/material/Box"; // Box, Stack, Grid are OK from MUI
144
-
145
- function ContactForm() {
146
- return (
147
- <Box sx={{ display: "flex", flexDirection: "column", gap: 3 }}>
148
- <TextField label="Name" fullWidth />
149
- <TextField label="Email" type="email" fullWidth />
150
- <Select label="Subject" fullWidth>
151
- <MenuItem value="support">Support</MenuItem>
152
- <MenuItem value="sales">Sales</MenuItem>
153
- </Select>
154
- <Button variant="contained" type="submit">
155
- Send
156
- </Button>
157
- </Box>
158
- );
159
- }
160
- ```
161
-
162
- ### MultiSelect with Select All
163
-
164
- ```tsx
165
- import { useState } from "react";
166
- import { MultiSelect } from "@matteoaliano/forest-ui";
167
-
168
- const options = [
169
- { label: "Bug", value: "bug" },
170
- { label: "Enhancement", value: "enhancement" },
171
- { label: "New Feature", value: "feature" },
172
- ];
173
-
174
- function CategoryFilter() {
175
- const [selected, setSelected] = useState<string[]>([]);
176
- return (
177
- <MultiSelect
178
- label="Category"
179
- options={options}
180
- value={selected}
181
- onChange={setSelected}
182
- />
183
- );
184
- }
185
- ```
186
-
187
- ### Data Table
188
-
189
- ```tsx
190
- import {
191
- Table, TableContainer, TableHead, TableBody, TableRow, TableCell,
192
- } from "@matteoaliano/forest-ui";
193
-
194
- function UsersTable({ users }) {
195
- return (
196
- <TableContainer>
197
- <Table>
198
- <TableHead>
199
- <TableRow>
200
- <TableCell>Name</TableCell>
201
- <TableCell>Email</TableCell>
202
- </TableRow>
203
- </TableHead>
204
- <TableBody>
205
- {users.map((u) => (
206
- <TableRow key={u.id}>
207
- <TableCell>{u.name}</TableCell>
208
- <TableCell>{u.email}</TableCell>
209
- </TableRow>
210
- ))}
211
- </TableBody>
212
- </Table>
213
- </TableContainer>
214
- );
215
- }
216
- ```
217
-
218
- ### DataGrid
219
-
220
- ```tsx
221
- import { DataGrid, type GridColDef } from "@matteoaliano/forest-ui";
222
-
223
- const columns: GridColDef[] = [
224
- { field: "id", headerName: "ID", width: 70 },
225
- { field: "name", headerName: "Name", flex: 1 },
226
- { field: "email", headerName: "Email", flex: 1 },
227
- ];
228
-
229
- function UsersGrid({ rows }) {
230
- return <DataGrid rows={rows} columns={columns} />;
231
- }
232
- ```
233
-
234
- ### Feedback Pattern
235
-
236
- ```tsx
237
- import { Alert, AlertTitle, Snackbar } from "@matteoaliano/forest-ui";
238
-
239
- // Inline feedback
240
- <Alert severity="error">
241
- <AlertTitle>Error</AlertTitle>
242
- Something went wrong.
243
- </Alert>
244
-
245
- // Toast notification
246
- <Snackbar open={open} autoHideDuration={4000} onClose={handleClose}>
247
- <Alert severity="success" variant="filled">Saved!</Alert>
248
- </Snackbar>
249
- ```
250
-
251
- ### Confirmation Dialog
252
-
253
- ```tsx
254
- import { Dialog, DialogTitle, DialogContent, DialogActions, DialogContentText, Button } from "@matteoaliano/forest-ui";
255
-
256
- function ConfirmDialog({ open, onClose, onConfirm }) {
257
- return (
258
- <Dialog open={open} onClose={onClose}>
259
- <DialogTitle>Confirm</DialogTitle>
260
- <DialogContent>
261
- <DialogContentText>Are you sure?</DialogContentText>
262
- </DialogContent>
263
- <DialogActions>
264
- <Button variant="outlined" onClick={onClose}>Cancel</Button>
265
- <Button onClick={onConfirm}>Confirm</Button>
266
- </DialogActions>
267
- </Dialog>
268
- );
269
- }
270
- ```
271
-
272
- ### Sidebar Navigation
273
-
274
- ```tsx
275
- import { SidebarNav, SidebarItem } from "@matteoaliano/forest-ui";
276
- import DashboardOutlined from "@mui/icons-material/DashboardOutlined";
277
- import SettingsOutlined from "@mui/icons-material/SettingsOutlined";
278
-
279
- function AppShell() {
280
- const [open, setOpen] = useState(true);
281
- return (
282
- <SidebarNav open={open} onOpenChange={setOpen}>
283
- <SidebarItem icon={<DashboardOutlined />} label="Dashboard" selected />
284
- <SidebarItem icon={<SettingsOutlined />} label="Settings" />
285
- </SidebarNav>
286
- );
287
- }
288
- ```
289
-
290
- ### Charts
291
-
292
- Colors are automatically assigned from the theme's 12-series palette. Override with the `colors` prop if needed.
293
-
294
- ```tsx
295
- import { BarChart, LineChart, PieChart, useChartColors } from "@matteoaliano/forest-ui";
296
-
297
- // Bar chart with striped variant
298
- <BarChart
299
- series={[
300
- { data: [10, 20, 30], label: "Current", variant: "solid" },
301
- { data: [8, 15, 25], label: "Previous", variant: "striped" },
302
- ]}
303
- xAxis={[{ data: ["Jan", "Feb", "Mar"], scaleType: "band" }]}
304
- height={300}
305
- />
306
-
307
- // Line chart
308
- <LineChart
309
- series={[{ data: [10, 20, 30], label: "Revenue" }]}
310
- xAxis={[{ data: ["Jan", "Feb", "Mar"], scaleType: "band" }]}
311
- height={300}
312
- />
313
-
314
- // Pie chart
315
- <PieChart
316
- series={[{ data: [
317
- { id: 0, value: 40, label: "Desktop" },
318
- { id: 1, value: 30, label: "Mobile" },
319
- { id: 2, value: 30, label: "Tablet" },
320
- ]}]}
321
- height={300}
322
- />
323
-
324
- // Access chart colors programmatically
325
- const colors = useChartColors(3); // ["#7c3aed", "#e36c09", "#5fe0d0"]
326
- ```
327
-
328
- ---
329
-
330
- ## 5. Storybook
331
-
332
- All component stories include interactive argTypes controls for testing props in Storybook. Use the Controls panel to test different variants.
333
-
334
- ### Adding Controls to Stories
335
-
336
- When adding argTypes to new stories, follow this pattern:
337
-
338
- ```tsx
339
- const meta: Meta<typeof Button> = {
340
- component: Button,
341
- argTypes: {
342
- variant: {
343
- control: "select",
344
- options: ["contained", "outlined", "text"],
345
- },
346
- color: {
347
- control: "select",
348
- options: ["primary", "secondary", "error", "warning", "success", "info"],
349
- },
350
- disabled: { control: "boolean" },
351
- },
352
- };
353
- ```
354
-
355
- **Control types:**
356
- - `control: "select"` with `options: [...]` — for enum values
357
- - `control: "boolean"` — for boolean flags
358
- - `control: "number"` — for numeric values
359
- - `control: "text"` — for string values
360
-
361
- See `Button.stories.tsx` for the full reference pattern.
362
-
363
- ---
364
-
365
- ## 6. Anti-Patterns
366
-
367
- ```tsx
368
- // ❌ WRONG: importing from @mui/material
369
- import Button from "@mui/material/Button";
370
-
371
- // ❌ WRONG: hardcoded colors
372
- <Box sx={{ backgroundColor: "#7f56d9" }} />
373
-
374
- // ❌ WRONG: hardcoded spacing
375
- <Box sx={{ padding: "16px" }} />
376
-
377
- // ❌ WRONG: forgetting ForestProvider
378
- ReactDOM.render(<App />, root); // theme won't apply
379
-
380
- // ❌ WRONG: using filled (default) icons
381
- import CloseIcon from "@mui/icons-material/Close";
382
-
383
- // ✅ CORRECT: always use Outlined variant
384
- import CloseIcon from "@mui/icons-material/CloseOutlined";
385
-
386
- // ✅ CORRECT: use theme tokens
387
- <Box sx={{ backgroundColor: "primary.main", p: 4 }} />
388
-
389
- // ❌ WRONG: manually building multi-select with Select + Checkbox
390
- // ✅ CORRECT: use the MultiSelect component
391
- <MultiSelect options={options} value={value} onChange={setValue} />
392
- ```
393
-
394
- > **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.
395
-
396
- ---
397
-
398
- ## 6. TypeScript Props
399
-
400
- Every component exports its props type:
401
-
402
- ```tsx
403
- import { Button, type ButtonProps } from "@matteoaliano/forest-ui";
404
-
405
- interface MyButtonProps extends ButtonProps {
406
- analyticsId: string;
407
- }
408
- ```