Skip to content

Components · Identity

WorkspaceSwitcher

Switch between the workspaces a person belongs to, with search and Create workspace.

@rookcom/monarch-react/shellComponent

Switch, create and manage

Usage examples

Collapsed, and nothing chosen yet

Purpose

Every Rook app lets a person move between their workspaces from the rail. One shared control names its trigger, marks the current workspace for screen readers and supports search.

Use when

  • The rail’s workspaceSwitcher slot, or the top of a settings sidebar.

Avoid when

  • Choosing a Space inside the workspace: use SpaceSwitcher.
  • Picking a workspace as a form value (inviting to a workspace): use EntityPicker in a Field.

Design principles

  • The app does the switch: onValueChange gets the id and the app navigates (and may keep the sub-page).
  • Square avatars for workspaces (round ones are people), with initials when there is no logo.
  • The current workspace is aria-selected, never marked by a coloured dot alone.
  • Search matches names, handles and hidden keywords such as old names.

API reference

import { WorkspaceSwitcher } from '@rookcom/monarch-react/shell';
ExportKindRenderingRoot class
WorkspaceSwitchercomponentclient.mn-workspace-switcher

Forwards its ref to the trigger button. Built on EntityPicker and Avatar from @rookcom/monarch-react.

WorkspaceOption is { id, name, handle?, avatarUrl?, keywords? }.

Generated from the TypeScript declarations of packages/react/src/components/identity/workspace-switcher.

Properties

Controlled with value + onValueChange, or uncontrolled with defaultValue. There is no "none" choice.

onCreate or createHref adds "Create workspace"; manageHref adds "All workspaces" (new tab unless manageExternal={false}).

WorkspaceSwitcher

Switches between the workspaces a person belongs to: an avatar trigger (name and handle when there is room), a searchable popover with the current workspace checked, and Create / All workspaces actions. Keyboard: the listbox model of EntityPicker (arrows, Home/End, type to search, Enter, Escape returns focus). The app supplies the workspaces and does the switch.

PropTypeDescription
workspaces requiredWorkspaceOption[]The workspaces this person belongs to.
align"center" | "start" | "end"
classNamestring
collapsedbooleanAvatar-only trigger for a collapsed rail; the name moves into a tooltip.
createHrefstring…or a link.
defaultValuestring | null
loadingboolean
manageExternalbooleanOpen `manageHref` in a new tab. Default true.
manageHrefstring"All workspaces" link (usually Rook ID).
messagesPartial<WorkspaceSwitcherMessages>
onCreate(() => void)"Create workspace": an action (the popover closes first)…
onOpenChange((open: boolean) => void)
onValueChange((workspaceId: string) => void)Called with the chosen workspace id. The app navigates (and keeps the sub-page if it wants).
openboolean
valuestring | nullThe current workspace id (controlled).

Variants

PropValuesDescription
collapsed'false''true'Avatar-only trigger with the name in a tooltip, for the 48px rail.

States

StateExposed asBehaviour
Current workspacearia-selected="true"Checked in the list; the trigger shows its name and @handle.
Nothing chosen–The trigger reads "Workspace: Choose a workspace" with a neutral icon.
Loading–The list says "Loading workspaces…".
Openaria-expanded="true"On the trigger.

Interaction behaviour

  • Opening moves focus to the search box; choosing closes the popover and returns focus to the trigger.
  • Choosing the current workspace again does nothing.
  • "Create workspace" closes the popover first, then runs onCreate (open your dialog there).

Keyboard support

KeysAction
Enter / Space / ↓Open from the trigger.
↓ / ↑ / Home / EndMove through the workspaces.
TypingFilter by name, handle or keyword.
EnterSwitch to the highlighted workspace.
EscapeClose and return focus to the trigger.

Accessibility

Role
button opening a dialog with a search combobox and a listbox
Accessible name
The trigger is named by its text, "Workspace: <name> @handle" (messages.label is visually hidden), also when collapsed to an avatar.
  • Fixes the audited gaps: a collapsed trigger without a name and an active item shown by colour only.
  • Avatars are decorative; the option label and @handle name each workspace.
  • The All workspaces link announces the new tab.

Responsive behaviour

  • The expanded trigger fills its container and truncates long names; the popover never exceeds the screen width.

Theme support

  • Tokens only; inside RookRail the trigger uses the accent panel colours.
  • Transitions are removed under reduced motion.

Do and don't

Do

  • Keep the sub-page when switching if the page exists in the other workspace.
  • Pass workspace logos as avatarUrl; initials are the fallback.

Don't

  • Do not list workspaces the person cannot open.
  • Do not put Space choices in this list.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsAvatar, EntityPicker

Testing coverage

  • Trigger named with the current workspace and its handle.
  • List with the current one selected; switching calls onValueChange and returns focus.
  • Keyboard search over names, handles and keywords; re-choosing the current one is ignored; controlled mode.
  • Create workspace (action and link) and All workspaces; placeholder and empty message; collapsed tooltip.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery/workspace-switcher; Cross-browser axe: /components/workspace-switcher

Tests: packages/react/src/components/identity/workspace-switcher