Early bird: 30% off Dashral ProSee pricing

Dashral

Account MenuPro

An avatar that widens into the account panel: who's signed in, the workspace (switched in a step that slides in), links, the theme and sign out.

Installation

When to use

  • The avatar in an app's header, or the account at a sidebar's foot (showName, side top): everything about the person signed in, in one place.
  • Apps with several workspaces or teams: switching happens inside the same panel, without a page.

When not to use

  • A site with no accounts: a plain link to sign in is enough.
  • Many settings to change at once: they belong on a settings page the menu links to.

Usage

Account Menu with your own data: a whole component you can paste as a page.

example.tsx
"use client"

import { AccountMenu } from "@/components/dashral/pro/account-menu"

import { useState } from "react"
import { Settings, UserRound } from "lucide-react"

const workspaces = [
  { id: "halcyon", name: "Halcyon Studio", detail: "Pro · 12 members" },
  { id: "orbit", name: "Orbit Labs", detail: "Team · 28 members" },
]

const items = [
  { id: "profile", label: "Profile", icon: <UserRound />, href: "/profile" },
  { id: "settings", label: "Settings", icon: <Settings />, href: "/settings" },
]

export default function Account() {
  const [workspace, setWorkspace] = useState("halcyon")
  const [theme, setTheme] = useState<"light" | "dark" | "system">("system")
  return (
    <AccountMenu
      user={{ name: "Maya Lindqvist", email: "maya@halcyon.studio" }}
      workspaces={workspaces}
      workspace={workspace}
      onWorkspaceChange={setWorkspace}
      items={items}
      theme={{ value: theme, onValueChange: setTheme }}
      onSignOut={() => console.log("signed out")}
    />
  )
}

API reference

AccountMenu

An avatar that widens into the account panel: who's signed in, the workspace (switched in a step that slides in), links, the theme and sign out (checked in a step of its own). Shrinks back onto the avatar when done.

PropTypeDefault
userAccountUser

Required.

—
workspacesAccountWorkspace[]—
workspacestring

The workspace in use, by id (controlled), or the first.

—
defaultWorkspacestring—
onWorkspaceChange(id: string) => void—
onCreateWorkspace() => void

Adds "Create workspace" under the workspaces.

—
itemsAccountItem[][]
theme{ value: AccountTheme; onValueChange: (theme: AccountTheme) => void }

A theme switch in the panel: light, dark or system.

—
onSignOut() => void

Adds Sign out, after a check inside the panel.

—
showNameboolean

The button: the avatar alone (default), or the avatar with the name, for a sidebar's foot.

false
side"bottom" | "top"

Where it opens: down from the button (default) or up from it.

"bottom"
align"start" | "end"

Which edge it keeps: the button's end (default) or its start.

"end"
widthnumber

The panel's width, in px (never wider than the screen).

300
linkAsReact.ElementType

Your router's link for items with an href; a plain <a> by default.

"a"
classNamestring—
classNamesAccountMenuClassNames—

type AccountUser

PropTypeDefault
namestring—
emailstring—
avatarstring

A picture; initials from the name until (or instead of) it.

—
statusAvatarStatus—

type AccountWorkspace

PropTypeDefault
idstring—
namestring—
logoReact.ReactNode

Its mark: a logo or an initial. The first letter of its name on a tile by default.

—
detailstring

A line under its name: its plan, its members.

—

type AccountItem

PropTypeDefault
idstring—
labelstring—
iconReact.ReactNode—
shortcutstring[]

Its keys, shown beside it (["mod", ","]). Shown only: wire them in your app if they should work outside.

—
hrefstring

A link (rendered with linkAs), or…

—
onSelect() => void

…an action.

—
groupstring

Items of the same group sit together; a line separates groups.

—

type AccountTheme

= "light" | "dark" | "system"

type AccountMenuClassNames

PropTypeDefault
rootstring—
buttonstring—
panelstring—

Keyboard

KeysAction
↑or↓Through the rows
HomeorEndThe first or last row
→orEnterOn the workspace: open the workspaces; on Sign out: open the check
←or→On Theme: light, dark or system
←In a step: back to the menu
EscBack from a step, or close; the focus returns to the avatar

Accessibility

  • The button is named "Account: <name>" (or shows the name, with showName) and says whether its panel is open.
  • The panel is a dialog (aria-modal); its rows are menu items with one tab stop, the workspaces menu item radios with aria-checked, the theme a radiogroup.
  • Sign out asks first, inside the panel, so it can't happen by a stray press.

Motion

  • The avatar widens into the panel (0.42 s) and, closing, the panel shrinks back while the two crossfade.
  • One highlight glides from row to row; the workspaces and the sign-out check slide in as the panel reshapes. A picked workspace's check moves first, then the step slides back. The theme thumb glides (right to left too).
  • Smooth tweens on [0.4, 0, 0.2, 1], never springs, except the small press. With reduced motion it only fades.