apache / apache/maka

Converge icon sizes onto a governed scale

Open
#2,359 1 comment 0 reactions 1 assignee Claimed by @1625567290 View on GitHub
Dominant language
TypeScript
Stars
5.4k
Forks
502
Avg merge
1d 2h
Merged PRs (30d)
715

Description

Icon sizes are set per call site with no scale behind them. A sweep of `packages/ui/src` and `apps/desktop/src` finds **145 hardcoded `size={n}` props across 11 distinct values**:

| size | uses |
|---|---|
| 14 | 37 |
| 16 | 35 |
| 15 | 27 |
| 13 | 21 |
| 12 | 13 |
| 11 / 18 / 20 / 24 / 26 / 28 | 12 combined |

`11`, `13`, `15` and `26` sit on no scale at all — Astryx's `Icon` offers `xsm`/`sm`/`md`/`lg` (12/16/20/24), and these fall between its steps. Narrowing to icons passed as a `Button`/`IconButton` `icon` prop — one position, one visual role — still spreads across 14 (16 uses), 16 (10), 15 (8), 13 (3) and 11 (2). Same slot, five different answers.

A token already exists and is almost unused:

```css
--icon-size: 16px; /* chrome glyph size (nav + button icons); dense
meta (12-14) and hero (20+) stay call-site */
```

It has **2 references in the entire codebase**, both in `plan-mode.css`. Its comment defines a real three-tier policy — chrome via token, dense meta at 12–14, hero at 20+ — but nothing enforces the tiers, so call sites drift and the token stays dead.

The precedent for fixing this is in the same file. Stroke width had the same problem (eight values across 143 usages) and was solved with one rule:

```css
svg.lucide { stroke-width: 1.75; }
```

That comment also explains why size cannot be handled identically: a global size rule would capture icons Astryx sizes through its own slot props (`Icon`'s `size`, `SideNavItem`'s `renderIconSlot`), which are the component's decision, not the product's. So this needs per-tier tokens plus a sweep, not one blanket rule.

Suggested direction:

1. Give each tier of the existing policy its own token (chrome / dense-meta / hero) instead of one `--icon-size` that only names the first.
2. Sweep the 145 call sites onto the nearest tier, recording anywhere a genuine exception is needed.
3. Add a check — `check-dead-css.mjs` and `check-a11y.mjs` are existing homes for this kind of governance — so new call sites cannot reintroduce off-scale values.

Found while reworking the chat message meta row (#2358), which landed its icons on 14 to match this policy's dense-meta tier. That PR deliberately does not attempt the sweep.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.