Account Switch Guard

Names which account an action runs as, and notices when another tab switched accounts, so nobody posts from the wrong one.

StopsPosted from the wrong account

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/account-switch-guard.json

The files land in your project. They're yours to edit.

What it catches

  • An account switch made in another tab of the same browser (BroadcastChannel, with a storage-event fallback)
  • The page's account differing from the most recently active account
  • Ambiguous action buttons, by naming the acting account on the button

Props

AccountSwitchGuard props
PropTypeDefault
accounts* (required)

Every account signed in on this browser, most recently used first.

GuardAccount[]—
pageAccountId* (required)

The account this page was loaded as. Its data is what the user is looking at.

string—
activeAccountId

Controlled active account. Omit to follow `announceActiveAccount` across tabs.

string—
channel

Channel shared with `announceActiveAccount`.

stringDEFAULT_CHANNEL
onAction* (required)

Runs the action. Receives the page's account id: scope the request to it, not to the session cookie.

(accountId: string) => void | Promise<void>—
onSwitchPage

Reloads this page as the newly active account. Hidden when omitted.

(accountId: string) => void—
identityText

Identity line. `{account}` and `{other}` are filled in.

string"Posting as {account}"
notText

Shown after the identity, naming the account most easily confused with it.

string"not {other}"
switchedText

Warning when another tab switched accounts. `{active}` and `{account}` are filled in.

string"You switched to {active} in another tab. This page still…
actionLabel

Button text for the action when the accounts match.

string"Post"
explicitActionLabel

Action label while the accounts disagree, so the click names its account.

string"Post as {account}"
switchPageLabel

Text for the button that switches the page to the newly active account.

string"Open as {active}"

* required. Also accepts the native props of <div> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Mismatch notice sits in an aria-live="polite" region
  • The action button is described by the identity line via aria-describedby
  • The highlight animation is skipped when prefers-reduced-motion is set
  • Avatar colour is decorative (aria-hidden); the account is always named in text

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

This is a UX guard rail. Enforce on the server: The server must act as the account the session actually authenticates, and reject requests whose stated account differs from it.

  • Only sees switches reported through its own channel; switches made elsewhere (another browser, device or app) are invisible
  • It does not change which session the request is sent with; your onAction decides that

What it stops

Posted from the wrong account

Also known as

account switcher · multiple accounts · posting as · brand account · google account · workspace · profile switch · multi-login

Field type

Dependencies

Pairs well with