Skip to content

Keep compact file explorer visible while open#1661

Open
boudra wants to merge 3 commits into
mainfrom
right-sidebar-state-drift
Open

Keep compact file explorer visible while open#1661
boudra wants to merge 3 commits into
mainfrom
right-sidebar-state-drift

Conversation

@boudra

@boudra boudra commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Linked issue

N/A

Type of change

  • Bug fix
  • New feature (with prior issue + design alignment)
  • Refactor / code improvement
  • Docs

What does this PR do

This keeps the compact right file explorer owned by the app shell while it is open, instead of letting an individual workspace screen own the visual shell.

The left sidebar already used that app-level ownership shape. This applies the same compact/mobile invariant to the right side: when the compact panel state says the file explorer is open, the shell is mounted from app chrome and derives its content from the active workspace. Desktop right sidebar behavior stays in WorkspaceScreen.

How did you verify it

  • npm run format
  • npx vitest run packages/app/src/components/compact-explorer-sidebar-host-state.test.ts --bail=1
  • npm run typecheck
  • npm run lint
  • Pre-commit hook reran lint, format check, and typecheck successfully.

Risk surface before merge: this touches compact Expo UI behavior and gesture ownership, so a mobile smoke test should open/close the right explorer from the header and right-edge gesture while a workspace is busy/loading. Desktop right sidebar should still resize and close normally.

Checklist

  • One focused change. Unrelated cleanups split out.
  • npm run typecheck passes
  • npm run lint passes
  • npm run format ran (Biome)
  • UI changes include screenshots or video for every affected platform
  • Tests added or updated where it made sense

@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR lifts compact (mobile/Expo) right-side file explorer ownership from individual workspace screens to the app shell (_layout.tsx), applying the same app-level ownership pattern the left sidebar already used. The ExplorerSidebarAnimationProvider and gesture surface now live at the app-chrome layer instead of inside each WorkspaceScreenContent mount.

  • New CompactExplorerSidebarHost (compact-explorer-sidebar-host.tsx + compact-explorer-sidebar-host-state.ts) owns the compact sidebar at the app shell level, retaining the last-known workspace model while the explorer is open so it stays visible during workspace reloads.
  • explorer-sidebar.tsx is split into a CompactExplorerSidebar (mobile overlay, always-true close gesture) and the existing ExplorerSidebar (desktop fixed-width with resize handle), sharing state through the new useExplorerSidebarSharedState helper.
  • diff-pane.tsx / surface.tsx thread a textMetricsStyle prop through all diff row and gutter components so font size, line height, and font family are applied consistently; the E2E test for diff row alignment is hardened with expect.poll and a localStorage guard to eliminate the flakiness those changes previously exposed.

Confidence Score: 5/5

Safe to merge pending a mobile smoke test of open/close from the header and right-edge gesture across workspace states (loading, busy, idle).

The ownership transfer is a clean lift-and-shift following the exact pattern used by the left sidebar. The new CompactExplorerSidebarHost correctly addresses the previous double-hook-call concern with a single call site. The retainedModelRef pattern for workspace-reload stability is correct and well-tested by the four pure-function unit tests. The explorer-sidebar.tsx split removes all isMobile conditionals from the combined component without leaving dead branches. Desktop resize, close, and animation paths are unchanged.

No files require special attention, but the compact explorer gesture ownership change warrants a manual mobile smoke test before shipping.

Important Files Changed

Filename Overview
packages/app/src/components/compact-explorer-sidebar-host.tsx New component hosting the compact sidebar at app-shell level; single hook call, correct retainedModelRef pattern for workspace-reload stability, gesture surface correctly gated on model?.workspaceRoot.
packages/app/src/components/compact-explorer-sidebar-host-state.ts Pure resolver for CompactExplorerSidebarHostModel; correctly retains previous root/isGit during workspace reload, switches ownership on workspace change, returns null with no selection.
packages/app/src/app/_layout.tsx App shell now wraps compact children with ExplorerSidebarAnimationProvider + CompactExplorerSidebarHost; desktop path is unchanged.
packages/app/src/components/explorer-sidebar.tsx Cleanly split into CompactExplorerSidebar (mobile overlay, always-enabled close gesture) and ExplorerSidebar (desktop resize handle). Shared tab state extracted into useExplorerSidebarSharedState.
packages/app/src/screens/workspace/workspace-screen.tsx Mobile gesture surface, openExplorerForWorkspace, ExplorerSidebarAnimationProvider, and the isMobile branch in handleOpenFileFromExplorer all removed cleanly. shouldShowWorkspaceExplorerSidebar correctly gates on !isMobile.
packages/app/src/git/diff-pane.tsx textMetricsStyle threaded through all diff row and gutter leaf components; useDiffRowMetricsStyle helper correctly memoizes minHeight from lineHeight.
packages/app/e2e/diff-row-alignment.spec.ts expectDiffCodeFontSize migrated to expect.poll(); useCodeFont guarded with localStorage presence check; expectStoredCodeFontSize added as a synchronisation barrier.

Reviews (3): Last reviewed commit: "fix(app): refresh diff row metrics after..." | Re-trigger Greptile

Comment thread packages/app/src/components/compact-explorer-sidebar-host.tsx
Comment thread packages/app/src/screens/workspace/workspace-screen.tsx Outdated
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