User menu
Your account, settings, theme, and sign out behind the avatar. Opens as a bottom sheet on phones.
motionproduct
Preview
User menu preview
Live · keyboard ready
When to use
- The single account entry point in an app top bar.
- Menus that combine presence status, theme preference, account links, and sign out.
- Apps that want async sign out with a spinner in the menu.
When not to use
- Use dropdown-menu for generic command lists.
- Use theme-switch for a standalone light and dark toggle.
- Use workspace-sidebar when account and workspace switching live in a side navigation.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "user-menu",
"type": "registry:ui",
"title": "User menu",
"description": "Your account, settings, theme, and sign out behind the avatar. Opens as a bottom sheet on phones.",
"categories": [
"actions"
],
"dependencies": [
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/user-menu/user-menu.tsx",
"type": "registry:component",
"target": "@components/manicat/user-menu/user-menu.tsx"
},
{
"path": "registry/components/user-menu/user-menu.module.css",
"type": "registry:component",
"target": "@components/manicat/user-menu/user-menu.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/user-menu",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/user-menu",
"markdown": "https://uiarc.dev/components/user-menu/markdown",
"tags": [
"motion",
"product"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { UserMenu } from "@/components/manicat/user-menu/user-menu";
export function UserMenuExample() {
return (
<UserMenu
user={{ name: "Elia Kuratli", email: "hello@manicat.dev", plan: "Manicat Pro" }}
items={[{ label: "Settings" }, { label: "Keyboard shortcuts", keys: ["⌘", "/"] }, { label: "Sign out" }]}
onSignOut={() => {}}
/>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Account menu The avatar menu in an app header with the plan, shortcuts and sign out.
Account menu
The avatar menu in an app header with the plan, shortcuts and sign out. preview
Live · keyboard ready
account-menu-the-avatar-menu-in-an-app-header-with-the-plan-shortcuts-and-sign-out-.tsxtsx
Keyboard interactions
| Keys | Action |
|---|---|
| Enter / Space / ArrowDown | Opens the menu from the avatar and moves to the first row. |
| ArrowUp | Opens the menu from the avatar and moves to the last row. |
| ArrowDown / ArrowUp | Moves between rows, looping at the ends. The highlight follows. |
| Home / End | Moves to the first or last row. |
| A to Z | Typeahead jumps to the next row starting with the typed letters. |
| ArrowLeft / ArrowRight | Chooses the previous or next option in the theme or status switch. |
| Enter / Space | Activates the row, or chooses a theme or status without closing. |
| Escape / Tab | Closes the menu and returns focus to the avatar. |
Accessibility
- The trigger has aria-haspopup="menu" and aria-expanded, and is labelled "Account menu, <name>" plus the status when one is shown.
- Rows are menuitem buttons; the theme and status switches are labelled groups of menuitemradio buttons with aria-checked.
- Pointer focus draws no ring; keyboard focus shows Arc's shared focus ring. The highlight marks the keyboard position. Outside press, the scrim, and swipe down close the menu.
- Sign out sets aria-busy while an async handler runs; shortcut hints are aria-hidden.
Motion
- The panel scales and fades out of the avatar on a spring that never overshoots; rows fade in with a short stagger, and closing is a quick fade.
- One highlight glides between rows for the pointer and the keyboard; the switch thumb slides between options.
- On phones the sheet rises from the bottom edge and follows a downward drag, closing past a short distance or a quick flick.
- Reduced motion opens and closes with a short fade, jumps the highlight, and turns off dragging.
Responsive behavior
- The menu is 17.5rem wide, capped at the viewport width minus 24px, with 12px collision padding.
- Long names and emails ellipsize instead of widening the menu.
- The trigger is a fixed 40px avatar, and the theme row keeps a 44px minimum height for touch.
Performance
- Content renders only while open; each opening gets a fresh layout namespace so shared indicators do not animate from stale positions.
- The avatar image decodes async and falls back to initials on error.
Notes for AI
- Use as the single account entry point in an app top bar. For generic command lists use dropdown-menu; for a standalone light/dark toggle use theme-switch.
- Keep items to three or four account destinations; the theme switch and sign out are built in.
- onThemeChange only reports; apply the theme to the document yourself, optionally with a view transition.
- Return the sign out promise so the item shows progress and the menu closes when it settles.