Xzero UI
Pro library

Team switcherPro

A workspace switcher like Linear, Vercel or Slack. The trigger shows the current workspace's logo and plan. The menu has search, your role in each workspace and a Cmd+1 to 9 shortcut for each, and lets you create or join a workspace inline. A highlight glides between rows, and switching crossfades the trigger through a short loading state.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/team-switcher
Live · keyboard ready

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/team-switcher

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { useState } from "react";
import { TeamSwitcher } from "@/components/xzero/team-switcher/team-switcher";

const workspaces = [
  { id: "acme", name: "Acme", plan: "Enterprise", members: 214, role: "Admin" },
  { id: "acme-labs", name: "Acme Labs", plan: "Pro", members: 12, role: "Owner" },
];

export function AppHeader() {
  const [workspaceId, setWorkspaceId] = useState("acme");
  return (
    <TeamSwitcher
      workspaces={workspaces}
      value={workspaceId}
      onValueChange={setWorkspaceId}
      onSwitch={(workspace, signal) => api.session.switch(workspace.id, { signal })}
      onCreateWorkspace={async (name, signal) => api.workspaces.create({ name }, { signal })}
      onJoinWorkspace={async (invite, signal) => api.invites.accept(invite, { signal })}
    />
  );
}

API reference

TeamSwitcher

A workspace switcher: a trigger with the current workspace's logo and plan, and a menu with search, roles, Cmd/Ctrl+number shortcuts, and inline create and join views. With no props it switches between six sample workspaces and simulates every action.

PropTypeDefaultDescription
workspacesWorkspace[]sampleWorkspacesThe workspaces you belong to: { id, name, plan?, members?, role?, logo?, tile?: { background, color? } }. The first nine get Cmd/Ctrl+1 to 9. Size a custom logo in em; the tile sets font-size to its own size.
valuestring–The active workspace id. Pair with onValueChange.
defaultValuestringfirst workspaceThe starting workspace when uncontrolled.
onValueChange(id: string, workspace: Workspace) => void–Called once a switch has finished loading.
onSwitch(workspace: Workspace, signal: AbortSignal) => Promise<void>–Loads the workspace. The trigger crossfades to the new workspace with a switching state until it resolves; a rejection reverts and shows the error's message. A newer switch aborts the older one. Simulated (650ms) when left out.
onCreateWorkspace(name: string, signal: AbortSignal) => Promise<Workspace | void>–Creates a workspace. Return it to add it and switch to it; throw an Error to show its message under the field. Simulated when left out.
onJoinWorkspace(invite: string, signal: AbortSignal) => Promise<Workspace | void>–Joins from an invite link or code. Return the workspace to switch to it; throw an Error to show its message. Simulated when left out, with sample invites for Resend and Notion.
openboolean–Controls the menu. Pair with onOpenChange.
defaultOpenbooleanfalseStarts with the menu open, without moving focus.
onOpenChange(open: boolean) => void–Called when the menu opens or closes.
globalShortcutsbooleanfalseListens for Cmd/Ctrl+1 to 9 anywhere on the page. Off, the shortcuts work while focus is inside the switcher.
simulatedDelaynumber650How long the simulated switch takes, in milliseconds.
disabledbooleanfalseDisables the trigger.
classNamestring–Class on the root. The root is up to 360px wide and fills narrower containers.

WorkspaceTile

The workspace avatar on its own: the brand mark on its brand color, or the first letter of the name.

PropTypeDefaultDescription
workspace (required)Workspace–The workspace to draw.
sizenumber28Tile size in pixels. The corner radius and mark scale with it.

Keyboard interactions

KeysAction
Enter / Space / ArrowDownOn the trigger, opens the menu and moves focus to the search field.
TypeFilters workspaces by name, plan or role. With no match, Enter opens Create workspace with the name filled in.
ArrowDown / ArrowUpMoves the highlight through workspaces and actions, wrapping at the ends.
Home / EndJumps to the first or last item when the search is empty.
EnterSwitches to the highlighted workspace, or opens Create workspace or Join with invite.
Cmd/Ctrl+1 to 9Switches to the workspace at that place in the list. Works while focus is in the switcher, or anywhere with globalShortcuts.
EscapeGoes back from create or join, then clears the search, then closes and returns focus to the trigger.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Also in ai

Guidance for AI tools

Team switcher: A workspace switcher like Linear, Vercel or Slack. The trigger shows the current workspace's logo and plan. The menu has search, your role in each workspace and a Cmd+1 to 9 shortcut for each, and lets you create or join a workspace inline. A highlight glides between rows, and switching crossfades the trigger through a short loading state. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components