# Icon System
OpenChamber uses an SVG sprite-based icon system for performance. Remixicon glyphs and explicitly registered custom glyphs are rendered via a single hidden SVG sprite injected into the DOM, referenced by ``.
## Usage
```tsx
import { Icon } from "@/components/icon/Icon";
```
## Icon Names
Icons use kebab-case names based on Remixicon. To find an icon name:
1. Start from the Remixicon component name: `RiArrowDownSLine`
2. Remove `Ri` prefix → `ArrowDownSLine`
3. Convert to kebab-case → `arrow-down-s`
Common suffixes:
- `Line` / `Fill` are dropped from the sprite name
- Numbers are preserved: `RiChat4Line` → `chat-4`
## Adding a New Icon
1. Import and use it in your code: ``
2. Run `bun run icons:sprite` to regenerate the sprite with the new icon
3. The script scans `packages/ui/src` for all `RiX` usages and extracts SVG paths
If the icon doesn't exist in the sprite, the script will warn you.
Custom product glyphs are registered in `scripts/generate-icon-sprite.mjs`. They must use the shared `24x24` viewbox and `currentColor` so they match Remixicon sizing and theme behavior.
## Sizing
The `Icon` component does not have a `size` prop. Use Tailwind classes instead:
```tsx
{/* 16px */}
{/* 20px */}
{/* 24px */}
```
## Type Safety
```tsx
import type { IconName } from "@/components/icon/icons";
const icon: IconName = "arrow-down-s"; // type-checked
```
## Architecture
- `sprite.ts` — Auto-generated SVG path data (run `bun run generate-icon-sprite` to regenerate)
- `Icon.tsx` — The `` component, injects sprite on first mount
- `icons.ts` — TypeScript type `IconName`
The sprite is injected as a hidden `