Skip to content

feat(tabs): add a setting to show pinned tabs as icons only - #17747

Open
gsustech wants to merge 1 commit into
stablyai:mainfrom
gsustech:feat/pinned-tabs-icon-only
Open

gsustech wants to merge 1 commit into
stablyai:mainfrom
gsustech:feat/pinned-tabs-icon-only

Conversation

@gsustech

@gsustech gsustech commented Aug 31, 2026 •

Copy link
Copy Markdown

ELI5

Pinned tabs keep their full-width title even though their icon is enough to recognise them. Tabs never shrink below 144px, so with a handful open the strip overflows and the pinned tabs scroll out of view. This adds an opt-in setting that shrinks pinned tabs to just their icon, giving the space back to the rest of the tab strip.

What Changed

Before: a pinned tab is as wide as any other tab (144–300px) and shows its title plus a pin glyph. Six tabs in a 1280px window already overflow, and the pinned tabs at the start of the strip scroll out of view.

After: with Settings → General → Navigation → Show pinned tabs as icons only turned on (off by default), a pinned tab collapses to a 25px chip showing only its icon, so more tabs fit before the strip has to scroll. Unpinned tabs are unchanged.

It applies to every tab kind (terminal, agent session, editor, browser, simulator). The collapse steps aside wherever the title was the only place some information lived:

  • Rename: double-clicking a collapsed tab opens the rename field; closing it collapses the tab again.
  • Title: the tab's hover card still shows the full title, and screen readers get it through an aria-label (the tab is a role="button" with no visible text once collapsed).
  • File state: a collapsed editor tab keeps a small coloured dot for git status, deleted/renamed files and unsaved edits, and spells them out in the hover card and accessible name, e.g. README.md (M, unsaved).

Mechanism: the setting is a new pinnedTabsIconOnly boolean in global settings. The tab bar reads it once and passes it to every row it renders (through TabBarItemRow); each tab component drops the label when the tab is pinned and not being renamed, and passes that to the strip's existing useTabStripSlotProps hook, which swaps the fixed tab width for a shrink-to-fit one (active collapsed tabs still dock as before). The tab strip's overflow measurement is re-keyed on the setting so scrolling stays correct when the widths change.

One small existing issue is fixed in the same code, because collapsing makes it visible: a pinned tab has no close button, so the unsaved-changes dot used to vanish on hover and leave nothing behind. It now stays.

SortableTab.tsx and EditorFileTab.tsx were both at the 400-line limit, so the terminal close button and the editor tab's icon logic move, unchanged, into their own files instead of suppressing the rule.

Why

Pinning is how people mark the tabs they keep open all day, so those are exactly the tabs whose icon is already familiar. Hiding their titles is the cheapest way to free space without touching how unpinned tabs behave.

Alternatives considered:

  • Narrower tabs for everyone — would truncate the tabs people are actively reading, and changes the default experience for all users.
  • Always collapse pinned tabs — would surprise people who rely on seeing pinned titles, so it's an opt-in setting.
  • Keep the pin glyph next to the icon — costs width for no information, since the chip's position and shape already mark it as pinned.

Linked Issue

Related: #2996 (pinned tabs), #9459 (pinned tabs in an overflowing tab strip).

Visual Proof

Measured in a 1280px-wide window with three pinned and three unpinned tabs:

Setting off Setting on
Pinned tabs 144px each, with title 25px, icon only
Tab content vs space available 864px in 464px — overflows 512px — fits
Tabs in view 4 of 6 (pinned tabs scrolled away) 6 of 6

Before (setting off), after (setting on), and the setting itself:

1-before-setting-off 2-after-setting-on 3-setting

Testing

Verified in a dev build driven over CDP (macOS), toggling the real Settings switch: collapsed widths, strip overflow, accessible names, rename round-trip, the git-status/unsaved dot and label, all five tab kinds, and turning the setting off restoring everything. The setting was also toggled and exercised by hand.

Automated: new tests cover every row kind receiving the setting, the tab strip re-measuring when it changes, the collapsed editor state (status, deleted/renamed and unsaved in combination), and the slot-width hook choosing the shrink-to-fit width while still docking an active tab. Ran pnpm tc, check:code-quality:changed (0 findings), the tab-bar and settings test suites (2,042 passing), the max-lines ratchet, and the localization checks.

The change is renderer-only and has no platform-specific code, no IPC or wire changes, and no effect on SSH/remote behaviour.

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

AI Disclosure

Written with Claude Code (Claude models). I directed the change, tested it by hand, and reviewed every change before it was pushed.

Review

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Security: no new inputs, IPC or network access; the only new data is one boolean setting. Cross-platform: no platform-specific code. Remote SSH / mobile: renderer-only, no wire changes. Backwards compatibility: the setting defaults to off and existing profiles without it read as off.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

🤖 Generated with Claude Code

https://claude.ai/code/session_016hmmFsseoDoJRcgWjCeUmc

Copilot AI lite review requested due to automatic review settings August 31, 2026 21:51
@gsustech
gsustech requested a review from brennanb2025 as a code owner August 31, 2026 21:51
@greptile-apps

greptile-apps Bot commented Aug 31, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Adds a UI setting to collapse pinned tabs to icons.

The PR does not appear safe to merge until scrolling an overflowing strip leaves the visible tabs clickable.

Findings

  1. P1 Docked tab covers other tabs ▶

Summary

The PR adds an opt-in setting that collapses pinned tabs to icons, preserves editor state in a compact indicator, and updates tab-strip measurement and scrolling. The later tab-strip changes also dock the active tab at a scroll edge, where it can cover other tabs during manual scrolling.

Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  S[Icon-only setting] --> R[Tab rows choose compact width]
  R --> O[Scrollable tab strip]
  O --> D[Active slot docks at viewport edge]
  O --> M[Manual scroll moves other slots beneath dock]
  D --> B[Dock overlays a tab]
  M --> B
Loading

Reviews (5) · Last reviewed commit: "feat(tabs): add a setting to show pinned..."

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a new user setting to collapse pinned tabs to icon-only chips (off by default), reclaiming tab-strip width while preserving key states (rename, tooltip title, dirty indicator, accessibility naming) across all tab row kinds.

Changes:

  • Introduces pinnedTabsIconOnly as a persisted global setting (default false) and wires it into the tab-bar runtime model.
  • Implements icon-only rendering for pinned tabs across terminal, browser, editor, simulator, and agent-session rows (including tooltip + aria-label behavior).
  • Refactors tab chrome into small components and adds targeted test coverage for collapse behavior, layout re-keying, and icon selection.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/shared/global-settings-types.ts Adds pinnedTabsIconOnly to the global settings type.
src/shared/default-global-settings.ts Sets default pinnedTabsIconOnly: false.
src/renderer/src/i18n/locales/en.json Adds English strings/keywords for the new setting.
src/renderer/src/components/tab-bar/use-tab-bar-runtime-model.ts Exposes pinnedTabsIconOnly on the tab-bar runtime model from persisted settings.
src/renderer/src/components/tab-bar/use-tab-bar-item-projection.ts Re-keys tab-strip layout memoization when icon-only mode toggles.
src/renderer/src/components/tab-bar/TerminalTabCloseButton.tsx Extracts terminal close button into a dedicated component.
src/renderer/src/components/tab-bar/TabBar.tsx Passes pinnedTabsIconOnly into tab item projection.
src/renderer/src/components/tab-bar/tab-title-tooltip.test.tsx Updates test harness to provide the new pinnedIconOnly prop.
src/renderer/src/components/tab-bar/tab-bar-item-surface.tsx Threads pinnedIconOnly through all row renderers.
src/renderer/src/components/tab-bar/tab-bar-item-model.ts Includes pinnedTabsIconOnly in the tab-strip layout key to force re-measure on toggle.
src/renderer/src/components/tab-bar/SortableTab.update-depth-probe.test.tsx Updates test harness to provide the new pinnedIconOnly prop.
src/renderer/src/components/tab-bar/SortableTab.tsx Implements icon-only pinned terminal/agent tabs with tooltip + aria-label support.
src/renderer/src/components/tab-bar/SortableTab.rename-shortcut.test.tsx Updates test harness to provide the new pinnedIconOnly prop.
src/renderer/src/components/tab-bar/pinned-tab-icon-only.ts Adds shared collapse predicate and shared CSS class constants.
src/renderer/src/components/tab-bar/pinned-tab-icon-only.test.tsx Adds unit tests for collapse predicate, row wiring, and layout re-keying.
src/renderer/src/components/tab-bar/EditorFileTabLeadingIcon.tsx Extracts editor leading icon logic and adds simulator glyph handling.
src/renderer/src/components/tab-bar/EditorFileTabLeadingIcon.test.tsx Adds tests for icon precedence and simulator glyph behavior.
src/renderer/src/components/tab-bar/EditorFileTab.tsx Implements icon-only pinned editor tabs, including dirty-dot behavior and accessibility naming.
src/renderer/src/components/tab-bar/EditorFileTab.test.tsx Updates test harness to provide the new pinnedIconOnly prop.
src/renderer/src/components/tab-bar/BrowserTab.tsx Implements icon-only pinned browser tabs with aria-label naming when collapsed.
src/renderer/src/components/tab-bar/BrowserTab.test.tsx Adds coverage for collapsed pinned browser tabs’ label removal + accessible naming.
src/renderer/src/components/settings/GeneralPane.tsx Adds the new toggle in Settings → General → Navigation.
src/renderer/src/components/settings/general-search.ts Adds the new setting to the General/Navigation search catalog.
src/main/codex-accounts/service-test-harness.ts Updates settings test harness defaults with pinnedTabsIconOnly.
src/main/codex-accounts/runtime-home-settings-test-fixtures.ts Updates runtime-home settings fixtures with pinnedTabsIconOnly.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@coderabbitai

coderabbitai Bot commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

  • Last reviewed commit: 8d53ce55f9613ee67d9b43b50742a9b884abc0f0
  • Latest commit, not reviewed: 23ade7c

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: abfd7fc5-6492-40ff-b633-3fde3cc62843

📥 Commits

Reviewing files that changed from the base of the PR and between 28a9c772655f997b430b0b8582db3ac0bee7982b and 8d53ce55f9613ee67d9b43b50742a9b884abc0f0.

📒 Files selected for processing (9)
  • src/renderer/src/components/settings/GeneralPane.tsx
  • src/renderer/src/components/tab-bar/BrowserTab.tsx
  • src/renderer/src/components/tab-bar/EditorFileTab.tsx
  • src/renderer/src/components/tab-bar/SortableTab.tsx
  • src/renderer/src/components/tab-bar/pinned-tab-icon-only.test.tsx
  • src/renderer/src/components/tab-bar/tab-width-rules.ts
  • src/renderer/src/i18n/locales/en.json
  • src/shared/default-global-settings.ts
  • src/shared/global-settings-types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/renderer/src/i18n/locales/en.json

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.

Walkthrough
📝 Walkthrough

Walkthrough

Adds a global setting for icon-only pinned tabs and exposes it in General settings and settings search. Propagates the setting through the tab-bar runtime, projection, layout key, and tab components. Collapsed browser, terminal, agent-session, simulator, and editor tabs now hide labels and pin icons, expose accessible labels, and use adjusted sizing. Adds editor icon and state handling, shared close-button behavior, tests, and automation localization strings.

Merge Risk: Low · up to 8d53c

The PR adds an opt-in icon-only presentation for pinned tabs without changing tab data or privileges. In localized settings search, the new option may be discoverable through the Navigation section but remain hidden by the setting’s narrower filter, so owner follow-up is recommended before or after merge.

Pre-merge checks: Passed 4
Check name Status Explanation
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.
Title check Passed The title clearly and concisely describes the primary change: adding a setting to display pinned tabs as icons only.
Description check Passed The description is comprehensive and covers the user impact, implementation, rationale, linked issues, visual proof, testing, AI disclosure, compatibility considerations, and checklist. The required R…
Full details: Description check

Explanation

The description is comprehensive and covers the user impact, implementation, rationale, linked issues, visual proof, testing, AI disclosure, compatibility considerations, and checklist. The required Risk section and explicit risk level are missing, but the description is otherwise mostly complete.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/renderer/src/i18n/locales/en.json (1)

174-180: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use auto-generated localization keys.

The new settings.general... IDs do not follow the repository convention used by the surrounding auto.components... entries. Generate keys from the file path and source text, then run pnpm run sync:localization-catalog. Update the TypeScript references to the generated keys.

Based on learnings: new locale strings should use SHA1(file path + source text) keys and be propagated to locale catalogs with pnpm run sync:localization-catalog.

Source: Learnings


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: 330e9ac0-a336-4413-aedd-7f6b2537303b

📥 Commits

Reviewing files that changed from the base of the PR and between 02a7742 and f3409bfd6ee6bc5a8b622250876574f1da3f93c3.

📒 Files selected for processing (25)
  • src/main/codex-accounts/runtime-home-settings-test-fixtures.ts
  • src/main/codex-accounts/service-test-harness.ts
  • src/renderer/src/components/settings/GeneralPane.tsx
  • src/renderer/src/components/settings/general-search.ts
  • src/renderer/src/components/tab-bar/BrowserTab.test.tsx
  • src/renderer/src/components/tab-bar/BrowserTab.tsx
  • src/renderer/src/components/tab-bar/EditorFileTab.test.tsx
  • src/renderer/src/components/tab-bar/EditorFileTab.tsx
  • src/renderer/src/components/tab-bar/EditorFileTabLeadingIcon.test.tsx
  • src/renderer/src/components/tab-bar/EditorFileTabLeadingIcon.tsx
  • src/renderer/src/components/tab-bar/SortableTab.rename-shortcut.test.tsx
  • src/renderer/src/components/tab-bar/SortableTab.tsx
  • src/renderer/src/components/tab-bar/SortableTab.update-depth-probe.test.tsx
  • src/renderer/src/components/tab-bar/TabBar.tsx
  • src/renderer/src/components/tab-bar/TerminalTabCloseButton.tsx
  • src/renderer/src/components/tab-bar/pinned-tab-icon-only.test.tsx
  • src/renderer/src/components/tab-bar/pinned-tab-icon-only.ts
  • src/renderer/src/components/tab-bar/tab-bar-item-model.ts
  • src/renderer/src/components/tab-bar/tab-bar-item-surface.tsx
  • src/renderer/src/components/tab-bar/tab-title-tooltip.test.tsx
  • src/renderer/src/components/tab-bar/use-tab-bar-item-projection.ts
  • src/renderer/src/components/tab-bar/use-tab-bar-runtime-model.ts
  • src/renderer/src/i18n/locales/en.json
  • src/shared/default-global-settings.ts
  • src/shared/global-settings-types.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

'settings.general.pinnedTabsIconOnly.description',
'Hide the title on pinned tabs so they shrink to their icon and leave more room in the tab strip.'
)}
keywords={['pinned', 'tab', 'icon', 'compact', 'space']}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- repository conventions ---'
find /tmp/coderabbit-repo-knowledge/stablyai/orca-89dc44e4 -maxdepth 2 -type f -name '*.md' -print 2>/dev/null | sort
printf '%s\n' '--- GeneralPane.tsx ---'
sed -n '130,205p' src/renderer/src/components/settings/GeneralPane.tsx
printf '%s\n' '--- SearchableSetting.tsx ---'
cat -n src/renderer/src/components/settings/SearchableSetting.tsx
printf '%s\n' '--- general-search.ts ---'
cat -n src/renderer/src/components/settings/general-search.ts

Repository: stablyai/orca

Length of output: 17871


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- GeneralPane imports, keyword definitions, and section guard ---'
rg -n -C 8 'tabOrderKeywords|pinnedTabsIconOnly|getGeneralNavigationSearchEntries|matchesSettingsSearch|searchQuery' src/renderer/src/components/settings/GeneralPane.tsx
printf '%s\n' '--- settings-search contract ---'
cat -n src/renderer/src/components/settings/settings-search.ts
printf '%s\n' '--- localized keyword helpers ---'
cat -n src/renderer/src/components/settings/settings-search-keywords.ts

Repository: stablyai/orca

Length of output: 17211


Pass localized aliases to SearchableSetting.

SearchableSetting filters its content with matchesSettingsSearch. A localized icon, compact, or space query can match getGeneralNavigationSearchEntries and render the Navigation section, but the switch uses only English keywords and returns null. Reuse the localized keyword list or remove the duplicate inner filter. Add a non-English regression test.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues — two minor points inline worth confirming before merge.

Reviewed changes

  • pinnedTabsIconOnly setting — new opt-in boolean (default off) wired through global-settings-types, default-global-settings, the General settings pane, and settings search; read into useTabBarRuntimeModel and threaded to every row kind.
  • Icon-only collapse — shouldCollapsePinnedTabToIcon plus the TAB_ICON_ONLY_* width/root classes applied across SortableTab, BrowserTab, and EditorFileTab; collapsed pinned tabs drop their label, shrink-wrap to the glyph, and get an aria-label plus a hover tooltip.
  • Layout re-key — buildTabStripLayoutKey now includes the setting so strip overflow measurement re-runs when the toggle flips.
  • Refactors — EditorFileTabLeadingIcon extracted (mode → simulator → file-type glyph precedence, Smartphone for simulator tabs) and TerminalTabCloseButton extracted from SortableTab.
  • Drive-by fix — a pinned dirty editor tab keeps its unsaved-changes dot on hover instead of blanking the slot.
  • Tests — collapse predicate, five-row-kind coverage, layout-key re-key, accessible-name coverage, and leading-icon precedence tests.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: ffcffb1d-0d93-4449-b473-11e03ca09793

📥 Commits

Reviewing files that changed from the base of the PR and between f3409bfd6ee6bc5a8b622250876574f1da3f93c3 and 29cc0dfadcd22fe2cf3cc58bd4b341f288fdd64f.

📒 Files selected for processing (3)
  • src/renderer/src/components/tab-bar/EditorFileTab.tsx
  • src/renderer/src/components/tab-bar/collapsed-editor-tab-state.test.ts
  • src/renderer/src/components/tab-bar/collapsed-editor-tab-state.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found — both prior inline concerns are addressed cleanly.

Reviewed changes

  • Status-state recovery — collapsed pinned editor tabs now surface git status and deleted/renamed external mutation through a new getCollapsedEditorTabState helper: a tinted dot plus a status suffix in the tooltip and aria-label, with external mutation outranking git status to match the expanded tab's strikethrough semantics.
  • Double-click rename — the tab root gained an onDoubleClick that opens the rename input when collapsed, restoring parity with SortableTab; the pre-existing preview-promotion branch is unchanged apart from a return.
  • Tests — collapsed-editor-tab-state.test.ts pins the projection for clean, modified, deleted/renamed, and dirty files; all 17 tab-bar tests pass locally.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Additive unsaved-changes reporting — getCollapsedEditorTabState no longer returns early on tabStatus, so a file that is both modified on disk and dirty in the buffer now reads README.md (M, unsaved) in the tooltip and aria-label instead of silently dropping the dirty state. External mutation still outranks git status, matching the expanded tab's strikethrough semantics.
  • Regression coverage — collapsed-editor-tab-state.test.ts pins both combinations (git status + unsaved, external mutation + unsaved) with exact assertions that would fail against the previous early-return logic.

The dotColor result is unchanged for every input combination — only the stateLabel/title text gains the appended unsaved segment — so the dot rendering cannot regress.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@gsustech
gsustech force-pushed the feat/pinned-tabs-icon-only branch from 777a1a1 to 28a9c77 Compare September 2, 2026 20:41
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Favicon consolidation — BrowserTab.tsx dropped its local BrowserTabFavicon in favor of the shared BrowserFavicon from @/components/browser-favicon (already used by TabBarCreateEntryRow and the worktree-jump palette), removing ~40 lines of duplicated image/fallback/retry logic. The collapsed-mode aria-label and Pin/label suppression are untouched.
  • Behavior parity verified — the shared component's normalized fallback and size-3 mr-1 shrink-0 … drop-shadow classes match the old local Globe exactly; its stricter URL validation (http(s)/data:image only) mirrors the filter already applied at the source in browser-page-webview-navigation-handlers.ts, so no real favicon is dropped. decoding="async" / loading="lazy" / fetchPriority="low" on the <img> are the same attributes the sibling surfaces already use.
  • Test rename — the favicon retry test renamed its trailing local from resetRender to retryRender, clarifying it against the adjacent reset test; no assertion changed.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@gsustech
gsustech force-pushed the feat/pinned-tabs-icon-only branch from 28a9c77 to 8d53ce5 Compare September 2, 2026 21:13

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Inlined collapse predicate — shouldCollapsePinnedTabToIcon deleted; the three-term boolean (isPinned && pinnedIconOnly && !isEditing/!isRenaming) inlined at the three call sites (BrowserTab, EditorFileTab, SortableTab).
  • Consolidated width constants — TAB_ICON_ONLY_CONTAINER_WIDTH_CLASSES and TAB_ICON_ONLY_ROOT_CLASSES moved from pinned-tab-icon-only.ts into tab-width-rules.ts alongside the other width constants.
  • Hoisted translate calls — duplicate translate() invocations in GeneralPane.tsx for the pinned-tabs-icon-only title and description extracted into local consts.
  • Test cleanup — dropped the source-regex census test and the dead shouldCollapsePinnedTabToIcon unit tests; the five-row-kind fixture test and layout-key test are preserved.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@gsustech
gsustech force-pushed the feat/pinned-tabs-icon-only branch 2 times, most recently from 7eb16cd to ac3768b Compare September 6, 2026 10:05

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found — this run is a rebase plus the #18099 conflict resolution, with no change to the collapse behavior reviewed previously.

Reviewed changes

  • Rebase onto current main — squashed to a single commit and rebased onto main (d19be48), which had diverged since the prior review.
  • #18099 conflict resolution — BrowserTab now hands the shared BrowserFavicon its loading prop (tab.loading && !tab.loadError && !isBlankBrowserTab(tab)) and drops the local bg-sky-500/80 loading dot. The condition is byte-identical to the removed dot; the favicon-to-spinner swap and blue tint are #18099's design, not this PR's, and size-3 is preserved on both so collapsed width is unaffected.
  • Absorbed main-side changes — the tab floor dropped min-w-[88px] → min-w-[72px] (#18871) in tab-width-rules.ts and the matching tooltip-test assertion; SortableTab gained the canSplitTerminal prop (defaulted false in tab-bar-item-surface.tsx); en.json picked up unrelated main-side strings.

The collapse predicate, collapsed-editor-tab-state.ts, double-click rename, and setting plumbing are byte-for-byte the prior-reviewed state.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@gsustech
gsustech force-pushed the feat/pinned-tabs-icon-only branch from ac3768b to 6109d75 Compare September 7, 2026 22:35

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Rebase onto current main — the PR was squashed and rebased onto 2265fce; the collapse logic, collapsed-editor-tab-state.ts, EditorFileTabLeadingIcon, TerminalTabCloseButton, and the setting plumbing are byte-identical to the previously approved state.
  • Dropped codex-accounts fixture edits — service-test-harness.ts and runtime-home-settings-test-fixtures.ts no longer hand-write pinnedTabsIconOnly: false. They were refactored on main to delegate through createCodexAccountSettings → createGlobalSettingsFixture → buildDefaultSettings, which already supplies the new default, so the per-fixture edit is obsolete. Verified the fixture chain still resolves the setting.
  • Absorbed main-side changes — editor rename-focus refactor (onCloseAutoFocus), terminal-tab-activity-status stale-title handling, and minimaxEndpoint/i18n additions landed via the rebase rather than as PR-authored edits.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@gsustech
gsustech force-pushed the feat/pinned-tabs-icon-only branch from 6109d75 to a4d1f8b Compare September 29, 2026 20:22
@gsustech
gsustech force-pushed the feat/pinned-tabs-icon-only branch from a4d1f8b to 6f3c0c5 Compare October 1, 2026 04:37
className: cn(TAB_CONTAINER_WIDTH_CLASSES, docks && 'sticky inset-x-0 z-10'),
className: cn(
iconOnly ? TAB_ICON_ONLY_CONTAINER_WIDTH_CLASSES : TAB_CONTAINER_WIDTH_CLASSES,
docks && 'sticky inset-x-0 z-10'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Docked tab covers other tabs

When someone manually scrolls an overflowing tab strip away from the active tab, this sticky slot stays at the edge above the other tabs. A tab that scrolls underneath it can still be visible but cannot be clicked. The automatic reveal path leaves room for the docked tab, but wheel, arrow-button, and scrollbar scrolling do not.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks — this one is pre-existing rather than introduced here. The docking condition (isActive && !isTabDragActive) and the sticky inset-x-0 z-10 classes are unchanged from main; they come from #24010. This PR only threads iconOnly into the width choice, which is why that line shows up in the diff.

If anything the collapse narrows the problem: a docked pinned tab in icon-only mode is 25px wide instead of 180–220px, so it covers much less of the strip. I would rather leave the docking behaviour to its own change than redesign it inside this one.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

Reviewed the delta since the prior Pullfrog review — a rebase onto current main plus one PR-authored refactor. All previous review threads are resolved.

  • Width logic moved into useTabStripSlotProps — the hook gains an optional iconOnly flag and now selects TAB_ICON_ONLY_CONTAINER_WIDTH_CLASSES itself, still composing the main-side dock classes (sticky inset-x-0 z-10) when the tab is active. BrowserTab, SortableTab, and EditorFileTab drop their outer-wrapper className conditional and the now-unused width imports, passing the flag to the hook instead. The same slot element still carries the width, so rendering is unchanged.
  • New hook test — use-tab-strip-slot-props.test.ts pins the default fixed width, the icon-only shrink-wrap (asserting the fixed w-[180px] is gone), and that an active icon-only tab still docks. Ran it locally: 3/3 pass.
  • Rebase absorption — the useTabStripSlotProps dock/sticky mechanism is a main-side addition the PR now extends; all five row kinds still receive pinnedTabsIconOnly. ClientHostedBrowserTab calls the hook without the flag, which is correct — it is a pinless in-memory row that can never be pinned.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@gsustech
gsustech force-pushed the feat/pinned-tabs-icon-only branch from 6f3c0c5 to 093d06b Compare October 11, 2026 23:56
A pinned tab keeps a full-width label it rarely needs — its icon already
identifies it. Since tabs no longer shrink below 144px, a strip of six tabs
overflows and the pinned ones scroll out of view. Behind a new General →
Navigation toggle (off by default), a pinned tab collapses to its glyph and
hands its width back: in a 1280px window six tabs go from 864px of content in
a 464px strip, with the pinned tabs scrolled off, to 512px that fits.

The collapse yields to any state the label would otherwise be the only
carrier of:

- An open rename editor takes the field back, and double-click still opens
  it on a collapsed editor tab (the root takes the gesture, since the label
  span that owns it is gone).
- The hover card still shows the full title, and the tab root gets an
  explicit aria-label since dnd-kit marks it role="button" and there is no
  longer any text to name it.
- An editor tab's git status, deleted/renamed state and unsaved changes come
  back as one tinted dot plus a suffix — "README.md (M, unsaved)". External
  mutation outranks git status, matching the expanded tab's strikethrough;
  unsaved is additive so one signal never shadows another.

Also fixes a pre-existing defect the collapse would amplify: a pinned tab
renders no close button, so the dirty dot's hover-hide left the slot blank
and dropped the tab's only unsaved-changes signal.

The width comes from the strip's existing useTabStripSlotProps hook, which
gains an iconOnly option rather than being overridden per tab, so an active
collapsed tab still docks. SortableTab and EditorFileTab both sit at the
400-line max-lines ceiling, so the terminal close button and the editor icon
logic move verbatim into their own modules rather than suppressing the rule.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gsustech
gsustech force-pushed the feat/pinned-tabs-icon-only branch from 093d06b to 23ade7c Compare November 2, 2026 22:41

This branch has not been deployed

No deployments
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.

2 participants