Skip to content

feat(ui): add AccountButton controller#9185

Open
alexcarpenter wants to merge 1 commit into
carp/account-button-switcherfrom
carp/account-button-controller
Open

feat(ui): add AccountButton controller#9185
alexcarpenter wants to merge 1 commit into
carp/account-button-switcherfrom
carp/account-button-controller

Conversation

@alexcarpenter

@alexcarpenter alexcarpenter commented Jul 16, 2026

Copy link
Copy Markdown
Member

Summary

Stacked on #9184 (the presentational view). Adds the controller layer that connects AccountButton to live Clerk data, plus its tests (TDD).

  • useAccountButtonController() (account-button.controller.tsx) — a plain hook (no machine) returning a 'loading' | 'hidden' | 'ready' discriminated union. When ready it carries AccountButtonData & AccountButtonCallbacks 1:1 with the contract in account-button.view.tsx.
  • AccountButton (account-button.tsx) — the connected container. Owns popover open state and close-on-success (Option A: wraps each one-shot callback with .finally(close); manage/create navigations do not auto-close).
  • Renamed the view's all-in-one export AccountButtonAccountButtonView, reserving the bare AccountButton for the connected container. Updated the swingset story + mdx.

Data mapping (Clerk → contract)

  • activeAccount from useUser() + useSession(), name fallback first+last > username > email.
  • activeOrganizationId from useOrganization() (null = personal).
  • memberships/suggestions/invitations from useOrganizationList(organizationListParams) (reused from the legacy switcher).
  • hasOrganizations from userMemberships.count (never array length).
  • additionalAccounts from clerk.client.signedInSessions, excluding the active user's session.
  • membershipRequestCount only on the active-org row and only with org:sys_memberships:manage.
  • planLabel / upgradeable deferred (undefined).

Actions (navigation mode)

setActive for select/switch, signOut for sign-out, router.navigate(clerk.build*Url()) for manage/create, .accept() + revalidate() for invitations/suggestions.

Tests

12 controller tests (__tests__/account-button.controller.test.tsx) using the mosaic vi.mock('@clerk/shared/react') harness (copied from organization-profile-delete-section.controller.test.tsx). Written failing first, then implemented to green.

Notes / deviations from the handoff

Two points where the handoff wasn't directly implementable; resolved as follows:

  1. onSelectOrganization navigation. The handoff referenced displayConfig.afterSelectOrganizationUrl, but that field only exists as a component prop, not on the environment. Per decision, navigation goes through setActive({ organization, redirectUrl }) (matching the legacy switcher), using displayConfig.afterCreateOrganizationUrl as the redirect. Fully type-safe, no cast.
  2. Container loading render. The handoff described loading → <AccountButtonView status="loading" />, but the view requires activeAccount (which is only present when ready) and the view was out of scope to restructure. The container renders null while loading/hidden and the view only when ready. The controller still exposes status: 'loading' for future use.

Checklist

@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jul 16, 2026 9:56pm
swingset Ready Ready Preview, Comment Jul 16, 2026 9:56pm

Request Review

@changeset-bot

changeset-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ba22f92

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

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.

⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a04aed4-0d7c-4b2c-a512-143674d4ca8d

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant