feat(web): switch orgs from the ⌘K palette with scope filters

Merged
RA
5h ago
+565-295

What is this contribution about?

Organizations move into the ⌘K palette, and the sidebar rail's search becomes a shortcut into it.

  • Rail footer: search and "new organization" are pinned below the scrolling org marks, so they stay in place however many orgs the rail draws. The search button opens the palette and shows the ⌘K shortcut in its tooltip.
  • Palette, organizations first: under "All" with an empty query, it lists up to 5 recent orgs other than the current one. Typing also searches the server, so orgs past Better Auth's first 500 memberships can be found.
  • Scope filters: All, Organizations, Projects, Chats & tasks, Connections, and Actions. Tab and Shift+Tab cycle them, and Backspace on an empty field returns to All. The filters do not take focus from the search field.
  • Fixed list height: the list is min(420px, 60vh) for every filter, so the palette does not change height when the filter changes. A filter with few results, such as Projects, leaves empty space below the list.
  • Key hints: the palette footer lists navigate, open, filter, and close.
  • Shared org switch: useTravelToOrg is used by both the rail and the palette. It brings a hidden org back onto the rail, records it as recent, and navigates to the org's home with a view transition.
  • Fallback outside an org: the palette is not mounted on pages such as /site-editor. There, the rail search opens an org-only dialog (OrgSearchDialog).
  • i18n: new strings in en and pt-br.

How did you verify your code works?

  • On apps/web/src/components/command-palette.tsx, tsc --noEmit, oxlint, and biome format pass.
  • In a local stack, I opened the palette and checked each of the six scope filters. The list measured 420px for all six.
  • Checked by hand: Tab cycles the filters, the filter buttons do not take focus from the search field, and typing "ni" shows organizations, a project, actions, and server-searched results together.
  • No automated tests are added or changed in this diff. Reviewers should cover the scenarios in How to Test.

Screenshots/Demonstration

UI change. Screenshots of the palette under All, Organizations, and Projects, and of the rail footer, are not attached yet. They need to be uploaded as GitHub attachments and embedded here before review.

How to Test

  1. Open the app with more than one org. Press ⌘K. Expected: the first section is Organizations, with up to 5 recent orgs other than the current one. The current org is not listed there.
  2. Press Tab. Expected: the filter moves to Organizations, all orgs are listed, and the current org is marked "current". The search placeholder changes to "Search organizations…".
  3. Press Tab through all six filters. Expected: the list stays 420px tall (or 60vh on short windows) on every filter.
  4. Click a filter chip while typing in the search field. Expected: focus stays in the search field.
  5. Type a term matching an org, a project, an action, and a thread. Expected: results from several sections appear together.
  6. Press Backspace on an empty search field while a filter is selected. Expected: the filter returns to All.
  7. In the sidebar rail, click the search button at the bottom. Expected: the palette opens. Press the "new organization" button. Expected: the create dialog opens.
  8. Pick an org from the palette. Expected: navigation to that org's home, and the org appears on the rail as a recent org.
  9. Open /site-editor, where the palette is not mounted. Click the rail search. Expected: the org-only dialog opens and lists all orgs.

Migration Notes

None. There are no schema or database changes. Existing rail localStorage preferences are read unchanged.

Review Checklist

  • PR title is clear and descriptive
  • Changes are tested and working
  • Documentation is updated (if needed)
  • No breaking changes

Summary by cubic

Organizations move into the ⌘K palette with scope filters, and the sidebar rail's search button now opens it instead of the old org-only dialog. Outside any org (e.g. /site-editor) the rail falls back to the org-only dialog because the palette isn't mounted.

Changes

  • Adds filter chips for Organizations, Projects, Chats & tasks, Connections, and Actions; Tab and Shift+Tab cycle them, Backspace on an empty field returns to All.
  • Under "All" with no query it lists up to 5 recent orgs other than the current one; typed search also queries the server, covering orgs past Better Auth's 500-membership limit.
  • Pins the rail's search and "new organization" buttons below the scrolling org marks, with the ⌘K shortcut shown in the search tooltip.
  • Extracts org switching (pinning, recents, navigation) into a shared useTravelToOrg hook used by both the rail and the palette.
  • Fixes the palette list height to min(420px, 60vh) across all scopes, so it stops changing when filters change.
  • Renames the rail's search button so its accessible name no longer collides with the connections page's search toggle, which could otherwise open the palette instead of connection search.

No schema, database, or localStorage changes.