Skip to content

feat(ui): redesign org/project switcher with searchable flyouts#2638

Merged
charlesvien merged 3 commits into
mainfrom
posthog-code/org-project-switcher-flyouts
Jun 12, 2026
Merged

feat(ui): redesign org/project switcher with searchable flyouts#2638
charlesvien merged 3 commits into
mainfrom
posthog-code/org-project-switcher-flyouts

Conversation

@annikaschmid

Copy link
Copy Markdown
Contributor

Problem

The account popover's "Change project" item opened a modal dialog, and there was no way to switch organizations from the app at all — switching to a project in another org was impossible. The main PostHog web app already solves this with separate Project and Organization sections with flyout pickers.

Changes

Replaces the single dialog with the web app's switcher pattern inside the lower-left account popover:

  • Project and Organization sections, each with a chevron flyout and a create action (/organization/create-project, /create-organization) that opens the cloud app externally (with ArrowSquareOut indicators, also added to the Discord link)
  • Flyouts are searchable (quill Autocomplete inline) with the active item pinned first and a left-gutter checkmark, the rest locale-sorted to match web ordering
  • Org rows show the saved org logo (/uploaded_media/... via the existing getPostHogUrl helper) with a deterministic colored-initial avatar fallback, like web
  • Org switching uses the existing useSwitchOrgMutation; project switching stays on useSelectProjectMutation
  • A local PinnedSubContent pins the flyouts to open downward (collisionAvoidance: { align: "none" }) with a fixed list height, so filtering never resizes or flips the popup; quill's DropdownMenuSubContent doesn't forward collisionAvoidance, so this mirrors its markup with a TODO to upstream the prop
  • A keyboard fence stops the menu's typeahead from swallowing keystrokes meant for the search input (Escape still closes)

Screenshots to follow in a comment.

How did you test this?

  • Manually in the desktop app (pnpm dev:code): switched projects and orgs, searched both flyouts, verified active-first ordering, org logos/initials, external create links, and stable popup positioning while filtering
  • Multi-agent adversarial review of the full diff (7 finder angles, per-finding verification); the three confirmed cleanups (reuse getPostHogUrl, TODO on the quill-internals fork, memoized item arrays/sort) are included
  • biome check clean; tsc reports no errors in the changed file (the repo-wide pnpm typecheck failures in host-router/useWorkspace.ts are pre-existing and untouched by this PR)

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Created with PostHog Code

Replace the single "Change project" dialog in the account popover with
the web app's switcher pattern: separate Project and Organization
sections, each with a chevron flyout listing the available options and
a create action that opens the cloud app externally.

- Searchable flyouts (Autocomplete) with the active item pinned first
  and the rest locale-sorted, matching web ordering
- Org rows show the saved logo from /uploaded_media, falling back to a
  deterministic colored initial avatar
- Flyouts pin align="start" via a local PinnedSubContent so filtering
  never makes the popup jump (quill's SubContent doesn't forward
  collisionAvoidance; TODO to upstream)
- External-link indicators on create actions and Discord

Generated-By: PostHog Code
Task-Id: d746f1ce-5792-4a1c-87ce-cd27cb95b17a
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

React Doctor could not complete this scan.

No React dependency found in /tmp/react-doctor-baseline-NPqusr/package.json. Add "react" to dependencies (or peerDependencies) and re-run.

Reviewed by React Doctor for commit 4a6a63e.

@annikaschmid

Copy link
Copy Markdown
Contributor Author

Screenshot of the changes:

CleanShot 2026-06-12 at 13 41 12

@annikaschmid annikaschmid requested a review from a team June 12, 2026 12:44
@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/ui/src/features/sidebar/components/ProjectSwitcher.tsx:417-420
**Conflicting Tailwind width utilities in `PinnedSubContent`**

The component hardcodes `w-auto` in its class string, then appends the caller's `className` (always `"w-64 p-0"`) after it. This produces `...w-auto w-64 p-0` on the same element. When two Tailwind utilities targeting the same CSS property appear in the same class list, the winner is determined by which rule appears later in the compiled stylesheet — not by the order in the HTML attribute. This is an implementation detail of Tailwind's JIT compilation and is not guaranteed. Since `cn` is already available in the quill package (used in `SidebarItem.tsx` in this same directory), `cn()` would resolve the conflict reliably.

```suggestion
        <BaseMenu.Popup
          data-slot="dropdown-menu-sub-content"
          className={`quill-menu__content quill-menu__sub-content ${className ?? ""}`}
        >
```

Reviews (1): Last reviewed commit: "Merge branch 'main' into posthog-code/or..." | Re-trigger Greptile

Comment on lines +417 to 420
<BaseMenu.Popup
data-slot="dropdown-menu-sub-content"
className={`quill-menu__content quill-menu__sub-content w-auto ${className ?? ""}`}
>

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.

P2 Conflicting Tailwind width utilities in PinnedSubContent

The component hardcodes w-auto in its class string, then appends the caller's className (always "w-64 p-0") after it. This produces ...w-auto w-64 p-0 on the same element. When two Tailwind utilities targeting the same CSS property appear in the same class list, the winner is determined by which rule appears later in the compiled stylesheet — not by the order in the HTML attribute. This is an implementation detail of Tailwind's JIT compilation and is not guaranteed. Since cn is already available in the quill package (used in SidebarItem.tsx in this same directory), cn() would resolve the conflict reliably.

Suggested change
<BaseMenu.Popup
data-slot="dropdown-menu-sub-content"
className={`quill-menu__content quill-menu__sub-content w-auto ${className ?? ""}`}
>
<BaseMenu.Popup
data-slot="dropdown-menu-sub-content"
className={`quill-menu__content quill-menu__sub-content ${className ?? ""}`}
>
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/features/sidebar/components/ProjectSwitcher.tsx
Line: 417-420

Comment:
**Conflicting Tailwind width utilities in `PinnedSubContent`**

The component hardcodes `w-auto` in its class string, then appends the caller's `className` (always `"w-64 p-0"`) after it. This produces `...w-auto w-64 p-0` on the same element. When two Tailwind utilities targeting the same CSS property appear in the same class list, the winner is determined by which rule appears later in the compiled stylesheet — not by the order in the HTML attribute. This is an implementation detail of Tailwind's JIT compilation and is not guaranteed. Since `cn` is already available in the quill package (used in `SidebarItem.tsx` in this same directory), `cn()` would resolve the conflict reliably.

```suggestion
        <BaseMenu.Popup
          data-slot="dropdown-menu-sub-content"
          className={`quill-menu__content quill-menu__sub-content ${className ?? ""}`}
        >
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@annikaschmid

Copy link
Copy Markdown
Contributor Author

For reviewers: I don’t feel strongly about the “open in browser” icons, it’s a bit much.

@charlesvien charlesvien left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is much better, ty for this!

@charlesvien charlesvien merged commit 191be14 into main Jun 12, 2026
23 checks passed
@charlesvien charlesvien deleted the posthog-code/org-project-switcher-flyouts branch June 12, 2026 18:36
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