@matteoaliano/forest-ui 0.3.3 → 0.3.4
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/bin/sync.mjs +30 -1
- package/dist/{chunk-J75HY2NM.mjs → chunk-G2ZXCZKP.mjs} +14 -14
- package/dist/chunk-G2ZXCZKP.mjs.map +1 -0
- package/dist/index.js +57 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -36
- package/dist/index.mjs.map +1 -1
- package/dist/theme.js +12 -12
- package/dist/theme.js.map +1 -1
- package/dist/theme.mjs +1 -1
- package/guidelines/FOREST_BE_GUIDELINES.md +1 -1
- package/guidelines/FOREST_FE_GUIDELINES.md +1 -1
- package/guidelines/FOREST_UI_GUIDELINES.md +1 -1
- package/package.json +2 -1
- package/skills/forest-agency/SKILL.md +84 -0
- package/skills/forest-agency/references/components.md +93 -0
- package/skills/forest-agency/references/patterns.md +256 -0
- package/skills/forest-external/SKILL.md +86 -0
- package/skills/forest-external/references/components.md +93 -0
- package/skills/forest-external/references/patterns.md +256 -0
- package/skills/forest-internal/SKILL.md +86 -0
- package/skills/forest-internal/references/components.md +93 -0
- package/skills/forest-internal/references/patterns.md +256 -0
- package/dist/chunk-J75HY2NM.mjs.map +0 -1
package/dist/theme.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { alpha, avatarColors, base, bg, border, breadcrumbColors, buildTheme, buildThemeOptions, buttonColors, chartColors, components, container, display, error, fg, focusRings, fontFamily, fontSize, fontWeight, forestAgencyPreset, forestExternalPreset, forestInternalPreset, forestTheme, forestThemeOptions, getAvailablePresets, getPreset, gray, iconColors, info, lineHeight, magenta, misc, navColors, palette, radius, radiusSharp, red, registerPreset, shadows2 as shadows, sliderColors, spacing, success, text, toggleColors, typography, violet, warning, widths } from './chunk-
|
|
1
|
+
export { alpha, avatarColors, base, bg, border, breadcrumbColors, buildTheme, buildThemeOptions, buttonColors, chartColors, components, container, display, error, fg, focusRings, fontFamily, fontSize, fontWeight, forestAgencyPreset, forestExternalPreset, forestInternalPreset, forestTheme, forestThemeOptions, getAvailablePresets, getPreset, gray, iconColors, info, lineHeight, magenta, misc, navColors, palette, radius, radiusSharp, red, registerPreset, shadows2 as shadows, sliderColors, spacing, success, text, toggleColors, typography, violet, warning, widths } from './chunk-G2ZXCZKP.mjs';
|
|
2
2
|
//# sourceMappingURL=theme.mjs.map
|
|
3
3
|
//# sourceMappingURL=theme.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matteoaliano/forest-ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Forest Design System — themed MUI components",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"dist",
|
|
27
27
|
"bin",
|
|
28
28
|
"guidelines",
|
|
29
|
+
"skills",
|
|
29
30
|
"fonts"
|
|
30
31
|
],
|
|
31
32
|
"scripts": {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: forest-agency
|
|
3
|
+
description: Forest UI Design System rules for the Agency (charcoal/red) preset. Enforces correct imports, component usage, and theming with @matteoaliano/forest-ui. Use when the project uses forest-ui, forest-agency preset, or when user builds UI components in a forest-ui project. Triggers on "forest", "forest-ui", "forest agency", "@matteoaliano/forest-ui".
|
|
4
|
+
metadata:
|
|
5
|
+
author: Forest Design System
|
|
6
|
+
version: 0.3.4
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Forest UI — Agency Preset
|
|
10
|
+
|
|
11
|
+
## Golden Rules
|
|
12
|
+
|
|
13
|
+
1. **NEVER import from `@mui/material` directly.** Always import from `@matteoaliano/forest-ui`. Exception: layout primitives (`Box`, `Stack`, `Grid`, `Container`) come from `@mui/material`.
|
|
14
|
+
2. **ALWAYS wrap your app root with `<ForestProvider>`** — it applies the theme and CSS baseline.
|
|
15
|
+
3. **NEVER use inline colors or spacing values.** Use design tokens or MUI's `sx` prop with theme values (`p: 4`, `backgroundColor: "primary.main"`).
|
|
16
|
+
4. **NEVER create custom component wrappers** for things Forest UI already provides.
|
|
17
|
+
5. **TypeScript is required.** All components export their prop types (e.g. `type ButtonProps`).
|
|
18
|
+
6. **ALWAYS use the Outlined variant of MUI icons.** Import from `@mui/icons-material/*Outlined` (e.g. `CloseOutlined`, `MailOutlined`). Never use filled, Rounded, Sharp, or TwoTone variants.
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @matteoaliano/forest-ui @mui/material @mui/x-data-grid @mui/x-date-pickers @mui/x-charts dayjs @emotion/react @emotion/styled
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { ForestProvider } from "@matteoaliano/forest-ui";
|
|
28
|
+
|
|
29
|
+
function App() {
|
|
30
|
+
return (
|
|
31
|
+
<ForestProvider preset="forest-agency">
|
|
32
|
+
{/* All app content here */}
|
|
33
|
+
</ForestProvider>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Preset Identity
|
|
39
|
+
|
|
40
|
+
**Atmosphere:** Bold, authoritative, and editorial — commanding yet refined.
|
|
41
|
+
|
|
42
|
+
| Role | Color | Hex |
|
|
43
|
+
|------|-------|-----|
|
|
44
|
+
| Primary (brand) | Commanding Charcoal | `#09090b` |
|
|
45
|
+
| Secondary (brand) | Deep Onyx | `#18181b` |
|
|
46
|
+
| Accent | Signal Red | `#FF2821` |
|
|
47
|
+
| Background | Warm Parchment | `#faf9f8` |
|
|
48
|
+
| Surface | Pure White | `#ffffff` |
|
|
49
|
+
| Text primary | Near-Black Ink | `#18181b` |
|
|
50
|
+
| Text secondary | Steel Gray | `#3f3f46` |
|
|
51
|
+
| Border primary | Silver Mist | `#d8d8dc` |
|
|
52
|
+
| Success | Verdant | `#079455` |
|
|
53
|
+
| Warning | Amber | `#dc6803` |
|
|
54
|
+
| Error | Coral | `#d92d20` |
|
|
55
|
+
| Info | Sky | `#1570ef` |
|
|
56
|
+
|
|
57
|
+
**Corner radius:** Sharp and architectural (4px for buttons/inputs, up to 12px for cards/modals).
|
|
58
|
+
**Font:** Aeonik (geometric sans-serif). Consumers must load it.
|
|
59
|
+
**Button height:** Compact 32px.
|
|
60
|
+
|
|
61
|
+
## Available Components
|
|
62
|
+
|
|
63
|
+
**Inputs:** Button, ButtonGroup, TextField, Select + MenuItem, MultiSelect, Checkbox, RadioGroup + Radio, Switch, ToggleButton + ToggleButtonGroup, Fab, Autocomplete, Search, DatePicker
|
|
64
|
+
|
|
65
|
+
**Data Display:** Badge, Chip, Divider, Typography, Tooltip, Table family (Table, TableHead, TableBody, TableRow, TableCell, TableContainer), DataGrid + GridColDef, List family
|
|
66
|
+
|
|
67
|
+
**Surfaces:** Accordion family, AppBar + Toolbar, Card family, Paper
|
|
68
|
+
|
|
69
|
+
**Feedback:** Alert + AlertTitle, Dialog family, Backdrop, LinearProgress, CircularProgress, Skeleton, Modal, Popover, Snackbar
|
|
70
|
+
|
|
71
|
+
**Navigation:** Breadcrumbs, Link, Menu + MenuList, Pagination, Stepper family, Tabs + Tab, SidebarNav + SidebarItem + useSidebar
|
|
72
|
+
|
|
73
|
+
**Charts:** BarChart, LineChart, PieChart, useChartColors
|
|
74
|
+
|
|
75
|
+
See `references/components.md` for full API details and `references/patterns.md` for code examples.
|
|
76
|
+
|
|
77
|
+
## Common Anti-Patterns
|
|
78
|
+
|
|
79
|
+
1. **Importing from `@mui/material`** instead of `@matteoaliano/forest-ui`
|
|
80
|
+
2. **Hardcoded color values** (`backgroundColor: "#7f56d9"`) instead of theme tokens (`backgroundColor: "primary.main"`)
|
|
81
|
+
3. **Hardcoded spacing** (`padding: "16px"`) instead of theme spacing (`p: 4`)
|
|
82
|
+
4. **Missing `<ForestProvider>`** at the app root — theme won't apply
|
|
83
|
+
5. **Using filled MUI icons** (`Close`) instead of Outlined (`CloseOutlined`)
|
|
84
|
+
6. **Building custom multi-select** instead of using the `<MultiSelect>` component
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Forest UI — Component Reference
|
|
2
|
+
|
|
3
|
+
> Full API reference for all components exported by `@matteoaliano/forest-ui`.
|
|
4
|
+
|
|
5
|
+
## Import Pattern
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
// CORRECT — import from forest-ui
|
|
9
|
+
import { Button, TextField, Alert } from "@matteoaliano/forest-ui";
|
|
10
|
+
|
|
11
|
+
// WRONG — never import from @mui/material
|
|
12
|
+
import Button from "@mui/material/Button";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
> Layout primitives (`Box`, `Stack`, `Grid`, `Container`) are NOT re-exported. Import those directly from `@mui/material`.
|
|
16
|
+
|
|
17
|
+
## Inputs
|
|
18
|
+
|
|
19
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
20
|
+
|-----------|--------|----------------------|---------------|
|
|
21
|
+
| `Button` | `import { Button } from "forest-ui"` | `variant: "contained" \| "outlined" \| "text"`, `color`, `disabled`, `startIcon`, `endIcon`, `loading`, `fullWidth`, `href` | `variant="contained"`, `size` prop removed |
|
|
22
|
+
| `ButtonGroup` | `import { ButtonGroup } from "forest-ui"` | `variant: "contained" \| "outlined" \| "text"`, `size: "small" \| "medium" \| "large"`, `orientation: "horizontal" \| "vertical"`, `color`, `disabled`, `fullWidth` | `variant="contained"` |
|
|
23
|
+
| `TextField` | `import { TextField } from "forest-ui"` | `variant: "outlined" \| "filled" \| "standard"`, `size: "small" \| "medium"`, `label`, `error`, `helperText`, `fullWidth`, `multiline`, `rows`, `type`, `placeholder`, `required`, `disabled` | — |
|
|
24
|
+
| `Select` + `MenuItem` | `import { Select, MenuItem } from "forest-ui"` | `variant: "outlined" \| "filled" \| "standard"`, `size: "small" \| "medium"`, `multiple`, `displayEmpty`, `label`, `labelId`, `renderValue`, `native`, `error`, `disabled` | — |
|
|
25
|
+
| `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"` |
|
|
26
|
+
| `Checkbox` | `import { Checkbox } from "forest-ui"` | `color: "default" \| "primary" \| "secondary" \| "error" \| "info" \| "success" \| "warning"`, `size: "small" \| "medium"`, `checked`, `indeterminate`, `disabled` | — |
|
|
27
|
+
| `RadioGroup` + `Radio` | `import { RadioGroup, Radio } from "forest-ui"` | `row`, `value`, `onChange`; Radio: `color`, `size: "small" \| "medium" \| "large"`, `disabled` | — |
|
|
28
|
+
| `Switch` | `import { Switch } from "forest-ui"` | `color: "default" \| "primary" \| "secondary" \| "error" \| "info" \| "success" \| "warning"`, `size: "small" \| "medium"`, `checked`, `disabled` | — |
|
|
29
|
+
| `ToggleButton` + `ToggleButtonGroup` | `import { ToggleButton, ToggleButtonGroup } from "forest-ui"` | `value`, `exclusive`, `onChange`, `orientation: "horizontal" \| "vertical"`, `size: "small" \| "medium" \| "large"`, `color`, `fullWidth` | — |
|
|
30
|
+
| `Fab` | `import { Fab } from "forest-ui"` | `variant: "circular" \| "extended"`, `size: "small" \| "medium" \| "large"`, `color`, `disabled`, `href` | `color="primary"` |
|
|
31
|
+
| `Autocomplete` | `import { Autocomplete } from "forest-ui"` | `options`, `renderInput` (required), `multiple`, `freeSolo`, `disableClearable`, `loading`, `groupBy`, `limitTags`, `filterOptions` | — |
|
|
32
|
+
| `Search` | `import { Search } from "forest-ui"` | `onClear`, `placeholder`, all TextField props (except `variant`) | `variant="outlined"`, `placeholder="Search..."`, built-in search icon and clear button |
|
|
33
|
+
| `DatePicker` | `import { DatePicker } from "forest-ui"` | All MUI X DatePicker props (`value`, `onChange`, `label`, `format`, `minDate`, `maxDate`, `disabled`, `readOnly`) | Wraps with `LocalizationProvider` + `AdapterDayjs` automatically |
|
|
34
|
+
|
|
35
|
+
## Data Display
|
|
36
|
+
|
|
37
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
38
|
+
|-----------|--------|----------------------|---------------|
|
|
39
|
+
| `Badge` | `import { Badge } from "forest-ui"` | `variant: "standard" \| "dot"`, `color`, `badgeContent`, `max`, `invisible`, `showZero`, `overlap: "rectangular" \| "circular"`, `anchorOrigin` | — |
|
|
40
|
+
| `Chip` | `import { Chip } from "forest-ui"` | `variant: "filled" \| "outlined"`, `color`, `size: "small" \| "medium"`, `label`, `onDelete`, `clickable`, `avatar`, `icon` | `deleteIcon={<CloseOutlined />}` |
|
|
41
|
+
| `Divider` | `import { Divider } from "forest-ui"` | `orientation: "horizontal" \| "vertical"`, `variant: "fullWidth" \| "inset" \| "middle"`, `textAlign`, `flexItem` | — |
|
|
42
|
+
| `Typography` | `import { Typography } from "forest-ui"` | `variant: "h1"-"h6" \| "subtitle1" \| "subtitle2" \| "body1" \| "body2" \| "caption" \| "overline" \| "button"`, `align`, `gutterBottom`, `noWrap` | — |
|
|
43
|
+
| `Tooltip` | `import { Tooltip } from "forest-ui"` | `title` (required), `placement` (12 positions), `arrow`, `followCursor`, `enterDelay`, `leaveDelay` | `arrow={true}` |
|
|
44
|
+
| `Table` family | `import { Table, TableHead, TableBody, TableRow, TableCell, TableContainer } from "forest-ui"` | Table: `size: "small" \| "medium"`, `stickyHeader`; TableCell: `align`, `padding`, `sortDirection`, `variant`; TableRow: `hover`, `selected` | — |
|
|
45
|
+
| `DataGrid` | `import { DataGrid, type GridColDef } from "forest-ui"` | `rows`, `columns`, `paginationModel`, `sortModel`, `filterModel`, `checkboxSelection`, `loading`, `density` | — |
|
|
46
|
+
| `List` family | `import { List, ListItem, ListItemButton, ListItemIcon, ListItemText, ListItemAvatar, ListSubheader } from "forest-ui"` | `dense`, `disablePadding`; ListItemButton: `selected`, `disabled`; ListItemText: `primary`, `secondary` | — |
|
|
47
|
+
|
|
48
|
+
## Surfaces
|
|
49
|
+
|
|
50
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
51
|
+
|-----------|--------|----------------------|---------------|
|
|
52
|
+
| `Accordion` family | `import { Accordion, AccordionSummary, AccordionDetails, AccordionActions } from "forest-ui"` | `expanded`, `defaultExpanded`, `onChange`, `disabled`, `disableGutters`, `square` | — |
|
|
53
|
+
| `AppBar` + `Toolbar` | `import { AppBar, Toolbar } from "forest-ui"` | `position`, `color`, `elevation`; Toolbar: `variant: "dense" \| "regular"` | — |
|
|
54
|
+
| `Card` family | `import { Card, CardContent, CardHeader, CardActions, CardMedia } from "forest-ui"` | `variant: "elevation" \| "outlined"`, `elevation`, `raised`; CardHeader: `title`, `subheader`, `avatar`, `action` | — |
|
|
55
|
+
| `Paper` | `import { Paper } from "forest-ui"` | `variant: "elevation" \| "outlined"`, `elevation` (0-24), `square` | — |
|
|
56
|
+
|
|
57
|
+
## Feedback
|
|
58
|
+
|
|
59
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
60
|
+
|-----------|--------|----------------------|---------------|
|
|
61
|
+
| `Alert` + `AlertTitle` | `import { Alert, AlertTitle } from "forest-ui"` | `severity: "success" \| "info" \| "warning" \| "error"`, `variant: "filled" \| "outlined" \| "standard"`, `color`, `icon`, `action`, `onClose` | — |
|
|
62
|
+
| `Dialog` family | `import { Dialog, DialogTitle, DialogContent, DialogActions, DialogContentText } from "forest-ui"` | `open` (required), `onClose`, `fullWidth`, `maxWidth`, `fullScreen`, `scroll: "paper" \| "body"` | — |
|
|
63
|
+
| `Backdrop` | `import { Backdrop } from "forest-ui"` | `open` (required), `invisible`, `onClick` | — |
|
|
64
|
+
| `LinearProgress` | `import { LinearProgress } from "forest-ui"` | `variant: "indeterminate" \| "determinate" \| "buffer" \| "query"`, `value` (0-100), `color` | — |
|
|
65
|
+
| `CircularProgress` | `import { CircularProgress } from "forest-ui"` | `variant: "indeterminate" \| "determinate"`, `value` (0-100), `color`, `size`, `thickness` | — |
|
|
66
|
+
| `Skeleton` | `import { Skeleton } from "forest-ui"` | `variant: "text" \| "circular" \| "rectangular" \| "rounded"`, `animation: "pulse" \| "wave" \| false`, `width`, `height` | — |
|
|
67
|
+
| `Modal` | `import { Modal } from "forest-ui"` | `open` (required), `onClose`, `children`, `keepMounted`, `disableAutoFocus`, `disableEscapeKeyDown` | — |
|
|
68
|
+
| `Popover` | `import { Popover } from "forest-ui"` | `open` (required), `anchorEl`, `onClose`, `anchorOrigin`, `transformOrigin`, `elevation` | — |
|
|
69
|
+
| `Snackbar` | `import { Snackbar } from "forest-ui"` | `open`, `message`, `autoHideDuration`, `onClose`, `action`, `anchorOrigin` | — |
|
|
70
|
+
|
|
71
|
+
## Navigation
|
|
72
|
+
|
|
73
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
74
|
+
|-----------|--------|----------------------|---------------|
|
|
75
|
+
| `Breadcrumbs` | `import { Breadcrumbs } from "forest-ui"` | `separator`, `maxItems`, `itemsAfterCollapse`, `itemsBeforeCollapse` | — |
|
|
76
|
+
| `Link` | `import { Link } from "forest-ui"` | `href`, `underline: "none" \| "hover" \| "always"`, `color`, `variant` | — |
|
|
77
|
+
| `Menu` + `MenuList` | `import { Menu, MenuList } from "forest-ui"` | Menu: `open` (required), `anchorEl`, `onClose`; use with `MenuItem` | — |
|
|
78
|
+
| `Pagination` | `import { Pagination } from "forest-ui"` | `count`, `page`, `onChange`, `variant: "text" \| "outlined"`, `shape`, `size`, `color`, `showFirstButton`, `showLastButton` | — |
|
|
79
|
+
| `Stepper` family | `import { Stepper, Step, StepLabel } from "forest-ui"` | `activeStep`, `orientation`, `alternativeLabel`, `nonLinear`; Step: `completed`, `disabled`; StepLabel: `optional`, `error` | — |
|
|
80
|
+
| `Tabs` + `Tab` | `import { Tabs, Tab } from "forest-ui"` | Tabs: `value`, `onChange`, `variant: "standard" \| "scrollable" \| "fullWidth"`, `orientation`, `centered`; Tab: `label`, `icon`, `iconPosition`, `disabled`, `value` | — |
|
|
81
|
+
| `SidebarNav` | `import { SidebarNav, SidebarItem, useSidebar } from "forest-ui"` | `open`, `onOpenChange`, `behavior: "permanent" \| "hover"`, `expandedWidth`, `collapsedWidth`, `showToggle`, `header`, `footer` | `expandedWidth=240`, `collapsedWidth=48`, `behavior="permanent"` |
|
|
82
|
+
| `SidebarItem` | (same import) | `icon` (required), `label` (required), `endAdornment`, `selected`, `onClick`, `disabled` | — |
|
|
83
|
+
|
|
84
|
+
## Charts
|
|
85
|
+
|
|
86
|
+
Requires `@mui/x-charts` peer dependency. Chart colors are automatically applied from the theme's 12-color series palette.
|
|
87
|
+
|
|
88
|
+
| Component | Import | Variants / Key Props | Default Props |
|
|
89
|
+
|-----------|--------|----------------------|---------------|
|
|
90
|
+
| `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 |
|
|
91
|
+
| `LineChart` | `import { LineChart } from "forest-ui"` | `series`, `colors`, `xAxis`, `yAxis`, `width`, `height` | `curve="linear"`, `strokeWidth=3`, `grid horizontal`, highlight/fade on hover |
|
|
92
|
+
| `PieChart` | `import { PieChart } from "forest-ui"` | `series` (data: `{ id, value, label, color? }[]`), `colors`, `width`, `height` | highlight/fade on hover |
|
|
93
|
+
| `useChartColors` | `import { useChartColors } from "forest-ui"` | `useChartColors(count)` — returns `string[]` of theme chart series colors (max 12) | — |
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Forest UI — Code Patterns & Anti-Patterns
|
|
2
|
+
|
|
3
|
+
## Code Patterns
|
|
4
|
+
|
|
5
|
+
### Form Layout
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { TextField, Button, Select, MenuItem, Checkbox } from "@matteoaliano/forest-ui";
|
|
9
|
+
import Box from "@mui/material/Box"; // Box, Stack, Grid are OK from MUI
|
|
10
|
+
|
|
11
|
+
function ContactForm() {
|
|
12
|
+
return (
|
|
13
|
+
<Box sx={{ display: "flex", flexDirection: "column", gap: 3 }}>
|
|
14
|
+
<TextField label="Name" fullWidth />
|
|
15
|
+
<TextField label="Email" type="email" fullWidth />
|
|
16
|
+
<Select label="Subject" fullWidth>
|
|
17
|
+
<MenuItem value="support">Support</MenuItem>
|
|
18
|
+
<MenuItem value="sales">Sales</MenuItem>
|
|
19
|
+
</Select>
|
|
20
|
+
<Button variant="contained" type="submit">
|
|
21
|
+
Send
|
|
22
|
+
</Button>
|
|
23
|
+
</Box>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### MultiSelect with Select All
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { useState } from "react";
|
|
32
|
+
import { MultiSelect } from "@matteoaliano/forest-ui";
|
|
33
|
+
|
|
34
|
+
const options = [
|
|
35
|
+
{ label: "Bug", value: "bug" },
|
|
36
|
+
{ label: "Enhancement", value: "enhancement" },
|
|
37
|
+
{ label: "New Feature", value: "feature" },
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
function CategoryFilter() {
|
|
41
|
+
const [selected, setSelected] = useState<string[]>([]);
|
|
42
|
+
return (
|
|
43
|
+
<MultiSelect
|
|
44
|
+
label="Category"
|
|
45
|
+
options={options}
|
|
46
|
+
value={selected}
|
|
47
|
+
onChange={setSelected}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Data Table
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import {
|
|
57
|
+
Table, TableContainer, TableHead, TableBody, TableRow, TableCell,
|
|
58
|
+
} from "@matteoaliano/forest-ui";
|
|
59
|
+
|
|
60
|
+
function UsersTable({ users }) {
|
|
61
|
+
return (
|
|
62
|
+
<TableContainer>
|
|
63
|
+
<Table>
|
|
64
|
+
<TableHead>
|
|
65
|
+
<TableRow>
|
|
66
|
+
<TableCell>Name</TableCell>
|
|
67
|
+
<TableCell>Email</TableCell>
|
|
68
|
+
</TableRow>
|
|
69
|
+
</TableHead>
|
|
70
|
+
<TableBody>
|
|
71
|
+
{users.map((u) => (
|
|
72
|
+
<TableRow key={u.id}>
|
|
73
|
+
<TableCell>{u.name}</TableCell>
|
|
74
|
+
<TableCell>{u.email}</TableCell>
|
|
75
|
+
</TableRow>
|
|
76
|
+
))}
|
|
77
|
+
</TableBody>
|
|
78
|
+
</Table>
|
|
79
|
+
</TableContainer>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### DataGrid
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { DataGrid, type GridColDef } from "@matteoaliano/forest-ui";
|
|
88
|
+
|
|
89
|
+
const columns: GridColDef[] = [
|
|
90
|
+
{ field: "id", headerName: "ID", width: 70 },
|
|
91
|
+
{ field: "name", headerName: "Name", flex: 1 },
|
|
92
|
+
{ field: "email", headerName: "Email", flex: 1 },
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
function UsersGrid({ rows }) {
|
|
96
|
+
return <DataGrid rows={rows} columns={columns} />;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Feedback Pattern
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { Alert, AlertTitle, Snackbar } from "@matteoaliano/forest-ui";
|
|
104
|
+
|
|
105
|
+
// Inline feedback
|
|
106
|
+
<Alert severity="error">
|
|
107
|
+
<AlertTitle>Error</AlertTitle>
|
|
108
|
+
Something went wrong.
|
|
109
|
+
</Alert>
|
|
110
|
+
|
|
111
|
+
// Toast notification
|
|
112
|
+
<Snackbar open={open} autoHideDuration={4000} onClose={handleClose}>
|
|
113
|
+
<Alert severity="success" variant="filled">Saved!</Alert>
|
|
114
|
+
</Snackbar>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Confirmation Dialog
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import { Dialog, DialogTitle, DialogContent, DialogActions, DialogContentText, Button } from "@matteoaliano/forest-ui";
|
|
121
|
+
|
|
122
|
+
function ConfirmDialog({ open, onClose, onConfirm }) {
|
|
123
|
+
return (
|
|
124
|
+
<Dialog open={open} onClose={onClose}>
|
|
125
|
+
<DialogTitle>Confirm</DialogTitle>
|
|
126
|
+
<DialogContent>
|
|
127
|
+
<DialogContentText>Are you sure?</DialogContentText>
|
|
128
|
+
</DialogContent>
|
|
129
|
+
<DialogActions>
|
|
130
|
+
<Button variant="outlined" onClick={onClose}>Cancel</Button>
|
|
131
|
+
<Button onClick={onConfirm}>Confirm</Button>
|
|
132
|
+
</DialogActions>
|
|
133
|
+
</Dialog>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Sidebar Navigation
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
import { SidebarNav, SidebarItem } from "@matteoaliano/forest-ui";
|
|
142
|
+
import DashboardOutlined from "@mui/icons-material/DashboardOutlined";
|
|
143
|
+
import SettingsOutlined from "@mui/icons-material/SettingsOutlined";
|
|
144
|
+
|
|
145
|
+
function AppShell() {
|
|
146
|
+
const [open, setOpen] = useState(true);
|
|
147
|
+
return (
|
|
148
|
+
<SidebarNav open={open} onOpenChange={setOpen}>
|
|
149
|
+
<SidebarItem icon={<DashboardOutlined />} label="Dashboard" selected />
|
|
150
|
+
<SidebarItem icon={<SettingsOutlined />} label="Settings" />
|
|
151
|
+
</SidebarNav>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Charts
|
|
157
|
+
|
|
158
|
+
Colors are automatically assigned from the theme's 12-series palette. Override with the `colors` prop if needed.
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
import { BarChart, LineChart, PieChart, useChartColors } from "@matteoaliano/forest-ui";
|
|
162
|
+
|
|
163
|
+
// Bar chart with striped variant
|
|
164
|
+
<BarChart
|
|
165
|
+
series={[
|
|
166
|
+
{ data: [10, 20, 30], label: "Current", variant: "solid" },
|
|
167
|
+
{ data: [8, 15, 25], label: "Previous", variant: "striped" },
|
|
168
|
+
]}
|
|
169
|
+
xAxis={[{ data: ["Jan", "Feb", "Mar"], scaleType: "band" }]}
|
|
170
|
+
height={300}
|
|
171
|
+
/>
|
|
172
|
+
|
|
173
|
+
// Line chart
|
|
174
|
+
<LineChart
|
|
175
|
+
series={[{ data: [10, 20, 30], label: "Revenue" }]}
|
|
176
|
+
xAxis={[{ data: ["Jan", "Feb", "Mar"], scaleType: "band" }]}
|
|
177
|
+
height={300}
|
|
178
|
+
/>
|
|
179
|
+
|
|
180
|
+
// Pie chart
|
|
181
|
+
<PieChart
|
|
182
|
+
series={[{ data: [
|
|
183
|
+
{ id: 0, value: 40, label: "Desktop" },
|
|
184
|
+
{ id: 1, value: 30, label: "Mobile" },
|
|
185
|
+
{ id: 2, value: 30, label: "Tablet" },
|
|
186
|
+
]}]}
|
|
187
|
+
height={300}
|
|
188
|
+
/>
|
|
189
|
+
|
|
190
|
+
// Access chart colors programmatically
|
|
191
|
+
const colors = useChartColors(3);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Storybook Controls
|
|
195
|
+
|
|
196
|
+
When adding argTypes to stories:
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
const meta: Meta<typeof Button> = {
|
|
200
|
+
component: Button,
|
|
201
|
+
argTypes: {
|
|
202
|
+
variant: {
|
|
203
|
+
control: "select",
|
|
204
|
+
options: ["contained", "outlined", "text"],
|
|
205
|
+
},
|
|
206
|
+
color: {
|
|
207
|
+
control: "select",
|
|
208
|
+
options: ["primary", "secondary", "error", "warning", "success", "info"],
|
|
209
|
+
},
|
|
210
|
+
disabled: { control: "boolean" },
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Control types:** `"select"` with `options`, `"boolean"`, `"number"`, `"text"`.
|
|
216
|
+
|
|
217
|
+
## Anti-Patterns
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
// WRONG: importing from @mui/material
|
|
221
|
+
import Button from "@mui/material/Button";
|
|
222
|
+
|
|
223
|
+
// WRONG: hardcoded colors
|
|
224
|
+
<Box sx={{ backgroundColor: "#7f56d9" }} />
|
|
225
|
+
|
|
226
|
+
// WRONG: hardcoded spacing
|
|
227
|
+
<Box sx={{ padding: "16px" }} />
|
|
228
|
+
|
|
229
|
+
// WRONG: forgetting ForestProvider
|
|
230
|
+
ReactDOM.render(<App />, root); // theme won't apply
|
|
231
|
+
|
|
232
|
+
// WRONG: using filled (default) icons
|
|
233
|
+
import CloseIcon from "@mui/icons-material/Close";
|
|
234
|
+
|
|
235
|
+
// CORRECT: always use Outlined variant
|
|
236
|
+
import CloseIcon from "@mui/icons-material/CloseOutlined";
|
|
237
|
+
|
|
238
|
+
// CORRECT: use theme tokens
|
|
239
|
+
<Box sx={{ backgroundColor: "primary.main", p: 4 }} />
|
|
240
|
+
|
|
241
|
+
// WRONG: manually building multi-select with Select + Checkbox
|
|
242
|
+
// CORRECT: use the MultiSelect component
|
|
243
|
+
<MultiSelect options={options} value={value} onChange={setValue} />
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## TypeScript Props
|
|
247
|
+
|
|
248
|
+
Every component exports its props type:
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
import { Button, type ButtonProps } from "@matteoaliano/forest-ui";
|
|
252
|
+
|
|
253
|
+
interface MyButtonProps extends ButtonProps {
|
|
254
|
+
analyticsId: string;
|
|
255
|
+
}
|
|
256
|
+
```
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: forest-external
|
|
3
|
+
description: Forest UI Design System rules for the External (violet) preset. Enforces correct imports, component usage, and theming with @matteoaliano/forest-ui. Use when the project uses forest-ui, forest-external preset, or when user builds UI components in a forest-ui project. Triggers on "forest", "forest-ui", "forest external", "@matteoaliano/forest-ui".
|
|
4
|
+
metadata:
|
|
5
|
+
author: Forest Design System
|
|
6
|
+
version: 0.3.4
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Forest UI — External Preset
|
|
10
|
+
|
|
11
|
+
## Golden Rules
|
|
12
|
+
|
|
13
|
+
1. **NEVER import from `@mui/material` directly.** Always import from `@matteoaliano/forest-ui`. Exception: layout primitives (`Box`, `Stack`, `Grid`, `Container`) come from `@mui/material`.
|
|
14
|
+
2. **ALWAYS wrap your app root with `<ForestProvider>`** — it applies the theme and CSS baseline.
|
|
15
|
+
3. **NEVER use inline colors or spacing values.** Use design tokens or MUI's `sx` prop with theme values (`p: 4`, `backgroundColor: "primary.main"`).
|
|
16
|
+
4. **NEVER create custom component wrappers** for things Forest UI already provides.
|
|
17
|
+
5. **TypeScript is required.** All components export their prop types (e.g. `type ButtonProps`).
|
|
18
|
+
6. **ALWAYS use the Outlined variant of MUI icons.** Import from `@mui/icons-material/*Outlined` (e.g. `CloseOutlined`, `MailOutlined`). Never use filled, Rounded, Sharp, or TwoTone variants.
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @matteoaliano/forest-ui @mui/material @mui/x-data-grid @mui/x-date-pickers @mui/x-charts dayjs @emotion/react @emotion/styled
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { ForestProvider } from "@matteoaliano/forest-ui";
|
|
28
|
+
|
|
29
|
+
function App() {
|
|
30
|
+
return (
|
|
31
|
+
<ForestProvider preset="forest-external">
|
|
32
|
+
{/* All app content here */}
|
|
33
|
+
</ForestProvider>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Preset Identity
|
|
39
|
+
|
|
40
|
+
**Atmosphere:** Vibrant, creative, and confidently modern — electric yet composed.
|
|
41
|
+
|
|
42
|
+
| Role | Color | Hex |
|
|
43
|
+
|------|-------|-----|
|
|
44
|
+
| Primary (brand) | Electric Violet | `#9D5FFF` |
|
|
45
|
+
| Primary hover | Deep Amethyst | `#7c4de6` |
|
|
46
|
+
| Brand depth | Royal Violet | `#5b3acc` |
|
|
47
|
+
| Brand tint | Soft Lavender | `#f5f0ff` |
|
|
48
|
+
| Background | Warm Parchment | `#faf9f8` |
|
|
49
|
+
| Surface | Pure White | `#ffffff` |
|
|
50
|
+
| Text primary | Near-Black Ink | `#18181b` |
|
|
51
|
+
| Text secondary | Steel Gray | `#3f3f46` |
|
|
52
|
+
| Border primary | Silver Mist | `#d8d8dc` |
|
|
53
|
+
| Border brand | Violet Frost | `#b090ff` |
|
|
54
|
+
| Success | Verdant | `#079455` |
|
|
55
|
+
| Warning | Amber | `#dc6803` |
|
|
56
|
+
| Error | Coral | `#d92d20` |
|
|
57
|
+
| Info | Sky | `#1570ef` |
|
|
58
|
+
|
|
59
|
+
**Corner radius:** Sharp and contemporary (4px for buttons/inputs, up to 12px for cards/modals).
|
|
60
|
+
**Font:** Aeonik (geometric sans-serif). Consumers must load it.
|
|
61
|
+
**Button height:** Compact 32px.
|
|
62
|
+
|
|
63
|
+
## Available Components
|
|
64
|
+
|
|
65
|
+
**Inputs:** Button, ButtonGroup, TextField, Select + MenuItem, MultiSelect, Checkbox, RadioGroup + Radio, Switch, ToggleButton + ToggleButtonGroup, Fab, Autocomplete, Search, DatePicker
|
|
66
|
+
|
|
67
|
+
**Data Display:** Badge, Chip, Divider, Typography, Tooltip, Table family (Table, TableHead, TableBody, TableRow, TableCell, TableContainer), DataGrid + GridColDef, List family
|
|
68
|
+
|
|
69
|
+
**Surfaces:** Accordion family, AppBar + Toolbar, Card family, Paper
|
|
70
|
+
|
|
71
|
+
**Feedback:** Alert + AlertTitle, Dialog family, Backdrop, LinearProgress, CircularProgress, Skeleton, Modal, Popover, Snackbar
|
|
72
|
+
|
|
73
|
+
**Navigation:** Breadcrumbs, Link, Menu + MenuList, Pagination, Stepper family, Tabs + Tab, SidebarNav + SidebarItem + useSidebar
|
|
74
|
+
|
|
75
|
+
**Charts:** BarChart, LineChart, PieChart, useChartColors
|
|
76
|
+
|
|
77
|
+
See `references/components.md` for full API details and `references/patterns.md` for code examples.
|
|
78
|
+
|
|
79
|
+
## Common Anti-Patterns
|
|
80
|
+
|
|
81
|
+
1. **Importing from `@mui/material`** instead of `@matteoaliano/forest-ui`
|
|
82
|
+
2. **Hardcoded color values** (`backgroundColor: "#7f56d9"`) instead of theme tokens (`backgroundColor: "primary.main"`)
|
|
83
|
+
3. **Hardcoded spacing** (`padding: "16px"`) instead of theme spacing (`p: 4`)
|
|
84
|
+
4. **Missing `<ForestProvider>`** at the app root — theme won't apply
|
|
85
|
+
5. **Using filled MUI icons** (`Close`) instead of Outlined (`CloseOutlined`)
|
|
86
|
+
6. **Building custom multi-select** instead of using the `<MultiSelect>` component
|