184 lines
5.4 KiB
Markdown
184 lines
5.4 KiB
Markdown
# IGNY8 Design System Guide
|
|
|
|
> **Single Source of Truth for UI Components**
|
|
>
|
|
> This guide ensures consistent, maintainable frontend code across the entire application.
|
|
|
|
---
|
|
|
|
## Quick Links
|
|
|
|
| Resource | Path | Description |
|
|
|----------|------|-------------|
|
|
| **Component System** | [docs/30-FRONTEND/COMPONENT-SYSTEM.md](docs/30-FRONTEND/COMPONENT-SYSTEM.md) | Full component reference with props, examples, and usage |
|
|
| **ESLint Plugin** | [frontend/eslint/](frontend/eslint/) | Custom rules enforcing design system |
|
|
| **Live Demo** | `/ui-elements` route | Interactive component showcase |
|
|
| **Design Tokens** | [frontend/src/styles/design-system.css](frontend/src/styles/design-system.css) | CSS variables and tokens |
|
|
| **Icons** | [frontend/src/icons/](frontend/src/icons/) | All SVG icons |
|
|
|
|
---
|
|
|
|
## Core Principles
|
|
|
|
### 1. Use Components, Never Raw HTML
|
|
|
|
```tsx
|
|
// ❌ NEVER
|
|
<button className="...">Click</button>
|
|
<input type="text" className="..." />
|
|
<select className="...">...</select>
|
|
<textarea className="..."></textarea>
|
|
|
|
// ✅ ALWAYS
|
|
<Button variant="primary">Click</Button>
|
|
<InputField type="text" label="Name" />
|
|
<Select options={options} />
|
|
<TextArea rows={4} />
|
|
```
|
|
|
|
### 2. Import Icons from Central Location
|
|
|
|
```tsx
|
|
// ❌ NEVER
|
|
import { XIcon } from '@heroicons/react/24/outline';
|
|
import { Trash } from 'lucide-react';
|
|
|
|
// ✅ ALWAYS
|
|
import { CloseIcon, TrashBinIcon } from '../../icons';
|
|
```
|
|
|
|
### 3. Consistent Sizing
|
|
|
|
```tsx
|
|
// Icons in buttons/badges
|
|
<Icon className="w-4 h-4" />
|
|
|
|
// Standalone icons
|
|
<Icon className="w-5 h-5" />
|
|
|
|
// Large/header icons
|
|
<Icon className="w-6 h-6" />
|
|
```
|
|
|
|
---
|
|
|
|
## Component Quick Reference
|
|
|
|
| Need | Component | Import |
|
|
|------|-----------|--------|
|
|
| Action button | `Button` | `components/ui/button/Button` |
|
|
| Icon-only button | `IconButton` | `components/ui/button/IconButton` |
|
|
| Text input | `InputField` | `components/form/input/InputField` |
|
|
| Checkbox | `Checkbox` | `components/form/input/Checkbox` |
|
|
| Radio | `Radio` | `components/form/input/Radio` |
|
|
| Dropdown | `Select` | `components/form/Select` |
|
|
| Multi-line text | `TextArea` | `components/form/input/TextArea` |
|
|
| Toggle | `Switch` | `components/form/switch/Switch` |
|
|
| Status label | `Badge` | `components/ui/badge/Badge` |
|
|
| Container | `Card` | `components/ui/card/Card` |
|
|
| Popup | `Modal` | `components/ui/modal` |
|
|
| Loading | `Spinner` | `components/ui/spinner/Spinner` |
|
|
| Notification | `useToast` | `components/ui/toast/ToastContainer` |
|
|
|
|
**→ See [COMPONENT-SYSTEM.md](docs/30-FRONTEND/COMPONENT-SYSTEM.md) for full props and examples**
|
|
|
|
---
|
|
|
|
## ESLint Enforcement
|
|
|
|
### Rules
|
|
|
|
| Rule | Level | Action |
|
|
|------|-------|--------|
|
|
| `no-raw-button` | warn → error | Use `Button` or `IconButton` |
|
|
| `no-raw-input` | warn → error | Use `InputField`, `Checkbox`, `Radio` |
|
|
| `no-raw-select` | warn → error | Use `Select` or `SelectDropdown` |
|
|
| `no-raw-textarea` | warn → error | Use `TextArea` |
|
|
| `no-restricted-imports` | error | Block external icon libraries |
|
|
|
|
### Check Violations
|
|
|
|
```bash
|
|
cd frontend
|
|
npm run lint
|
|
```
|
|
|
|
### Plugin Location
|
|
|
|
The custom ESLint plugin is at: `frontend/eslint/eslint-plugin-igny8-design-system.cjs`
|
|
|
|
---
|
|
|
|
## For AI Agents
|
|
|
|
When working on this codebase:
|
|
|
|
1. **Read first**: [docs/30-FRONTEND/COMPONENT-SYSTEM.md](docs/30-FRONTEND/COMPONENT-SYSTEM.md)
|
|
2. **Never use**: `<button>`, `<input>`, `<select>`, `<textarea>` tags
|
|
3. **Import icons from**: `src/icons` only
|
|
4. **Verify after changes**: `npm run lint`
|
|
5. **Reference pages**: Planner and Writer modules use correct patterns
|
|
|
|
### Correct Import Paths
|
|
|
|
```tsx
|
|
// From a page in src/pages/
|
|
import Button from '../components/ui/button/Button';
|
|
import IconButton from '../components/ui/button/IconButton';
|
|
import InputField from '../components/form/input/InputField';
|
|
import { PlusIcon, CloseIcon } from '../icons';
|
|
|
|
// From a component in src/components/
|
|
import Button from '../../components/ui/button/Button';
|
|
import { PlusIcon } from '../../icons';
|
|
|
|
// From a nested component
|
|
// Adjust ../ based on depth
|
|
```
|
|
|
|
---
|
|
|
|
## File Structure
|
|
|
|
```
|
|
frontend/
|
|
├── eslint/
|
|
│ └── eslint-plugin-igny8-design-system.cjs # Custom rules
|
|
├── src/
|
|
│ ├── components/
|
|
│ │ ├── ui/ # Display components
|
|
│ │ │ ├── button/ # Button, IconButton
|
|
│ │ │ ├── badge/ # Badge
|
|
│ │ │ ├── card/ # Card
|
|
│ │ │ ├── modal/ # Modal
|
|
│ │ │ └── ...
|
|
│ │ └── form/ # Form components
|
|
│ │ ├── input/ # InputField, Checkbox, Radio, TextArea
|
|
│ │ ├── switch/ # Switch
|
|
│ │ ├── Select.tsx
|
|
│ │ └── ...
|
|
│ ├── icons/ # All SVG icons
|
|
│ │ └── index.ts # Export all icons
|
|
│ └── styles/
|
|
│ └── design-system.css # Design tokens
|
|
docs/
|
|
└── 30-FRONTEND/
|
|
└── COMPONENT-SYSTEM.md # Full component documentation
|
|
```
|
|
|
|
---
|
|
|
|
## Migration Checklist
|
|
|
|
When fixing violations:
|
|
|
|
- [ ] Replace `<button>` with `Button` or `IconButton`
|
|
- [ ] Replace `<input type="text/email/password/number">` with `InputField`
|
|
- [ ] Replace `<input type="checkbox">` with `Checkbox`
|
|
- [ ] Replace `<input type="radio">` with `Radio`
|
|
- [ ] Replace `<select>` with `Select` or `SelectDropdown`
|
|
- [ ] Replace `<textarea>` with `TextArea`
|
|
- [ ] Replace external icon imports with `src/icons`
|
|
- [ ] Run `npm run lint` to verify
|
|
- [ ] Run `npm run build` to confirm no errors
|