Skip to content

Rebuild ProfileMenu on the registry DropdownMenu per the Nebari header recipe #564

Description

@jbouder

Summary

frontend/src/components/layout/ProfileMenu.tsx is a hand-rolled popover (custom open state, onBlur/Escape handling, role="menu" div, Tab-based focus order). The canonical Nebari app-header recipe (.claude/skills/nebari-ui/SKILL.md, "Profile / account menu" and "Theme picker") builds the profile menu from the registry DropdownMenu (modal={false}, DropdownMenuTrigger variant="ghost", DropdownMenuContent align="end" className="w-[248px] p-2") with the Light/Dark/System picker as a Base UI Menu.RadioGroup / Menu.RadioItem (closeOnClick={false}) wired to useTheme().

The registry re-sync PR applied the mechanical parts (248px width, token-based shadow, ThemeMode from @nebari/use-theme-preference, text-sign-out-foreground) but left the composition alone because it is a structural change.

Motivation

  • One header across Nebari apps: keyboard behaviour (arrow-key navigation, typeahead, focus return) and open/close semantics should come from the shared DropdownMenu rather than a bespoke implementation.
  • Removes ~100 lines of focus/blur bookkeeping that the registry primitive already handles.
  • The theme picker should read/write theme state via useTheme() directly instead of props threaded from App through Layout.

Acceptance Criteria

  • ProfileMenu renders DropdownMenu modal={false} + DropdownMenuTrigger / DropdownMenuContent from @/components/ui/dropdown-menu (248px, p-2), keeping the avatar/initial + name + ChevronDown trigger.
  • Theme picker is a Menu.RadioGroup of three Menu.RadioItems exposing role="menuitemradio" + aria-checked, with closeOnClick={false}, wired to useTheme() from @/hooks/theme-provider.
  • Layout no longer needs themeMode / onThemeChange props (it can keep isDarkMode for the logo, or read useTheme() itself).
  • Sign-out item uses DropdownMenuItem with text-sign-out-foreground (nebi is a Wails desktop app in local mode; the item stays conditional on team mode as today).
  • ProfileMenu.test.tsx and the e2e selectTheme helper are updated for menu keyboard semantics (arrow keys instead of Tab between items) and still pass.

Out of Scope

  • Adding a notifications bell (nebi has no in-app notification feed).
  • Introducing an avatar primitive; the registry does not publish @nebari/avatar, so the current <img> / initial fallback stays.
  • Other hand-rolled menus (e.g. SplitButton).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Start date

    None yet

    Target date

    None yet

    Size

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions