|
| 1 | +# Design System Agent Instructions |
| 2 | + |
| 3 | +**CRITICAL**: These instructions are MANDATORY for all UI/frontend work. Follow exactly as written. |
| 4 | + |
| 5 | +## Pre-Work Checklist |
| 6 | + |
| 7 | +Before ANY UI/component work: |
| 8 | + |
| 9 | +1. **Check MCP availability (recommended)**: |
| 10 | + - Search for `mcp__storybook__*` tools |
| 11 | + - Search for `mcp__figma__*` tools |
| 12 | + - If available: Use them to get design context and component examples |
| 13 | + - If missing: Continue with pattern discovery via code exploration |
| 14 | + |
| 15 | +2. **Load design context** (if MCPs available): |
| 16 | + ``` |
| 17 | + Call: mcp__storybook__get-ui-building-instructions |
| 18 | + Call: mcp__figma__get_design_context (if working from designs) |
| 19 | + ``` |
| 20 | + |
| 21 | +3. **Read existing patterns**: |
| 22 | + - The Storybook MCP provides component examples and usage patterns |
| 23 | + - Find similar widgets/components in the project: `src/web/src/**/*{keyword}*.{tsx,ts}` |
| 24 | + - Use Grep to find token usage patterns: `theme\.color\.|theme\.space\.|theme\.radius\.` |
| 25 | + - Read 1-2 similar components in the project to understand patterns |
| 26 | + - DO NOT read more than 3 files for context |
| 27 | + |
| 28 | +## Strict Rules (Zero Tolerance) |
| 29 | + |
| 30 | +### 1. Design Tokens ONLY |
| 31 | +**NEVER** hardcode values. Use `theme.*` exclusively: |
| 32 | + |
| 33 | +```typescript |
| 34 | +// ❌ FORBIDDEN |
| 35 | +color: '#1976d2' |
| 36 | +padding: '8px' |
| 37 | +border-radius: '4px' |
| 38 | +font-size: '14px' |
| 39 | + |
| 40 | +// ✅ REQUIRED |
| 41 | +color: ${theme.color.primary.action} |
| 42 | +padding: ${theme.space.space8} |
| 43 | +border-radius: ${theme.radius.radius8} |
| 44 | +// For typography, prefer using <Text> or <Heading> components |
| 45 | +``` |
| 46 | + |
| 47 | +**Token Reference** (understand the patterns): |
| 48 | +- Colors: `theme.color.{category}.{property}` |
| 49 | + - Example categories: `neutral`, `primary`, `primaryBlack`, `success`, `warning`, `danger` |
| 50 | + - Example properties: `text`, `textMuted`, `background`, `backgroundSubtle`, `action`, `actionHover`, `border`, `icon`, etc. |
| 51 | +- Spacing: `theme.space.space{N}` |
| 52 | + - Examples: `space8`, `space16`, `space24` (incremental values available) |
| 53 | +- Radius: `theme.radius.radius{N}` |
| 54 | + - Examples: `radius4`, `radius6`, `radius8`, `radius12`, `radiusFull` |
| 55 | +- Shadows: `theme.shadow.{name}` |
| 56 | + - Examples: `shadow1`, `shadow2`, `shadow3`, `shadowActive` |
| 57 | + |
| 58 | +**To discover available tokens**: Use Storybook MCP or Grep existing usage in `src/web/src` |
| 59 | + |
| 60 | +### 2. Component Imports |
| 61 | +```typescript |
| 62 | +// ✅ Import from ui-library |
| 63 | +import { Button, Badge, Chip } from '@apify/ui-library'; |
| 64 | + |
| 65 | +// ❌ NEVER create duplicate components |
| 66 | +// ❌ NEVER import from relative paths outside ui-library |
| 67 | +``` |
| 68 | + |
| 69 | +### 3. Styled Components Pattern |
| 70 | +```typescript |
| 71 | +import styled from 'styled-components'; |
| 72 | +import { theme } from '@apify/ui-library'; |
| 73 | + |
| 74 | +// ✅ Correct pattern |
| 75 | +const StyledComponent = styled.div<{ $variant?: string }>` |
| 76 | + color: ${theme.color.neutral.text}; |
| 77 | + padding: ${theme.space.space16}; |
| 78 | +
|
| 79 | + ${({ $variant }) => $variant === 'primary' && css` |
| 80 | + background: ${theme.color.primary.background}; |
| 81 | + `} |
| 82 | +`; |
| 83 | + |
| 84 | +// Note: Use $ prefix for transient props ($variant, $isActive, etc.) |
| 85 | +``` |
| 86 | + |
| 87 | +### 4. Component Structure (Strict Order) |
| 88 | +```typescript |
| 89 | +// 1. Imports (grouped) |
| 90 | +import { forwardRef } from 'react'; |
| 91 | +import styled from 'styled-components'; |
| 92 | +import { theme } from '@apify/ui-library'; |
| 93 | + |
| 94 | +// 2. Constants & Types |
| 95 | +export const COMPONENT_VARIANTS = { ... } as const; |
| 96 | +type ComponentVariants = ValueOf<typeof COMPONENT_VARIANTS>; |
| 97 | + |
| 98 | +// 3. Styled Components |
| 99 | +const StyledWrapper = styled.div`...`; |
| 100 | + |
| 101 | +// 4. Component Implementation |
| 102 | +export const Component = forwardRef<HTMLElement, Props>((props, ref) => { |
| 103 | + // implementation |
| 104 | +}); |
| 105 | + |
| 106 | +// 5. Display Name |
| 107 | +Component.displayName = 'Component'; |
| 108 | +``` |
| 109 | + |
| 110 | +### 5. Color Usage Rules |
| 111 | + |
| 112 | +**Semantic Naming Required**: |
| 113 | +- Text: `theme.color.{category}.text`, `.textMuted`, `.textSubtle`, `.textDisabled` |
| 114 | +- Backgrounds: `theme.color.{category}.background`, `.backgroundSubtle`, `.backgroundMuted` |
| 115 | +- Interactive: `theme.color.{category}.action`, `.actionHover`, `.actionActive` |
| 116 | +- Borders: `theme.color.{category}.border`, `.separatorSubtle`, `.fieldBorder` |
| 117 | +- Icons: `theme.color.{category}.icon`, `.iconSubtle`, `.iconDisabled` |
| 118 | + |
| 119 | +**State Variants**: |
| 120 | +```typescript |
| 121 | +// Default → Hover → Active states |
| 122 | +background: ${theme.color.primary.action}; |
| 123 | +&:hover { background: ${theme.color.primary.actionHover}; } |
| 124 | +&:active { background: ${theme.color.primary.actionActive}; } |
| 125 | +``` |
| 126 | + |
| 127 | +### 6. Spacing Rules |
| 128 | +- Gaps between elements: `space4`, `space8`, `space12` |
| 129 | +- Component padding: `space8`, `space12`, `space16` |
| 130 | +- Section margins: `space16`, `space24`, `space32` |
| 131 | +- Large layouts: `space40`, `space64`, `space80` |
| 132 | + |
| 133 | +**NEVER** use arbitrary values like `gap: 10px` - round to nearest token. |
| 134 | + |
| 135 | +### 7. Typography Rules |
| 136 | +```typescript |
| 137 | +// ✅ Use Text or Heading components from ui-library |
| 138 | +import { Text, Heading } from '@apify/ui-library'; |
| 139 | + |
| 140 | +// Text component props: type, size, weight |
| 141 | +<Text type="body" size="regular" weight="normal">Content here</Text> |
| 142 | + |
| 143 | +// Heading component props: type |
| 144 | +<Heading type="titleL">Title here</Heading> |
| 145 | + |
| 146 | +// ❌ NEVER use typography tokens directly |
| 147 | +// ❌ NEVER hardcode font properties |
| 148 | +``` |
| 149 | + |
| 150 | +## Verification Protocol (Before Submitting) |
| 151 | + |
| 152 | +Run this mental checklist: |
| 153 | + |
| 154 | +1. **Token Audit**: Search your code for: |
| 155 | + - Regex: `['"]#[0-9a-fA-F]{3,8}['"]` → Should be ZERO matches |
| 156 | + - Regex: `['"][0-9]+px['"]` → Should be ZERO matches (except in exceptional cases) |
| 157 | + - All `color:`, `background:`, `padding:`, `margin:`, `gap:` use `theme.*` |
| 158 | + |
| 159 | +2. **Import Check**: |
| 160 | + - All styled-components import `theme` from `@apify/ui-library` |
| 161 | + - No duplicate component implementations |
| 162 | + |
| 163 | +3. **Pattern Match**: |
| 164 | + - Compare your component structure to similar existing components |
| 165 | + - Follow same prop naming conventions |
| 166 | + - Use same variant patterns |
| 167 | + |
| 168 | +## Common Pitfalls (Avoid These) |
| 169 | + |
| 170 | +1. **❌ Mixing hardcoded and token values** |
| 171 | + ```typescript |
| 172 | + // ❌ WRONG |
| 173 | + padding: ${theme.space.space16} 10px; |
| 174 | + |
| 175 | + // ✅ CORRECT |
| 176 | + padding: ${theme.space.space16} ${theme.space.space10}; |
| 177 | + ``` |
| 178 | + |
| 179 | +2. **❌ Using non-existent color properties** |
| 180 | + ```typescript |
| 181 | + // ❌ WRONG |
| 182 | + theme.color.neutral.textLight // doesn't exist |
| 183 | + theme.color.primary.main // doesn't exist |
| 184 | + |
| 185 | + // ✅ CORRECT |
| 186 | + theme.color.neutral.textMuted // use actual property names |
| 187 | + theme.color.primary.action // use actual property names |
| 188 | + ``` |
| 189 | + |
| 190 | +3. **❌ Not using available MCPs** |
| 191 | + - If Storybook or Figma MCPs are available, use them |
| 192 | + - They provide valuable context and patterns |
| 193 | + |
| 194 | +4. **❌ Over-reading for context** |
| 195 | + - Read max 3 similar components |
| 196 | + - Don't read entire directories |
| 197 | + - Use Grep to find specific patterns |
| 198 | + |
| 199 | +## Figma Integration Workflow |
| 200 | + |
| 201 | +When user provides Figma design: |
| 202 | + |
| 203 | +1. **Get design context**: |
| 204 | + ``` |
| 205 | + mcp__figma__get_design_context (with Figma URL) |
| 206 | + ``` |
| 207 | + |
| 208 | +2. **Extract design tokens**: |
| 209 | + - Colors → Map to `theme.color.*` |
| 210 | + - Spacing → Map to `theme.space.*` |
| 211 | + |
| 212 | +3. **Get screenshots if needed**: |
| 213 | + ``` |
| 214 | + mcp__figma__get_screenshot (for visual reference) |
| 215 | + ``` |
| 216 | + |
| 217 | +4. **Verify variable mappings**: |
| 218 | + ``` |
| 219 | + mcp__figma__get_variable_defs (to see Figma variables) |
| 220 | + ``` |
| 221 | + |
| 222 | +## Quick Reference Card |
| 223 | + |
| 224 | +| Property | Token Pattern | Example | |
| 225 | +|----------|---------------|---------| |
| 226 | +| Text color | `theme.color.{cat}.{prop}` | `theme.color.neutral.text` | |
| 227 | +| Background | `theme.color.{cat}.{prop}` | `theme.color.primary.background` | |
| 228 | +| Padding/Margin | `theme.space.space{N}` | `theme.space.space16` | |
| 229 | +| Gap | `theme.space.space{N}` | `theme.space.space8` | |
| 230 | +| Border radius | `theme.radius.radius{N}` | `theme.radius.radius8` | |
| 231 | +| Shadow | `theme.shadow.{name}` | `theme.shadow.shadow2` | |
| 232 | +| Typography | `<Text>` or `<Heading>` components | `<Text type="body" size="regular">` | |
| 233 | + |
| 234 | +**Note**: Use Storybook MCP or Grep (`src/web/src`) to discover all available token values. |
| 235 | + |
| 236 | +## Error Recovery |
| 237 | + |
| 238 | +If you realize you used hardcoded values: |
| 239 | + |
| 240 | +1. Immediately stop |
| 241 | +2. List all violations |
| 242 | +3. Fix ALL violations before proceeding |
| 243 | +4. Re-verify using audit checklist |
| 244 | + |
| 245 | +## Summary: The Non-Negotiables |
| 246 | + |
| 247 | +1. ✅ Check MCP availability and use if available (recommended) |
| 248 | +2. ✅ Use `theme.*` tokens for ALL styling values (colors, spacing, radius, shadows) |
| 249 | +3. ✅ Use `<Text>` and `<Heading>` components for typography (not tokens) |
| 250 | +4. ✅ Import components from `@apify/ui-library` |
| 251 | +5. ✅ Follow existing component patterns (read 1-3 examples) |
| 252 | +6. ✅ Use semantic color naming (category.property) |
| 253 | +7. ✅ Verify zero hardcoded values before submitting |
| 254 | +8. ❌ NEVER hardcode colors (#hex or rgb) |
| 255 | +9. ❌ NEVER hardcode spacing (Npx values) |
| 256 | +10. ❌ NEVER create duplicate components |
| 257 | + |
| 258 | +--- |
| 259 | + |
| 260 | +**Enforcement**: Any UI code not following these rules must be rejected and refactored immediately. |
0 commit comments