Skip to content

feat(desktop): add configurable workspace navigation style (top-bar vs sidebar)#2

Closed
andreasasprou wants to merge 1 commit intofeat/desktop-workbench-review-modefrom
workspace-sidebar
Closed

feat(desktop): add configurable workspace navigation style (top-bar vs sidebar)#2
andreasasprou wants to merge 1 commit intofeat/desktop-workbench-review-modefrom
workspace-sidebar

Conversation

@andreasasprou
Copy link
Copy Markdown
Owner

Summary

This PR adds a configurable workspace navigation style setting that lets users choose between displaying workspaces as horizontal tabs in the TopBar (current behavior) or in a dedicated left sidebar (Linear/GitHub Desktop style).

Details

Architecture

  • Persisted setting: Navigation style stored in SQLite via settings.navigationStyle column
  • Shared hook pattern: useWorkspaceShortcuts extracts keyboard shortcuts (⌘1-9) and auto-create logic shared between both modes
  • Zustand state: Sidebar width, collapsed projects, and open state persisted with zustand/persist
  • Lazy data loading: GitHub PR status loaded on hover to avoid N+1 queries

How it works

  1. User selects "Top bar" or "Sidebar" in Settings → Behavior
  2. MainScreen queries the setting and conditionally renders:
    • Top bar mode: WorkspacesTabs in the header (current behavior)
    • Sidebar mode: ResizableWorkspaceSidebar on the left + simplified TopBar
  3. Both modes share the same keyboard shortcuts via useWorkspaceShortcuts hook

Key decisions

Decision Choice Rationale
Sidebar type New dedicated sidebar Avoids complexity of reusing ModeCarousel
State storage Zustand + localStorage Matches existing sidebar patterns
Collapsed projects string[] not Set<string> JSON serialization for persist middleware
Diff stats source getGitHubStatus on hover Avoids N+1 queries, lazy load pattern
TopBar in sidebar mode Show project/workspace name Maintains context without tabs

New Components

WorkspaceSidebar

  • WorkspaceSidebar.tsx - Main sidebar component
  • WorkspaceSidebarHeader.tsx - "Workspaces" title header
  • WorkspaceSidebarFooter.tsx - "Add project" button
  • ResizableWorkspaceSidebar.tsx - Wrapper with resize handle

ProjectSection

  • ProjectSection.tsx - Collapsible project group with workspaces
  • ProjectHeader.tsx - Project name, color dot, collapse toggle

WorkspaceListItem

  • WorkspaceListItem.tsx - Individual workspace row with lazy-loaded PR data
  • WorkspaceStatusBadge.tsx - PR status badge (open/merged/closed/draft)
  • WorkspaceDiffStats.tsx - Additions/deletions display

Shared

  • useWorkspaceShortcuts.ts - Shared hook for ⌘1-9 shortcuts and auto-create logic
  • workspace-sidebar-state.ts - Zustand store for sidebar UI state

Keyboard Shortcuts

Shortcut Action
⌘⇧B Toggle workspace sidebar (sidebar mode only)
⌘B Toggle files sidebar (renamed from "Toggle sidebar")
⌘1-9 Switch to workspace N (works in both modes)
⌘← / ⌘→ Previous/next workspace (works in both modes)

Manual Test Checklist

Navigation Style Setting

  • Setting persists across app restarts
  • Changing setting immediately switches layout
  • Default is "Top bar" for new installs

Sidebar Mode

  • Sidebar renders with correct width (default 280px)
  • Sidebar is resizable between 220-400px
  • Resize persists across restarts
  • ⌘⇧B toggles sidebar visibility
  • Projects are collapsible
  • Collapsed state persists
  • Active workspace has left border indicator
  • Hover shows keyboard shortcut (⌘1-9)
  • PR status/diff stats load on hover (worktree workspaces)
  • "Add project" button works

Top Bar Mode

  • Existing tab behavior unchanged
  • No workspace sidebar visible
  • ⌘⇧B does nothing (correct)

Keyboard Shortcuts (Both Modes)

  • ⌘1-9 switches to correct workspace
  • ⌘← / ⌘→ navigates workspaces
  • Auto-create main workspace still works

Files Changed

New Files

  • apps/desktop/src/renderer/hooks/useWorkspaceShortcuts.ts
  • apps/desktop/src/renderer/stores/workspace-sidebar-state.ts
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceSidebarControl.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/* (10 files)
  • packages/local-db/drizzle/0005_add_navigation_style.sql

Modified Files

  • packages/local-db/src/schema/schema.ts — Added NavigationStyle type and column
  • apps/desktop/src/lib/trpc/routers/settings/index.ts — Added get/set navigation style routes
  • apps/desktop/src/renderer/screens/main/components/SettingsView/BehaviorSettings.tsx — Added dropdown
  • apps/desktop/src/renderer/screens/main/components/TopBar/index.tsx — Conditional rendering
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/index.tsx — Refactored to use shared hook
  • apps/desktop/src/renderer/screens/main/index.tsx — Wire up sidebar and navigation style
  • apps/desktop/src/shared/constants.ts — Added DEFAULT_NAVIGATION_STYLE
  • apps/desktop/src/shared/hotkeys.ts — Added TOGGLE_WORKSPACE_SIDEBAR, renamed TOGGLE_SIDEBAR

@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 31, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
superset-api Error Error Dec 31, 2025 7:40am
superset-web Error Error Dec 31, 2025 7:40am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 31, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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

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

…s sidebar)

Add a setting to let users choose between displaying workspaces as
horizontal tabs in the TopBar (current behavior) or in a dedicated left
sidebar (new feature, similar to Linear/GitHub Desktop).

Key changes:
- Add navigationStyle column to settings table (migration 0005)
- Add navigation style dropdown in Behavior Settings
- Create WorkspaceSidebar component with collapsible project sections
- Create shared useWorkspaceShortcuts hook (⌘1-9 shortcuts, auto-create)
- Update TopBar to conditionally render based on navigation style
- Add ⌘⇧B hotkey to toggle workspace sidebar

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +64 to +66
if (!isOpen) {
return null;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep workspace hotkeys active when sidebar is hidden

When isOpen is false this component returns null, which unmounts WorkspaceSidebar. In sidebar mode that’s the only place useWorkspaceShortcuts registers the ⌘1–9 and ⌘←/→ handlers, so toggling the workspace sidebar closed disables workspace switching shortcuts (and the auto-create logic) even though the feature is meant to work in both modes. Consider moving the shortcut hook to a parent that stays mounted or keeping it active even when the sidebar is hidden.

Useful? React with 👍 / 👎.

andreasasprou pushed a commit that referenced this pull request Jan 8, 2026
* WIP

* WIP

* WIP - tried to restore code

* WIP - tried to restore code

* WIP - tried to restore code

* WIP - tried to restore code

* chore: update bun.lock after rebase

Regenerated lockfile after rebasing onto latest origin/main.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* WIP

* fix(desktop): use auth client instead of server to avoid database dependency

Split @superset/auth package exports to separate server and client.
Desktop app now imports from @superset/auth/client which doesn't
require DATABASE_URL, fixing startup crash in production builds.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(auth): use Better Auth client API and split server/client exports

- Updated desktop app to use correct Better Auth client API methods:
  - authClient.getSession() instead of auth.api.getSession()
  - authClient.organization.setActive() instead of auth.api.setActiveOrganization()
- Renamed packages/auth/src/index.ts to server.ts
- Changed package exports from "." to "./server" for clarity
- Removed unnecessary createAuthApiClient factory function
- Updated all imports from @superset/auth to @superset/auth/server

This fixes the typecheck errors and database dependency issue in the
desktop app by properly separating server-side auth (requires DB) from
client-side auth (HTTP API calls only).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* chore: add BETTER_AUTH_SECRET to app env.ts files for tree-shaking

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
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