# IGNY8 Design System Guide

> **Single Source of Truth for UI Components**
> 
> 🔒 **STYLE LOCKED** - This design system is enforced by ESLint. All frontend code must comply.

**Last Updated:** January 3, 2026  
**Version:** 1.3.2

---

## Quick Links

| Resource | Path | Description |
|----------|------|-------------|
| **Component System** | [COMPONENT-SYSTEM.md](COMPONENT-SYSTEM.md) | Full component reference with props, examples, and usage |
| **Design Tokens Doc** | [DESIGN-TOKENS.md](DESIGN-TOKENS.md) | Detailed token documentation |
| **ESLint Plugin** | `frontend/eslint/` | Custom rules enforcing design system |
| **Live Demo** | `/ui-elements` route | Interactive component showcase |
| **CSS Tokens** | `frontend/src/styles/design-system.css` | CSS variables source file |
| **Icons** | `frontend/src/icons/` | All SVG icons |

---

## 🎨 Color System (CRITICAL!)

### Only 6 Base Colors in Entire System

All colors derive from 6 primary hex values defined in `design-system.css`:

| Token | Hex | Purpose |
|-------|-----|---------|
| `--color-primary` | #0077B6 | Brand Blue - main CTA, links |
| `--color-success` | #2CA18E | Success Green - confirmations |
| `--color-warning` | #D9A12C | Warning Amber - alerts |
| `--color-danger` | #A12C40 | Danger Red - errors, destructive |
| `--color-purple` | #2C40A1 | Purple - premium features |
| `--color-gray-base` | #667085 | Neutral gray - text, borders |

### Tailwind Color Utilities

**⚠️ Tailwind default colors are DISABLED!** Only use:

```css
/* ✅ AVAILABLE */
brand-50 through brand-950    /* Primary blue scale */
gray-25 through gray-950      /* Neutral scale */
success-25 through success-950 /* Green scale */
error-25 through error-950     /* Red scale */
warning-25 through warning-950 /* Amber scale */
purple-25 through purple-950   /* Purple scale */

/* ❌ DISABLED - These will NOT work */
blue-*, red-*, green-*, emerald-*, amber-*, indigo-*, 
pink-*, rose-*, sky-*, teal-*, cyan-*, etc.
```

### Usage Examples

```tsx
// ✅ CORRECT
<div className="bg-brand-500 text-white">Primary Button</div>
<div className="text-gray-700 bg-gray-50">Card content</div>
<Badge tone="success">Active</Badge>
<Alert variant="error" message="Failed" />

// ❌ WRONG
<div className="bg-blue-500">...</div>     // Default blue disabled
<div className="bg-[#0693e3]">...</div>   // Hardcoded hex
<div style={{ color: '#ff0000' }}>...</div> // Inline style
```

---

## 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 | Use `Button` or `IconButton` |
| `no-raw-input` | warn | Use `InputField`, `Checkbox`, `Radio` |
| `no-raw-select` | warn | Use `Select` or `SelectDropdown` |
| `no-raw-textarea` | warn | Use `TextArea` |
| `no-icon-children` | warn | Use `startIcon`/`endIcon` props instead of icon children |
| `no-restricted-imports` | error | Block `@heroicons/*`, `lucide-react`, `@mui/icons-material` |

### Check Violations

```bash
# Inside container
docker exec -it igny8_frontend npm run lint

# Or directly
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
