Skip to content

feat(studio): custom icon set module and specimen sheet - #4195

Open
miguel-heygen wants to merge 7 commits into
mainfrom
feat/studio-icon-set
Open

miguel-heygen wants to merge 7 commits into
mainfrom
feat/studio-icon-set

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

What a user gets

Studio gets its own icon set: one grid, one stroke, one corner language, drawn for the dark Studio surface and legible at 12 px. This PR adds the module and the specimen sheet only; no call site changes yet, so nothing a user sees moves in this PR. The sweep by area follows in small PRs, and the last one removes the third-party icon library.

What is in it

  • packages/studio/src/icons/glyphs.ts: 102 glyphs as path data on a 16-unit grid with a 1-unit safe margin. A few glyphs carry a small drawing used below 14 px (sidebar pair, order quartet, file types) instead of scaling the 16 px shape down. Four names (bring-forward, send-backward, bring-to-front, send-to-back) map verbatim to Studio's existing default icons rather than a new drawing; everything else in the set is custom.
  • packages/studio/src/icons/Icon.tsx: <Icon name size title filled>. currentColor only; stroke 1.5 at 14 px and up, 1.25 below; round caps and joins; aria-hidden unless a title is given; filled paints only closed silhouettes (keyframe, play, select, magnet), open glyphs ignore it.
  • packages/studio/src/icons/index.tsx: one named export per glyph with an Icon suffix (CheckIcon, EyeOffIcon, WindowIcon) so a call site imports by name and nothing shadows Image, File or Window.
  • packages/studio/scripts/icon-specimen.tsx: renders the specimen sheet from the module itself, so the sheet cannot drift from the code.
  • Icon.test.tsx: every glyph renders with the 16 viewBox in currentColor, no hard-coded colour, stays inside the safe margin (every path point, relative commands resolved, plus primitive boxes), has a named export; title announces, filled respects the silhouette rule, small variants switch at 14 px, stroke follows the size class.

Before

Today's Phosphor glyphs (left of each pair) beside ours (right), the 20 most-used icons at 16 and 12 px, then the pairs that must stay distinct at 12 px:

Today beside ours, and the distinct-at-12 block

After

The icons placed in a mock of Studio's chrome, then the whole set at 12 / 14 / 16 / 20 px with enabled, hover, active and disabled states:

The set in a Studio chrome mock

Every icon at four sizes and four states

What I measured

  • packages/studio/src/icons/Icon.test.tsx alone on a Linux box: exit 0, 210 passed, 0 skipped.
  • Three mutations, one run each: an absolute coordinate off the grid (M0.5 8h10) and a relative one running off it (M3 8h13) each fail only that glyph's margin test; filled applied to every glyph fails only the silhouette test. Restored run: 210 passed.
  • Specimen rendered by the script and looked at in a browser at 1x before posting.

Rules for the sweep PRs

  • title only on a standalone icon; inside a button that has its own label the icon stays aria-hidden.
  • Call sites pass size and className only; viewBox, aria-* and role are the module's.

What I did NOT exercise

  • No call site uses the module yet; the sweep PRs carry the real Before/After captures per area.
  • No visual regression test; the specimen is the review surface.

@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

Layer-order icons redrawn after design review: back square outline, front square filled with a real gap (no overlap), direction and count carried by an arrow outside the squares (above = forward, below = backward, single = one step, double = all the way). Head b4fac9e.

@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

12 px zoomed x4 (real shape, magnified for review) beside the 16/20 and the reference:

v4-crop

@miguel-heygen
miguel-heygen marked this pull request as ready for review September 19, 2026 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant