|
| 1 | +### UI‑New Agent Guide |
| 2 | + |
| 3 | +This package is our Chakra v3 design system (`@trycompai/ui-new`). The goal is **one source of truth** for design decisions (colors, typography, radii, borders, focus rings) so changing a token updates the entire system. |
| 4 | + |
| 5 | +### Golden rules |
| 6 | + |
| 7 | +- **No hardcoded styling in recipes** if a token exists. |
| 8 | + - Use **tokens** (`radii`, `borders`, `shadows`, `fonts`, …) and **semantic tokens** (`colorPalette.*`, `bg/fg/border`) instead of raw values. |
| 9 | +- **Semantic tokens define behavior**, recipes only consume behavior. |
| 10 | + - Example: recipes use `colorPalette.solid/hover/active/contrast` instead of `primary.700`. |
| 11 | +- **DRY through factories + shared helpers** |
| 12 | + - Shared logic lives in `theme/semantic/` and `theme/recipes/shared/`. |
| 13 | +- **Colocate config with the recipe** |
| 14 | + - Each component recipe gets its own folder under `theme/recipes/<component>/` once it needs multiple files. |
| 15 | +- **Light palettes can use black contrast** |
| 16 | + - `yellow` and `sand` intentionally use `colorPalette.contrast = black` for readability. |
| 17 | + |
| 18 | +### Folder structure |
| 19 | + |
| 20 | +``` |
| 21 | +packages/ui-new/src/ |
| 22 | + components/ |
| 23 | + ui/ |
| 24 | + provider.tsx # ChakraProvider wiring |
| 25 | + color-mode.tsx # Color mode helpers |
| 26 | + ... # UI wrappers |
| 27 | + theme/ |
| 28 | + index.ts # createSystem + theme config (imports everything) |
| 29 | + global-css.ts # token-driven globalCss (low specificity :where) |
| 30 | + colors/ |
| 31 | + index.ts # raw palettes (primary/secondary/blue/orange/rose/yellow/sand) |
| 32 | + tokens/ |
| 33 | + borders.ts # border style tokens (subtle/strong/none) |
| 34 | + radii.ts # radii tokens + semantic radii (input/card) |
| 35 | + shadows.ts # focus ring shadow token (palette-aware) |
| 36 | + typography.ts # Geist fonts + brand line-height/letter-spacing + weights |
| 37 | + index.ts # barrel exports for tokens/* |
| 38 | + semantic/ |
| 39 | + helpers.ts # {colors.<palette>.<shade>} refs + token helpers |
| 40 | + types.ts # types used by semantic token factories |
| 41 | + semantic-colors.ts # exports semanticColors |
| 42 | + palettes/ |
| 43 | + dark-palette.ts # factory for “dark” palettes (white contrast) |
| 44 | + light-palette.ts # factory for “light” palettes (black contrast) |
| 45 | + secondary-palette.ts # neutral palette semantics |
| 46 | + index.ts # barrel export |
| 47 | + semantic-tokens.ts # backwards-compatible re-export of semanticColors |
| 48 | + recipes/ |
| 49 | + index.ts # exports recipes |
| 50 | + shared/ |
| 51 | + color-palettes.ts # SUPPORTED_COLOR_PALETTES + variant generator |
| 52 | + button/ |
| 53 | + defaults.ts # BUTTON_DEFAULT_VARIANTS |
| 54 | + sizes.ts # BUTTON_SIZES |
| 55 | + variants.ts # BUTTON_VARIANTS |
| 56 | + recipe.ts # buttonRecipe |
| 57 | + index.ts # barrel for button recipe folder |
| 58 | +``` |
| 59 | + |
| 60 | +### How to add a new color palette |
| 61 | + |
| 62 | +- **1) Add raw palette** |
| 63 | + - Add the scale in `src/theme/colors/index.ts` |
| 64 | +- **2) Add semantic behavior** |
| 65 | + - Add to `src/theme/semantic/semantic-colors.ts` |
| 66 | + - Choose the correct factory: |
| 67 | + - `makeDarkPalette({ palette: '...' })` for “dark” palettes (white text) |
| 68 | + - `makeLightPalette({ palette: 'yellow' | 'sand', ... })` for “light” palettes (black text) |
| 69 | +- **3) Allow it in recipes** |
| 70 | + - Add it to `src/theme/recipes/shared/color-palettes.ts` (`SUPPORTED_COLOR_PALETTES`) |
| 71 | + - Recipes like button will automatically pick it up. |
| 72 | + |
| 73 | +### How to add a new recipe (best practice) |
| 74 | + |
| 75 | +- Create `src/theme/recipes/<component>/` once you have multiple concerns: |
| 76 | + - `defaults.ts`, `sizes.ts`, `variants.ts`, `recipe.ts`, `index.ts` |
| 77 | +- Keep `recipe.ts` as composition: |
| 78 | + - base styles + `defaultVariants` + `variants` wired from the local folder + shared helpers. |
| 79 | +- Prefer **semantic tokens**: |
| 80 | + - `bg: 'colorPalette.solid'` |
| 81 | + - `_hover: { bg: 'colorPalette.hover' }` |
| 82 | + - `color: 'colorPalette.contrast'` |
| 83 | + - `borderColor: 'colorPalette.border'` |
| 84 | + - focus ring: `boxShadow: 'focusRing'` (palette-aware) |
| 85 | + |
| 86 | +### Typography rules (Geist Sans) |
| 87 | + |
| 88 | +- Host apps must load fonts via `next/font` and apply `GeistSans.className` at the document root. |
| 89 | +- `ui-new` defaults are enforced via: |
| 90 | + - `theme/tokens/typography.ts` for `fonts/*`, `lineHeights.brand`, `letterSpacings.brand` |
| 91 | + - `theme/global-css.ts` for document + headings + form controls |
| 92 | + |
| 93 | +### Required checks (before shipping) |
| 94 | + |
| 95 | +Run these (scoped to this package): |
| 96 | + |
| 97 | +```bash |
| 98 | +bun run -F @trycompai/ui-new typecheck |
| 99 | +bun run -F @trycompai/ui-new lint |
| 100 | +``` |
0 commit comments