User menu
The signed-in account, its destinations, and sign out. The app supplies the destinations and handles the session; everything else \u2014 the trigger, the keyboard, the ARIA, the placement of sign out \u2014 is fixed.
Anatomy
Code
<GdUserMenu
:user="{ name: 'Jordan Teal', email: '[email protected]' }"
:unread="3"
:links="[
{ label: 'Your projects', to: '/projects' },
{ label: 'Messages', to: '/messages', badge: 3 }
]"
@signed-out="signOut"
/>What is fixed, and why
- Sign out is always last, always present, and always separated. A slightly destructive action flush beneath "Settings" is how people sign out by accident \u2014 it sits under a rule, away from the destinations.
- It EMITS rather than acts. A UI package has no business owning a session: the endpoint, the redirect and the cookie are the app's.
- The account is named in the trigger's accessible name, not in a head inside the panel \u2014
role="menu"may only contain items, groups and separators, and the ARIA is the part that must not bend to fit a design. - The keyboard is GdMenu's. One disclosed departure from the WAI-ARIA note: ArrowUp on the trigger opens onto the FIRST item, not the last.
- Never hand-compose an account menu. Composing this per app is the re-invention the system exists to stop.
API
Props
userrequired{ name: string; email: string }—Who is signed in. Both fields reach the trigger's accessible name — initials cannot disambiguate two accounts, and knowing WHICH account you are about to act as is the point of the control.
unreadnumber0The count on the avatar itself; 0 hides it. It also rides along in the trigger's accessible name, because the badge that carries it visually is hidden from assistive tech.
linksGdUserMenuLink[][]The destinations: `{ label, to, badge? }`. The only thing the app supplies — the map has a certifier desk and Code has neither that nor a settings page.
actionsGdUserMenuAction[][]Items that DO something rather than going somewhere.
Events
signedOut[]Sign out was chosen. The request, the redirect and the session cookie belong to the app; the component only says it happened.