Dropdown Menu

Displays a menu to the user — such as a set of actions or functions — triggered by a button.

    My Account
  • Profile
    • Team
    • Invite Users
      • Email
      • Message
    • Support
    • API
  • Logout
<DropdownMenu>
  <DropdownMenuTrigger>
    <Button variant="outline">Open Menu</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuLabel>My Account</DropdownMenuLabel>
    <DropdownMenuItem>Profile</DropdownMenuItem>
    <DropdownMenuGroup class="border-t">
      <DropdownMenuItem>Team</DropdownMenuItem>
      <DropdownMenuSub>
        <DropdownMenuSubTrigger>
          Invite Users
        </DropdownMenuSubTrigger>
        <DropdownMenuSubContent>
          <DropdownMenuItem>Email</DropdownMenuItem>
          <DropdownMenuItem>Message</DropdownMenuItem>
        </DropdownMenuSubContent>
      </DropdownMenuSub>
    </DropdownMenuGroup>
    <DropdownMenuGroup>
      <DropdownMenuItem>Support</DropdownMenuItem>
      <DropdownMenuItem>API</DropdownMenuItem>
    </DropdownMenuGroup>
    <DropdownMenuItem class="border-t">Logout</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Installation

uvx --from basic-components components add dropdown_menu
pipx run --spec basic-components components add dropdown_menu
pip install basic-components && components add dropdown_menu
  • Copy Dropdown Menu components below to your local environment
  • Place them in the components/ui/dropdown_menu directory in your project
  • Configure your jinja environment for JinjaX
  • Add the cn() helper function to your global jinja environment

Usage

<DropdownMenu>
  <DropdownMenuTrigger>
    <Button variant="outline">Open Menu</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuLabel>My Account</DropdownMenuLabel>
    <DropdownMenuItem>Profile</DropdownMenuItem>
    <DropdownMenuGroup class="border-t">
      <DropdownMenuItem>Team</DropdownMenuItem>
      <DropdownMenuSub>
        <DropdownMenuSubTrigger>
          Invite Users
        </DropdownMenuSubTrigger>
        <DropdownMenuSubContent>
          <DropdownMenuItem>Email</DropdownMenuItem>
          <DropdownMenuItem>Message</DropdownMenuItem>
        </DropdownMenuSubContent>
      </DropdownMenuSub>
    </DropdownMenuGroup>
    <DropdownMenuGroup>
      <DropdownMenuItem>Support</DropdownMenuItem>
      <DropdownMenuItem>API</DropdownMenuItem>
    </DropdownMenuGroup>
    <DropdownMenuItem class="border-t">Logout</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Code

<div x-data="{ open: false }" >{{ content }}</div>
{#def
    label: str = "",
    className: str = "",
    checked: bool = False,
    disabled: bool = False,
#}
<DropdownMenuItem
    class="{{ className }} data-[state=checked]:bg-zinc-100 data-[state=checked]:text-zinc-900 dark:data-[state=checked]:bg-zinc-800 dark:data-[state=checked]:text-zinc-50"
>
  <div class="relative flex items-center">
    <Checkbox :checked="{{ checked }}" :disabled="{{ disabled }}"/>
    <span class="ml-2">{{ label }}</span>
  </div>
</DropdownMenuItem>
<div
    x-show="open"
    @click.away="open = false"
    class="absolute z-50 mt-2 w-48 rounded-md border bg-white p-1 shadow-lg dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-50"
>
  <ul>
    {{ content }}
  </ul>
</div>
{#def
    className: str = "",
#}
<div
    class="{{ className }} border-b border-zinc-100 py-1 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-50"
>
  <ul>
    {{ content }}
  </ul>
</div>
{#def
    className: str = "",
#}
<li
    @click="open = false"
    class="{{ className }} cursor-pointer border-zinc-100 px-4 py-2 text-sm hover:bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-50 dark:hover:bg-zinc-800 dark:hover:text-zinc-50"
>
  {{ content }}
</li>
<div
    class="border-b border-zinc-100 px-4 py-2 text-sm font-semibold dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-50"
>
  {{ content }}
</div>
{#def
    name: str = "",
    className: str = "",
    options: list[str, str] = [],
    value: str = ""
#}
<DropdownMenuItem class="{{ className }}">
  <div class="relative flex items-center">
    <RadioGroup :name="{{ name }}" :options="{{ options }}" :value="{{ value }}"/>
    <span class="ml-2">{{ name }}</span>
  </div>
</DropdownMenuItem>
{#def
    className: str = "",
#}
<div
    class="{{ className }} -mx-1 my-1 h-px bg-zinc-100 dark:bg-zinc-800"
    {{ attrs.render() }}
    aria-hidden="true"
>
  {{ content }}
</div>
<div x-data="{ subOpen: false }" class="group relative">{{ content }}</div>
<div
    x-show="subOpen"
    @mouseenter="subOpen = true"
    @mouseleave="subOpen = false"
    class="absolute left-full top-0 z-50 -ml-2 w-32 rounded-md border bg-white p-1 shadow-lg dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-50"
>
  <ul>
    {{ content }}
  </ul>
</div>
<div
    @mouseenter="subOpen = true"
    @mouseleave="subOpen = false"
    class="flex cursor-pointer items-center justify-between px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-zinc-800 dark:hover:text-zinc-50"
>
  {{ content }}
  <span class="ml-2"><ChevronRightIcon className="h-4 w-4"/></span>
</div>
{#def
    className: str = "",
#}
<div @click="open = !open" class="{{ className }}">{{ content }}</div>