7.2 KiB
7.2 KiB
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 20, 2026
Version: 1.8.4
Quick Links
| Resource | Path | Description |
|---|---|---|
| Component System | COMPONENT-SYSTEM.md | Full component reference with props, examples, and usage |
| Design Tokens Doc | 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:
/* ✅ 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
// ✅ 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
// ❌ 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
// ❌ NEVER
import { XIcon } from '@heroicons/react/24/outline';
import { Trash } from 'lucide-react';
// ✅ ALWAYS
import { CloseIcon, TrashBinIcon } from '../../icons';
3. Consistent Sizing
// 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 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
# 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:
- Read first: docs/30-FRONTEND/COMPONENT-SYSTEM.md
- Never use:
<button>,<input>,<select>,<textarea>tags - Import icons from:
src/iconsonly - Verify after changes:
npm run lint - Reference pages: Planner and Writer modules use correct patterns
Correct Import Paths
// 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>withButtonorIconButton - Replace
<input type="text/email/password/number">withInputField - Replace
<input type="checkbox">withCheckbox - Replace
<input type="radio">withRadio - Replace
<select>withSelectorSelectDropdown - Replace
<textarea>withTextArea - Replace external icon imports with
src/icons - Run
npm run lintto verify - Run
npm run buildto confirm no errors