WorkspaceSwitcher

WorkspaceSwitcher changes the current workspace and reports that selected state. Choose it over Dropdown when the choice is an account or tenant, not an action performed on the current context.

Examples

Controlled current workspace

Pass current with onChange when the application owns the active workspace. Without current, the first workspace is shown, which is suitable only when that default matches the surrounding state.

Create action

Providing onCreate adds an option after the workspace list. createLabel should name the next workflow, not repeat the current workspace's name. defaultOpen exists for visual demos; keep it out of ordinary examples and application flows.

When to use

Use WorkspaceSwitcher when a person selects the workspace, account or tenant that frames the page.

Reach for something else when:

  • The list contains commands for the current context — use Dropdown, which is a menu.
  • The choice is one of a few peer views — use Tabs.
  • The person needs to find a destination or command across the product — use CommandPalette.

Accessibility

  • The trigger has aria-haspopup="listbox", aria-expanded and aria-controls. Its popup is a role="listbox" labelled by the trigger, and each workspace is a role="option" with aria-selected; the create action is another option after an <hr role="presentation">.
  • Enter, Space and ArrowDown open the list at the first option; ArrowUp opens it at the last. In the list, ArrowDown and ArrowUp wrap, Home and End jump to the ends, Escape restores trigger focus, and Tab closes without preventing native sequential focus.
  • The component moves real DOM focus among options, unlike CommandPalette's active-descendant model. It also flips upward when there is no room below the trigger.
  • onChange receives both the selected id and workspace record. Update the surrounding application state there; current is how a controlled switcher announces that state on the next render.

Props

NameTypeRequiredDescription
workspacesWorkspace[]Workspaces available for selection.
currentstringIdentifier of the current workspace. Defaults to the first workspace.
onChange(id: string, workspace: Workspace) => voidCalled when a workspace is selected.
onCreate() => voidWhen present, shows a create-workspace action in the popover.
createLabelstringCreate-action label. Default `"Create workspace"`.
defaultOpenbooleanWhether the popover starts open. Useful for demos.

Plain HTML

The current workspace is the selected listbox option; creation remains an option, not a menu command:

html
<div class="lyra-wssw">
  <button
    class="lyra-wssw__trigger"
    type="button"
    aria-haspopup="listbox"
    aria-expanded="true"
    aria-controls="workspace-list"
  >
    <span class="lyra-wssw__id">
      <span class="lyra-wssw__name">Atlas</span>
      <span class="lyra-wssw__plan">Pro</span>
    </span>
  </button>
  <div class="lyra-wssw__pop" id="workspace-list" role="listbox" aria-labelledby="workspace-label">
    <span class="lyra-wssw__pop-label" id="workspace-label">Workspaces</span>
    <button class="lyra-wssw__item" type="button" role="option" aria-selected="true">
      <span class="lyra-wssw__id"
        ><span class="lyra-wssw__name">Atlas</span
        ><span class="lyra-wssw__meta">Pro · 12 members</span></span
      >
    </button>
    <button class="lyra-wssw__item" type="button" role="option" aria-selected="false">
      <span class="lyra-wssw__id"><span class="lyra-wssw__name">Northstar Studio</span></span>
    </button>
    <hr class="lyra-wssw__sep" role="presentation" />
    <button class="lyra-wssw__item" type="button" role="option" aria-selected="false">
      <span class="lyra-wssw__plus">+</span
      ><span class="lyra-wssw__create-label">Create workspace</span>
    </button>
  </div>
</div>