Skip to content

chore(ui): clean up chrome icon registry and add worktree#359

Merged
Astro-Han merged 3 commits intodevfrom
claude/icon-cleanup-stale
May 1, 2026
Merged

chore(ui): clean up chrome icon registry and add worktree#359
Astro-Han merged 3 commits intodevfrom
claude/icon-cleanup-stale

Conversation

@Astro-Han
Copy link
Copy Markdown
Owner

@Astro-Han Astro-Han commented May 1, 2026

Summary

  • Remove 26 unused upstream OpenCode chrome icon keys from packages/ui/src/components/icon.tsx (no callers anywhere) and sync icon.stories.tsx names array.
  • Redraw the new-session / new-session-active icon pair from the v3 imagegen sheet (chat-bubble + plus, with dot for active) using the THICK=2 trace pipeline so the stroke weight matches the v2 brand family.
  • Add a new worktree chrome icon (folder + branch) traced from the v3 worktree sheet so [Feature] Agent session lacks worktree isolation — worktree is a project concept, not a session context #278 can wire it up directly.

Why

The chrome icon registry accumulated 26 keys that were inherited from upstream OpenCode but never wired up; they show up in the storybook gallery and as autocomplete noise when designers and agents pick icons, increasing the chance of picking a stale icon. The new-session v2 drawing was a file + pencil shape that read poorly at sidebar size; the chat-bubble + plus form matches Codex / ChatGPT new-chat convention. worktree is a missing key for #278.

Related Issue

#356 (chrome icon cleanup, P2) and prep for #278 (worktree feature).

Human Review Status

Pending.

Review Focus

  • Are there any consumers of the 26 removed keys that grep missed? (I scanned packages/app/src and packages/ui/src; only icon.stories.tsx referenced them.)
  • The new new-session / new-session-active paths use fill-rule="evenodd" to ensure hollow-region rendering across all SVG renderers; v2 paths relied on potrace winding alone. If a renderer ever shows the new icons as solid blobs, the fill-rule attribute is the first thing to check.
  • The worktree key sits next to branch in icon.tsx; visually it combines folder + branch so it's distinct from both branch and folder.

Risk Notes

None. Only packages/ui chrome icon registry changes. No data, IPC, packaging, signing, or platform behavior is affected. macOS / Windows runtime impact identical.

How To Verify

```text
icon-registry-rename guard test: 3 passed (packages/ui)
typecheck (turbo run typecheck): 8 packages clean
grep for removed keys in packages/app/src + packages/ui/src: only icon.stories.tsx hits, fixed
visual: rendered new-session, new-session-active, worktree at 16/32/96 px in /tmp/*.html, confirmed by maintainer
```

Screenshots or Recordings

Visual comparison HTML files were used during review; no production screenshots since changes are limited to the icon registry and dev surfaces will pick them up automatically.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added new worktree icon for version control operations.
  • Updates

    • Removed deprecated icons: chevron, archive, layout, and share variants.
    • Updated appearance of new-session icon.

Astro-Han added 3 commits May 1, 2026 16:23
Drop align-right, archive, arrow-down-to-line, chevron-double-right,
chevron-left, collapse, discord, edit-small-2, expand, eye, file-tree,
file-tree-active, fork, github, layout-bottom{,-full,-partial},
layout-left{,-full,-partial}, layout-right{,-full,-partial}, share,
shield, speech-bubble. None of these keys are referenced anywhere in
the app; they were inherited from upstream OpenCode and partially
redrawn during the brand v2 pass (2abc369) but never wired up.

Sync icon.stories.tsx names array to match. icon-registry-rename guard
unaffected (only checks agent rename from #128).

Refs #356.
Replace the v2 file+pencil drawing for new-session / new-session-active
with chat-bubble+plus from the v3 imagegen sheet
(imagegen-chrome-icons-newsession.png column 1). The chat-bubble form
matches Codex / ChatGPT "new chat" convention, and the active variant
keeps the bubble identical with a small filled dot in the corner — same
"selected" pattern we use for terminal-active / sidebar-active.

Tracing pipeline: potrace via icon-trace.mjs with THICK=2 to dilate the
strokes so the rendered weight matches the rest of the v2 brand family
(brain, agent, prompt). potrace output uses fill-rule="evenodd" so
hollow regions render correctly across SVG renderers.

Refs #356.
Add a `worktree` key to the chrome icon registry, traced from the v3
imagegen worktree sheet (imagegen-chrome-icons-worktree.png r1c1) with
THICK=2 dilate to match the v2 brand stroke weight. The shape combines
folder + branch so it reads as "a checked-out working directory on a
branch", visually distinct from `branch` (just the fork) and `folder`
(no version-control hint).

No worktree-active variant is added in this commit; #278 surfaces this
inline rather than as a sidebar nav tab. If a nav placement appears
later, a paired active variant can be added then.

Refs #356, #278.
@Astro-Han Astro-Han added enhancement New feature or request P2 Medium priority ui Design system and user interface labels May 1, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e330624c-f074-40f7-bd6e-e73bd35cb15d

📥 Commits

Reviewing files that changed from the base of the PR and between 299c1a7 and 8a764a7.

📒 Files selected for processing (2)
  • packages/ui/src/components/icon.stories.tsx
  • packages/ui/src/components/icon.tsx
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: e2e-artifacts
  • GitHub Check: smoke-macos-arm64
  • GitHub Check: unit-windows-opencode-config-project
  • GitHub Check: unit-windows-desktop
  • GitHub Check: unit-windows-opencode-server-tools
  • GitHub Check: unit-windows-app
  • GitHub Check: unit-app
  • GitHub Check: unit-desktop
  • GitHub Check: typecheck
  • GitHub Check: analyze-js-ts
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:58.310Z
Learning: In Astro-Han/pawwork (`packages/ui/src/theme/context.tsx` and related files), the renaming of localStorage theme keys from `opencode-*` to `pawwork-*` (THEME_ID, COLOR_SCHEME, THEME_CSS_LIGHT, THEME_CSS_DARK) is intentional and should NOT include a migration path from the old keys. Migrating would re-couple PawWork and OpenCode browser storage namespaces, which the PR is explicitly designed to avoid. A reset to the PawWork default theme on upgrade is acceptable by design.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 224
File: packages/app/src/i18n/zh.ts:0-0
Timestamp: 2026-04-24T17:08:46.780Z
Learning: In Astro-Han/pawwork PR `#224`, the first-occurrence `PawWork 爪印` branding rule originally specified in issue `#196` was superseded by an updated Chinese-branding spec. On all zh UI surfaces in `packages/app/src/i18n/zh.ts` (e.g., `dialog.model.unpaid.freeModels.title`, `session.new.subtitle`, `sidebar.gettingStarted.line1`), the correct and intentional target is fully localized `爪印` branding — no `PawWork` prefix. Do NOT flag these strings as missing the first-occurrence `PawWork 爪印` rule in future reviews.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 191
File: packages/app/src/pages/layout/pawwork-sidebar.tsx:139-139
Timestamp: 2026-04-23T15:10:26.994Z
Learning: In Astro-Han/pawwork, the icon registry in `packages/ui/src/components/icon.tsx` uses **bare (unquoted) TypeScript object keys** for single-word icon names (e.g., `pin:` at line 102, `workspace:` at line 99) and **quoted keys** only for hyphenated names (e.g., `"review-active":`). When verifying icon registration with `rg`, always search for both forms — use a pattern like `rg -n "(\"${key}\"|${key}:)"` — otherwise bare-key icons will be missed and incorrectly flagged as unregistered.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 270
File: packages/opencode/src/file/ripgrep.ts:311-328
Timestamp: 2026-04-28T05:36:21.974Z
Learning: In `packages/opencode/src/file/ripgrep.ts` (Astro-Han/pawwork, PR `#270`), the ripgrep binary download flow (`HttpClientRequest.get` → `fs.writeWithDirs` → `extract`) does NOT verify a pinned SHA-256 checksum. Adding per-platform hash verification (15.1.0 × 6 platforms) requires a dedicated manifest + `crypto.subtle.digest` step and is intentionally deferred to a follow-up PR. Existing mitigations: (1) `VERSION` is pinned to `"15.1.0"`, (2) downloads are over HTTPS from GitHub Releases, (3) PawWork production builds ship a bundled `rg` binary so this download path is a last-resort fallback (system PATH → cached → download). Do NOT re-flag the missing checksum verification in this file until the dedicated follow-up PR lands.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 320
File: packages/app/src/pages/layout/sidebar.css:1-6
Timestamp: 2026-04-29T04:23:53.138Z
Learning: In `packages/app/src/pages/layout/sidebar-project.tsx` (Astro-Han/pawwork), the branch-icon container at line 229 uses `size-5` (20px) with `justify-center items-center` and `data-leading-slot` by design. This is intentional: (1) the 3px padding is symmetric, not asymmetric; (2) the branch row lives inside the project-preview header card — a different visual context from the X=8 left rail (SessionRow/NewSessionItem/New session/Search/Settings). The `data-leading-slot` + 20×20 container combination is the deliberate mechanism to render a 14×14 icon glyph (via sidebar.css) inside a larger touch-target without affecting global Icon size="small". Do NOT flag this size-5 container as misaligned or asymmetric in future reviews.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 270
File: packages/opencode/src/tool/edit.ts:35-45
Timestamp: 2026-04-28T04:38:13.519Z
Learning: In `packages/opencode/src/tool/edit.ts` (Astro-Han/pawwork, PR `#270`), the module-scoped `Map<string, Semaphore.Semaphore>` (`locks`) and `lock(filePath)` helper are intentionally left as a global, never-cleaned registry. PR `#270` is a pure upstream-sync graft and mixing in a bugfix would drift the diff from the upstream baseline. The fix (moving per-file semaphores into `InstanceState`/`ScopedCache` for per-instance lifecycle management) is tracked as a follow-up to land in its own PR or be reported upstream. Do NOT re-flag the absence of InstanceState wiring for the lock map in this file until the follow-up PR is opened.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 270
File: packages/opencode/src/patch/index.ts:337-346
Timestamp: 2026-04-28T04:38:10.087Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/patch/index.ts`), the BOM-transition surfacing gap — where `Bom.split` strips BOM before building `unified_diff`/`new_content` but `Bom.join` later re-attaches BOM on disk write, meaning BOM changes are not reflected in the diff payload — is intentionally deferred. PR `#270` is an upstream-sync graft; fixing the issue here would mix refactor + bugfix intents and drift the diff from the upstream baseline needed for clean future grafts. A dedicated follow-up PR (or upstream report) will address this. Do NOT re-flag the missing BOM-change surfacing in `ApplyPatchFileUpdate`/`ApplyPatchFileChange` as a blocking issue in PR `#270` or in future sync PRs that carry the same upstream baseline.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 270
File: packages/opencode/src/tool/edit.ts:48-48
Timestamp: 2026-04-28T08:14:35.518Z
Learning: In `packages/opencode/src/tool/edit.ts` (Astro-Han/pawwork), the `filePath` schema description (`"The absolute path to the file to modify"`) is upstream-inherited from `dev:packages/opencode/src/tool/edit.ts:48`. The runtime actually accepts relative paths (resolved via `Instance.directory` at lines 79-81), but the description fix is intentionally deferred to a single PawWork-authored description-cleanup PR that will also cover the identical mismatch in `packages/opencode/src/tool/write.ts:24`. Do NOT re-flag the too-narrow `filePath` description in upstream-sync PRs; flag it only in the dedicated description-cleanup PR.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 270
File: packages/opencode/src/file/ripgrep.ts:469-470
Timestamp: 2026-04-28T08:29:07.177Z
Learning: In `packages/opencode/src/file/ripgrep.ts` (Astro-Han/pawwork, PR `#270`), the `tree()` function filters files with `if (file.includes(".opencode")) continue`, which is a raw substring match that would also drop unrelated paths whose names merely contain `.opencode` (e.g., `.opencode-backup`). The correct fix is `if (file.split(path.sep).includes(".opencode")) continue` to match only the exact path segment. However, upstream `dev:packages/opencode/src/file/ripgrep.ts` carries the identical false-positive filter. PR `#270` is an upstream-sync graft; fixing it here would diverge from the baseline. The fix is deferred to a PawWork ripgrep filter cleanup PR or an upstream-first fix, to land alongside the other ripgrep deferrals (Schema.Class, bytes-union, abort short-circuit, mixed-separator). Do NOT re-flag the `.opencode` substring filter in upstream-sync PRs.
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 208
File: packages/app/src/components/prompt-input.tsx:1569-1611
Timestamp: 2026-04-24T05:39:58.329Z
Learning: In Astro-Han/pawwork `packages/app/src/components/prompt-input.tsx`, after the composer unification in PR `#208` (fixed in commit 5d810aa):
- `SendButton.disabled` does NOT gate on `store.mode !== "normal"`. Shell mode has a fully visible, clickable orange submit button that calls `handleSubmit` directly (same path as the Enter key in `handleKeyDown`). Do NOT suggest re-adding the mode gate.
- `SendButton` does NOT use the `buttons()` spring opacity animation (`style={buttons()}`). It is always fully visible regardless of mode.
- `WorkspaceChip` is gated on `props.homeMode && store.mode === "normal"` so it hides in shell mode (preventing it from appearing isolated/bright while neighboring controls fade).
- The left-side chip group (`aria-hidden={store.mode !== "normal"}`) covers attach/model/variant/workspace controls only; `SendButton` remains in a separate right-side sibling div.
📚 Learning: 2026-04-22T09:32:58.310Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:58.310Z
Learning: In Astro-Han/pawwork (`packages/ui/src/theme/context.tsx` and related files), the renaming of localStorage theme keys from `opencode-*` to `pawwork-*` (THEME_ID, COLOR_SCHEME, THEME_CSS_LIGHT, THEME_CSS_DARK) is intentional and should NOT include a migration path from the old keys. Migrating would re-couple PawWork and OpenCode browser storage namespaces, which the PR is explicitly designed to avoid. A reset to the PawWork default theme on upgrade is acceptable by design.

Applied to files:

  • packages/ui/src/components/icon.stories.tsx
  • packages/ui/src/components/icon.tsx
📚 Learning: 2026-04-23T15:10:26.994Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 191
File: packages/app/src/pages/layout/pawwork-sidebar.tsx:139-139
Timestamp: 2026-04-23T15:10:26.994Z
Learning: In Astro-Han/pawwork, the icon registry in `packages/ui/src/components/icon.tsx` uses **bare (unquoted) TypeScript object keys** for single-word icon names (e.g., `pin:` at line 102, `workspace:` at line 99) and **quoted keys** only for hyphenated names (e.g., `"review-active":`). When verifying icon registration with `rg`, always search for both forms — use a pattern like `rg -n "(\"${key}\"|${key}:)"` — otherwise bare-key icons will be missed and incorrectly flagged as unregistered.

Applied to files:

  • packages/ui/src/components/icon.stories.tsx
  • packages/ui/src/components/icon.tsx
📚 Learning: 2026-04-29T04:23:53.138Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 320
File: packages/app/src/pages/layout/sidebar.css:1-6
Timestamp: 2026-04-29T04:23:53.138Z
Learning: In `packages/app/src/pages/layout/sidebar-project.tsx` (Astro-Han/pawwork), the branch-icon container at line 229 uses `size-5` (20px) with `justify-center items-center` and `data-leading-slot` by design. This is intentional: (1) the 3px padding is symmetric, not asymmetric; (2) the branch row lives inside the project-preview header card — a different visual context from the X=8 left rail (SessionRow/NewSessionItem/New session/Search/Settings). The `data-leading-slot` + 20×20 container combination is the deliberate mechanism to render a 14×14 icon glyph (via sidebar.css) inside a larger touch-target without affecting global Icon size="small". Do NOT flag this size-5 container as misaligned or asymmetric in future reviews.

Applied to files:

  • packages/ui/src/components/icon.tsx
📚 Learning: 2026-04-29T04:31:25.092Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 0
File: :0-0
Timestamp: 2026-04-29T04:31:25.092Z
Learning: In `packages/app/src/pages/layout/pawwork-sidebar.tsx` (Astro-Han/pawwork), the session-row pin button container must be sized `w-[14px] h-[14px]` to match the 14×14 leading slot declared in `sidebar-items.tsx`. The Icon glyph inside is auto-shrunk to 14×14 by the `[data-leading-slot]` CSS rule in `sidebar.css`, so all three dimensions (button wrapper, icon content, slot frame) align at 14×14. Do NOT suggest widening the pin button container beyond 14×14 in this context.

Applied to files:

  • packages/ui/src/components/icon.tsx
📚 Learning: 2026-04-23T08:51:04.230Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:04.230Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/util/filesystem.ts`), the `Filesystem` utility does NOT expose a `remove` or `unlink` helper. The established repository pattern for auth.json teardown in tests (e.g. `provider.test.ts`, `amazon-bedrock.test.ts`, `workspace-adaptor.test.ts`) is to combine `Filesystem.write` with `node:fs/promises unlink`. Do not flag this mixed usage as inconsistent — it is the correct and intentional pattern.

Applied to files:

  • packages/ui/src/components/icon.tsx
🔇 Additional comments (3)
packages/ui/src/components/icon.stories.tsx (1)

75-75: Storybook options correctly include the new icon key.

"worktree" is added to the gallery/select list and stays aligned with the registry update.

packages/ui/src/components/icon.tsx (2)

32-33: new-session icon pair update looks consistent and safe.

Both keys remain registered, preserving the public name contract while updating only SVG payloads.


59-59: worktree icon is correctly added to the registry.

The new key integrates cleanly with keyof typeof icons consumers.


📝 Walkthrough

Walkthrough

This PR updates the icon registry by removing approximately 26 unused icon entries from the codebase, replaces the SVG markup for new-session and new-session-active icons, and adds a new worktree icon entry. The corresponding story file is updated to reflect these changes in its gallery dataset.

Changes

Cohort / File(s) Summary
Icon Registry and Story
packages/ui/src/components/icon.tsx, packages/ui/src/components/icon.stories.tsx
Removes multiple unused icon entries (align-right, archive, fork, chevron variants, layout variants, speech-bubble, share, shield, github, discord, arrow-down-to-line, etc.); replaces new-session and new-session-active SVG markup; adds worktree icon; updates story's icon names dataset to match registry changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 With whiskers twitching, I hop with glee,
Old icons pruned—the registry clean and free!
Worktree sprouts where unused ones once lay,
New-session reborn! Hooray, hooray! 🎨✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: cleaning up the chrome icon registry by removing unused keys and adding the worktree icon.
Description check ✅ Passed The description comprehensively addresses all required template sections including summary, rationale, related issues, review focus, risk assessment, verification steps, and addressing all checklist items.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/icon-cleanup-stale

Review rate limit: 8/10 reviews remaining, refill in 10 minutes and 51 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request streamlines the icon library by removing several unused icons and adding a new worktree icon. The review feedback highlights that the SVG paths for the updated new-session icons and the new worktree icon are inconsistent with the project's standard 20x20 grid and stroke width requirements, recommending a redesign of these paths for better consistency across the icon family.

Comment thread packages/ui/src/components/icon.tsx
Comment thread packages/ui/src/components/icon.tsx
@Astro-Han Astro-Han merged commit 8a24eff into dev May 1, 2026
38 of 39 checks passed
@Astro-Han Astro-Han deleted the claude/icon-cleanup-stale branch May 1, 2026 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request P2 Medium priority ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant