Skip to content
buttery

v1.0.0

Source on GitHub

Version 1.0.0

AccountMenu

The workspace switcher at the top of a sidebar and its menu: the workspace, switching to another, the person signed in, and signing out.

import { AccountMenu } from "@butteryui/react";

Demo

When to use it

Use it for

  • The switcher slot of a Sidebar
  • An app where people belong to more than one workspace or team

Not for

  • Actions on a record: use a Menu
  • A plain profile link: use a link

Examples

Opened from a note

The menu opened from a note on the page, with open and onOpenChange kept in useState.

Harbor Beans added you to their workspace

Single workspace

One workspace and nothing to switch to: just the person and Sign out.

Signed in as Tomas Reyes

Workspace switcher

A sidebar's workspace switcher: settings, switching, the person signed in and Sign out.

Signed in to Northside Roasters

Variants and states

Workspace switcher

Open it for the workspace, Switch workspace (ArrowRight or a 40ms rest), the person and Sign out.

Props

AccountMenu

PropTypeDefaultDescription
workspace

required

stringThe workspace's name, on the trigger and at the top of the menu.
captionReactNodeA line under the name at the top of the menu, such as the plan or how many people are in it.
labelstring"Workspace"Names the trigger for screen readers, before the workspace's name. Defaults to "Workspace".
openbooleanWhether the menu is open. Pair with onOpenChange to control it.
defaultOpenbooleanfalseWhether it starts open when uncontrolled. Defaults to false.
onOpenChange((open: boolean) => void)Called when the menu opens or closes.
childrenReactNodeThe menu's items: Menu.Items, AccountMenu.Workspaces, AccountMenu.User, separators and submenus.

It also takes Omit<ComponentPropsWithRef<"button">, "children">.

AccountMenu.User

PropTypeDefaultDescription
name

required

stringThe person's name.
picturestringTheir picture's address; their initials show without one.
onSelect(() => void)Called when the row is chosen, such as to open their profile.
iconComponentType<IconComponentProps>An icon at the row's end for what choosing it does, such as a gear.

AccountMenu.Workspaces

PropTypeDefaultDescription
workspaces

required

readonly AccountWorkspace[]Every workspace the person is in.
current

required

stringThe id of the workspace in use; it shows a check.
onSwitch

required

(id: string) => voidCalled with the id of the workspace chosen.
onCreate(() => void)Called by "New workspace". Leave it out to hide the item.
onManage(() => void)Called by "Manage workspaces". Leave it out to hide the item.
labelsPartial<Readonly<{ switchWorkspace: string; newWorkspace: string; manageWorkspaces: string; }>>The words it uses, for other languages.

AccountWorkspace

One workspace someone can switch to.

FieldTypeDefaultDescription
id

required

stringWhat current and onSwitch carry.
name

required

stringIts name, with its initials on a tile.

Accessibility

The trigger is a button named "Workspace" and the workspace's name, with aria-haspopup and aria-expanded. The menu's items are menuitems; workspaces are menuitemradios with the current one checked. ArrowRight opens Switch workspace.

KeysWhat they do
Enter, Space or ArrowDownOpens the menu from the trigger
ArrowUp or ArrowDownMoves to the previous or next item
Home or EndMoves to the first or last item
A letterMoves to the next item that starts with it
Enter or SpaceChooses the item, or opens Switch workspace or another submenu
ArrowRightOpens the submenu of the item it's on
ArrowLeftCloses the submenu and goes back to its item
EscapeCloses the menu and puts focus back on the trigger

Motion

It appears with a `Presence` preset and leaves faster than it came, in about 60% of the time.

With reduced motion: The menu and its submenus fade in and out in 100ms instead of growing from the trigger; inside AppShell layout="sidebar" the menu appears and goes at once either way.

Layout

The trigger is a 36px row (--bt-h-button) that fills its slot, the workspace's name truncating with an ellipsis and its full name as the title; in a sidebar's rail it's the 20px tile alone, centered, with the name in a tooltip. The menu is 280px wide with 36px items, and the trigger's whole row is its hit area.

See it in the roastery demo.