2026-02-01 18:29:34 +02:00
---
name : theme-system
2026-07-14 00:45:44 +03:00
description : Use when creating or modifying OpenChamber UI components, styling, colors, buttons, visual states, themes, or icons.
2026-02-01 18:29:34 +02:00
---
2026-07-14 00:45:44 +03:00
# Theme System
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
## Core Rules
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
- Use semantic OpenChamber theme tokens; never hardcode hex colors or generic Tailwind palette colors.
- Use shared UI primitives before introducing feature-local controls.
- Use the shared `Button` ; do not create button wrappers such as `ButtonSmall` or `ButtonLarge` .
2026-07-18 00:11:05 +03:00
- Every dropdown-style value-picker trigger (shows current value, opens a picker) takes its chrome from `dropdownTriggerVariants` in `packages/ui/src/components/ui/dropdown-trigger.ts` (sizes: `sm` dense h-6, `default` forms h-8; native `SelectTrigger` consumes it). Call sites add layout classes only (width/truncation) — never re-declare border/radius/bg/hover. Deliberately chrome-less pickers (chat composer, headers) are the only exception.
2026-07-14 00:45:44 +03:00
- Use the sprite-based `Icon` ; never import icons directly from `@remixicon/react` .
- Apply hover tokens only to interactive elements.
- Use status colors only for actual status/feedback.
- Use selection tokens for selected state and primary tokens for primary actions.
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
## Load References By Task
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
| Task | Required reference |
|---|---|
| Choosing colors/tokens or reviewing styled examples | `references/tokens-and-examples.md` |
| Adding, converting, storing, or generating icons | `references/icons.md` |
| Adding built-in or custom themes | `references/adding-themes.md` |
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
Load every matching reference before editing. Settings work must also load `settings-ui-patterns` ; user-facing or accessible text must load `locale-ui-patterns` .
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
## Token Decision
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
1. Code display -> `syntax.*`
2. Error/warning/success/info -> `status.*`
3. Primary CTA -> `primary.*`
4. Hover/pressed/focus -> `interactive.*`
5. Selected/active state -> `interactive.selection*`
6. Background/text/border layer -> `surface.*` and semantic utility classes
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
Prefer CSS variables/classes for component styling. Use `useThemeSystem()` only when an API requires resolved color values.
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
## Button Contract
2026-03-20 01:01:03 +02:00
2026-07-14 00:45:44 +03:00
Use `Button` from `packages/ui/src/components/ui/button.tsx` .
2026-03-20 01:01:03 +02:00
2026-07-14 00:45:44 +03:00
| Variant | Use |
|---|---|
| `default` | Primary local action |
| `outline` | Visible secondary action |
| `secondary` | Soft secondary action |
| `ghost` | Quiet row/toolbar action |
| `destructive` | Destructive action |
| `chip` | Compact selectable option with `aria-pressed` |
| `link` | Rare inline text action |
2026-03-20 01:01:03 +02:00
2026-07-14 00:45:44 +03:00
| Size | Use |
|---|---|
| `xs` | Dense row/list control |
| `sm` | Compact action |
| `default` | Standard action |
| `lg` | Prominent action |
| `icon` | Icon-only square action |
2026-03-20 01:01:03 +02:00
2026-07-14 00:45:44 +03:00
Do not hardcode button height/padding when a size variant exists. Do not recreate selection/destructive styling with ad-hoc classes.
2026-03-20 01:01:03 +02:00
2026-07-14 00:45:44 +03:00
## Icon Contract
2026-03-20 01:01:03 +02:00
2026-02-01 18:29:34 +02:00
```tsx
2026-07-14 00:45:44 +03:00
import { Icon } from '@/components/icon/Icon' ;
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
< Icon name = "check" className = "size-4" />
2026-02-01 18:29:34 +02:00
```
2026-07-14 00:45:44 +03:00
Use `IconName` for icon values stored in arrays, objects, state, or config. `Icon` has no `size` prop. Run `bun run icons:generate` when introducing a sprite name, and never edit `sprite.ts` manually. Load `references/icons.md` for the complete workflow.
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
## Verification
2026-02-01 18:29:34 +02:00
2026-07-14 00:45:44 +03:00
- No hardcoded/palette colors were introduced.
- Buttons use shared variants and sizes.
- Icons use `Icon` /`IconName` , and generated sprite changes are intentional.
- Hover, selection, primary, and status semantics are distinct.
- Light/dark/high-contrast and long-text states remain legible.
- Relevant type-check, visual/runtime validation, and generated-asset checks ran.