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-08-13 13:57:00 +03:00
- Every dropdown-style value-picker trigger takes its chrome from `dropdownTriggerVariants` in `packages/ui/src/components/ui/dropdown-trigger.ts` ; call sites add layout classes only. Deliberately chrome-less pickers in composers or headers are the 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-08-13 13:57:00 +03:00
Load every matching reference before editing. User-facing or accessible text must load `locale-ui-patterns` . Settings composition is owned by `settings-ui-patterns` , which declares `theme-system` as its one-way companion.
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-08-03 18:38:58 +03:00
## Animation Contract
2026-08-13 13:57:00 +03:00
Animate only `transform` and `opacity` . Use `transform: rotate(...)` , not the individual `rotate` property. Non-composited properties recalculate style continuously; geometry also triggers layout, and wrappers, `will-change` , `contain` , or stepped timing do not remove that cost. Animate only while conveying live information.
For any other technique, load `performance-engineering` and `scripts/perf/DOCUMENTATION.md` , measure it with `bun run profile:animation` , and add a fixture variant when needed. This skill owns animation styling; `performance-engineering` owns performance evidence.
## Completion Criteria
2026-02-01 18:29:34 +02:00
2026-08-03 18:38:58 +03:00
- Animations are limited to `transform` and `opacity` , or their cost was measured and accepted.
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.
2026-08-13 13:57:00 +03:00
- Every applicable contract and loaded task reference was verified with relevant type-check, visual/runtime validation, and generated-asset checks.