workos-auth/ui-shell: Add account dropdown to auth corner#52
Conversation
Introduce shadcn dropdown-menu and replace the minimal email/sign-out block with a compact avatar trigger menu in the app shell sidebar.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Greptile SummaryThis PR polishes the auth corner introduced in PR #51 by replacing the flat email/sign-out block with a compact avatar-initials trigger that opens a shadcn
Confidence Score: 3/5Safe to merge for mouse/pointer users; keyboard-only users cannot sign out through the dropdown. The sign-out form nested inside DropdownMenuItem works for mouse clicks because the button fills the entire item area, but bits-ui dispatches keyboard activation (Enter/Space) as a synthetic click on the item div rather than on child elements, so the button[type="submit"] inside the form is never triggered. Separately, focus:bg-transparent on that same item removes the only focus indicator keyboard users would have. The rest of the PR — the new shadcn dropdown-menu primitives and the initials derivation — is straightforward and clean. src/lib/components/auth-corner.svelte — specifically the DropdownMenuItem wrapping the sign-out form at lines 38–47. Important Files Changed
Sequence DiagramsequenceDiagram
participant U as User
participant AC as AuthCorner
participant DM as DropdownMenu (bits-ui)
participant F as Sign-out Form
participant S as /sign-out endpoint
U->>AC: View sidebar (userId present)
AC->>AC: Derive initials from email/userId
AC-->>U: Render avatar trigger button
U->>DM: Click avatar button
DM-->>U: Open dropdown (email label + Sign out item)
note over U,DM: Mouse path (works)
U->>F: Click button directly (mouse)
F->>S: POST /sign-out
S-->>U: Redirect / session cleared
note over U,DM: Keyboard path (broken)
U->>DM: Navigate to Sign out item (arrow keys)
U->>DM: Press Enter
DM->>DM: Dispatches click() on item div
DM--xF: click does NOT propagate to child button
note over F: Form never submitted
Reviews (1): Last reviewed commit: "Add account dropdown to auth corner with..." | Re-trigger Greptile |
| <DropdownMenuItem class="p-0 focus:bg-transparent"> | ||
| <form method="POST" action={resolve('/sign-out')} class="w-full"> | ||
| <button | ||
| type="submit" | ||
| class="w-full rounded-md px-2 py-1.5 text-left text-xs hover:bg-accent hover:text-accent-foreground" | ||
| > | ||
| Sign out | ||
| </button> | ||
| </form> | ||
| </DropdownMenuItem> |
There was a problem hiding this comment.
DropdownMenuPrimitive.Item (rendered as a div[role="menuitem"]) handles keyboard activation (Enter/Space) by dispatching a synthetic click on itself — not on its child elements. Because the button[type="submit"] is a child, that synthetic click never reaches it, so the form is never submitted via keyboard. Mouse users work correctly because they click the button itself (which fills the item area via w-full), but keyboard-only users cannot sign out from this menu.
A common fix is to use the item's onSelect handler to programmatically submit the form, or to forward the activation directly to a button using the asChild prop if bits-ui supports it for Item.
| <DropdownMenuLabel class="truncate font-normal">{email}</DropdownMenuLabel> | ||
| <DropdownMenuSeparator /> | ||
| {/if} | ||
| <DropdownMenuItem class="p-0 focus:bg-transparent"> |
There was a problem hiding this comment.
Focus indicator suppressed on sign-out item
focus:bg-transparent overrides the focus:bg-accent style provided by DropdownMenuPrimitive.Item, leaving the focused state visually indistinguishable from the unfocused state. Keyboard users navigating with arrow keys get no visual cue that "Sign out" is focused, which violates WCAG 2.4.7 (Focus Visible). The hover:bg-accent styles on the inner button are mouse-only and don't help here.

Stack Context
This 3-PR stack migrates FlightLog from Clerk to WorkOS AuthKit while preserving cookie sessions for the dashboard and Bearer tokens for the SDK/API.
Stack:
workos-auth/core(#51) →workos-auth/ui-shell→workos-auth/docs-testsWhy?
PR 1 ships a functional but minimal auth corner. This PR polishes the app shell account UI with a compact avatar dropdown that matches the rest of the shadcn-based dashboard.
What?
dropdown-menucomponentsTest plan
bun run checkbun run lint(src/)bunx vitest run src/lib/server/auth.test.ts src/lib/auth-redirect.test.ts