Dropdown Menu

Displays a menu of items that users can select from when triggered.

llms.txt
	<script lang="ts">
  import { Avatar, DropdownMenu } from "bits-ui";
  import Cardholder from "phosphor-svelte/lib/Cardholder";
  import CaretRight from "phosphor-svelte/lib/CaretRight";
  import DotsThree from "phosphor-svelte/lib/DotsThree";
  import GearSix from "phosphor-svelte/lib/GearSix";
  import UserCircle from "phosphor-svelte/lib/UserCircle";
  import UserCirclePlus from "phosphor-svelte/lib/UserCirclePlus";
  import Bell from "phosphor-svelte/lib/Bell";
  import Check from "phosphor-svelte/lib/Check";
  import DotOutline from "phosphor-svelte/lib/DotOutline";
 
  let notifications = $state<boolean>(false);
  let invited = $state("");
</script>
 
<DropdownMenu.Root>
  <DropdownMenu.Trigger
    class="border-input text-foreground shadow-btn hover:bg-muted inline-flex h-10 w-10 select-none items-center justify-center rounded-full border text-sm font-medium active:scale-[0.98]"
  >
    <DotsThree class="text-foreground h-6 w-6" />
  </DropdownMenu.Trigger>
  <DropdownMenu.Portal>
    <DropdownMenu.Content
      class="border-muted bg-background shadow-popover outline-hidden focus-visible:outline-hidden w-[229px] rounded-xl border px-1 py-1.5"
      sideOffset={8}
    >
      <DropdownMenu.Item
        class="rounded-button data-highlighted:bg-muted ring-0! ring-transparent! flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
      >
        <div class="flex items-center">
          <UserCircle class="text-foreground-alt mr-2 size-5" />
          Profile
        </div>
        <div class="ml-auto flex items-center gap-px">
          <kbd
            class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-xs"
          >

          </kbd>
          <kbd
            class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-[10px]"
          >
            P
          </kbd>
        </div>
      </DropdownMenu.Item>
      <DropdownMenu.Item
        class="rounded-button data-highlighted:bg-muted ring-0! ring-transparent! flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
      >
        <div class="flex items-center">
          <Cardholder class="text-foreground-alt mr-2 size-5" />
          Billing
        </div>
        <div class="ml-auto flex items-center gap-px">
          <kbd
            class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-xs"
          >

          </kbd>
          <kbd
            class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-[10px]"
          >
            B
          </kbd>
        </div>
      </DropdownMenu.Item>
      <DropdownMenu.Item
        class="rounded-button data-highlighted:bg-muted ring-0! ring-transparent! flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
      >
        <div class="flex items-center">
          <GearSix class="text-foreground-alt mr-2 size-5" />
          Settings
        </div>
        <div class="ml-auto flex items-center gap-px">
          <kbd
            class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-xs"
          >

          </kbd>
          <kbd
            class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-[10px]"
          >
            S
          </kbd>
        </div>
      </DropdownMenu.Item>
      <DropdownMenu.CheckboxItem
        bind:checked={notifications}
        class="rounded-button data-highlighted:bg-muted ring-0! ring-transparent! flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
      >
        {#snippet children({ checked })}
          <div class="flex items-center pr-4">
            <Bell class="text-foreground-alt mr-2 size-5" />
            Notifications
          </div>
          <div class="ml-auto flex items-center gap-px">
            {#if checked}
              <Check class="size-4" />
            {/if}
          </div>
        {/snippet}
      </DropdownMenu.CheckboxItem>
      <DropdownMenu.Sub>
        <DropdownMenu.SubTrigger
          class="rounded-button data-highlighted:bg-muted data-[state=open]:bg-muted ring-0! ring-transparent! flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
        >
          <div class="flex items-center">
            <UserCirclePlus class="text-foreground-alt mr-2 size-5" />
            Workspace
          </div>
          <div class="ml-auto flex items-center gap-px">
            <CaretRight class="text-foreground-alt size-5" />
          </div>
        </DropdownMenu.SubTrigger>
        <DropdownMenu.SubContent
          class="border-muted bg-background shadow-popover ring-0! ring-transparent! w-[209px] rounded-xl border px-1 py-1.5"
          sideOffset={10}
        >
          <DropdownMenu.RadioGroup bind:value={invited}>
            <DropdownMenu.RadioItem
              value="huntabyte"
              class="rounded-button data-highlighted:bg-muted ring-0! ring-transparent! flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
            >
              {#snippet children({ checked })}
                <Avatar.Root
                  class="border-foreground/50 relative mr-3 flex size-5 shrink-0 overflow-hidden rounded-full border"
                >
                  <Avatar.Image
                    src="https://github.com/huntabyte.png"
                    alt="@huntabyte"
                    class="aspect-square h-full w-full"
                  />
                  <Avatar.Fallback
                    class="bg-muted text-xxs flex h-full w-full items-center justify-center rounded-full"
                    >HJ</Avatar.Fallback
                  >
                </Avatar.Root>
                @huntabyte
                {#if checked}
                  <DotOutline class="ml-auto size-4" />
                {/if}
              {/snippet}
            </DropdownMenu.RadioItem>
            <DropdownMenu.RadioItem
              value="pavel"
              class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
            >
              {#snippet children({ checked })}
                <Avatar.Root
                  class="border-foreground/50 relative mr-3 flex size-5 shrink-0 overflow-hidden rounded-full border"
                >
                  <Avatar.Image
                    src="https://github.com/pavelstianko.png"
                    alt="@pavel_stianko"
                    class="aspect-square h-full w-full"
                  />
                  <Avatar.Fallback
                    class="bg-muted flex h-full w-full items-center justify-center rounded-full text-xs"
                    >PS</Avatar.Fallback
                  >
                </Avatar.Root>
                @pavel_stianko
                {#if checked}
                  <DotOutline class="ml-auto size-4" />
                {/if}
              {/snippet}
            </DropdownMenu.RadioItem>
            <DropdownMenu.RadioItem
              value="cokakoala"
              class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
            >
              {#snippet children({ checked })}
                <Avatar.Root
                  class="border-foreground/50 relative mr-3 flex size-5 shrink-0 overflow-hidden rounded-full border"
                >
                  <Avatar.Image
                    src="https://github.com/adriangonz97.png"
                    alt="@cokakoala_"
                    class="aspect-square h-full w-full"
                  />
                  <Avatar.Fallback
                    class="bg-muted flex h-full w-full items-center justify-center rounded-full text-xs"
                    >CK</Avatar.Fallback
                  >
                </Avatar.Root>
                @cokakoala_
                {#if checked}
                  <DotOutline class="ml-auto size-4" />
                {/if}
              {/snippet}
            </DropdownMenu.RadioItem>
            <DropdownMenu.RadioItem
              value="tglide"
              class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
            >
              {#snippet children({ checked })}
                <Avatar.Root
                  class="border-foreground/50 relative mr-3 flex size-5 shrink-0 overflow-hidden rounded-full border"
                >
                  <Avatar.Image
                    src="https://github.com/tglide.png"
                    alt="@tglide"
                    class="aspect-square h-full w-full"
                  />
                  <Avatar.Fallback
                    class="bg-muted flex h-full w-full items-center justify-center rounded-full text-xs"
                  >
                    TL
                  </Avatar.Fallback>
                </Avatar.Root>
                @thomasglopes
                {#if checked}
                  <DotOutline class="ml-auto size-4" />
                {/if}
              {/snippet}
            </DropdownMenu.RadioItem>
          </DropdownMenu.RadioGroup>
        </DropdownMenu.SubContent>
      </DropdownMenu.Sub>
    </DropdownMenu.Content>
  </DropdownMenu.Portal>
</DropdownMenu.Root>

Structure

	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
</script>
 
<DropdownMenu.Root>
  <DropdownMenu.Trigger />
 
  <DropdownMenu.Content>
    <DropdownMenu.Group>
      <DropdownMenu.GroupHeading />
      <DropdownMenu.Item />
    </DropdownMenu.Group>
 
    <DropdownMenu.Group>
      <DropdownMenu.Item />
    </DropdownMenu.Group>
 
    <DropdownMenu.CheckboxItem>
      <DropdownMenu.CheckboxIndicator />
    </DropdownMenu.CheckboxItem>
 
    <DropdownMenu.RadioGroup>
      <DropdownMenu.RadioItem>
        <DropdownMenu.RadioIndicator />
      </DropdownMenu.RadioItem>
    </DropdownMenu.RadioGroup>
 
    <DropdownMenu.Sub>
      <DropdownMenu.SubTrigger />
      <DropdownMenu.SubContent />
    </DropdownMenu.Sub>
 
    <DropdownMenu.Separator />
    <DropdownMenu.Arrow />
  </DropdownMenu.Content>
</DropdownMenu.Root>

Reusable Components

If you're planning to use Dropdown Menu in multiple places, you can create a reusable component that wraps the Dropdown Menu component.

This example shows you how to create a Dropdown Menu component that accepts a few custom props that make it more capable.

MyDropdownMenu.svelte
	<script lang="ts">
  import type { Snippet } from "svelte";
  import { DropdownMenu, type WithoutChild } from "bits-ui";
 
  type Props = DropdownMenu.Props & {
    buttonText: string;
    items: string[];
    contentProps?: WithoutChild<DropdownMenu.Content.Props>;
    // other component props if needed
  };
 
  let {
    open = $bindable(false),
    children,
    buttonText,
    items,
    contentProps,
    ...restProps
  }: Props = $props();
</script>
 
<DropdownMenu.Root bind:open {...restProps}>
  <DropdownMenu.Trigger>
    {buttonText}
  </DropdownMenu.Trigger>
  <DropdownMenu.Portal>
    <DropdownMenu.Content {...contentProps}>
      <DropdownMenu.Group aria-label={buttonText}>
        {#each items as item}
          <DropdownMenu.Item textValue={item}>
            {item}
          </DropdownMenu.Item>
        {/each}
      </DropdownMenu.Group>
    </DropdownMenu.Content>
  </DropdownMenu.Portal>
</DropdownMenu.Root>

You can then use the MyDropdownMenu component like this:

	<script lang="ts">
  import MyDropdownMenu from "./MyDropdownMenu.svelte";
</script>
 
<MyDropdownMenu
  buttonText="Select a manager"
  items={["Michael Scott", "Dwight Schrute", "Jim Halpert"]}
/>

Managing Open State

This section covers how to manage the open state of the menu.

Two-Way Binding

Use bind:open for simple, automatic state synchronization:

	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
  let isOpen = $state(false);
</script>
 
<button onclick={() => (isOpen = true)}>Open Context Menu</button>
 
<DropdownMenu.Root bind:open={isOpen}>
  <!-- ... -->
</DropdownMenu.Root>

Fully Controlled

Use a Function Binding for complete control over the state's reads and writes.

	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
  let myOpen = $state(false);
 
  function getOpen() {
    return myOpen;
  }
 
  function setOpen(newOpen: boolean) {
    myOpen = newOpen;
  }
</script>
 
<DropdownMenu.Root bind:open={getOpen, setOpen}>
  <!-- ... -->
</DropdownMenu.Root>

Groups

To group related menu items, you can use the DropdownMenu.Group component along with either a DropdownMenu.GroupHeading or an aria-label attribute on the DropdownMenu.Group component.

	<DropdownMenu.Group>
  <DropdownMenu.GroupHeading>File</DropdownMenu.GroupHeading>
  <DropdownMenu.Item>New</DropdownMenu.Item>
  <DropdownMenu.Item>Open</DropdownMenu.Item>
  <DropdownMenu.Item>Save</DropdownMenu.Item>
  <DropdownMenu.Item>Save As</DropdownMenu.Item>
</DropdownMenu.Group>
<!-- or -->
<DropdownMenu.Group aria-label="file">
  <DropdownMenu.Item>New</DropdownMenu.Item>
  <DropdownMenu.Item>Open</DropdownMenu.Item>
  <DropdownMenu.Item>Save</DropdownMenu.Item>
  <DropdownMenu.Item>Save As</DropdownMenu.Item>
</DropdownMenu.Group>

Group Heading

The DropdownMenu.GroupHeading component must be a child of either a DropdownMenu.Group or DropdownMenu.RadioGroup component. If used on its own, an error will be thrown during development.

	<DropdownMenu.Group>
  <DropdownMenu.GroupHeading>File</DropdownMenu.GroupHeading>
  <!-- ... items here -->
</DropdownMenu.Group>
 
<!-- or -->
 
<DropdownMenu.RadioGroup>
  <DropdownMenu.GroupHeading>Favorite color</DropdownMenu.GroupHeading>
  <!-- ... radio items here -->
</DropdownMenu.RadioGroup>

Radio Groups

You can combine the DropdownMenu.RadioGroup and DropdownMenu.RadioItem components to create a radio group within a menu.

	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
 
  const values = ["one", "two", "three"];
  let value = $state("one");
</script>
 
<DropdownMenu.RadioGroup bind:value>
  <DropdownMenu.GroupHeading>Favorite number</DropdownMenu.GroupHeading>
  {#each values as value}
    <DropdownMenu.RadioItem {value}>
      {#snippet children({ checked })}
        {#if checked}

        {/if}
        {value}
      {/snippet}
    </DropdownMenu.RadioItem>
  {/each}
</DropdownMenu.RadioGroup>

The value state does not persist between menu open/close cycles. To persist the state, you must store it in a $state variable and pass it to the value prop.

Checkbox Items

You can use the DropdownMenu.CheckboxItem component to create a menuitemcheckbox element to add checkbox functionality to menu items.

	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
 
  let notifications = $state(true);
</script>
 
<DropdownMenu.CheckboxItem bind:checked={notifications}>
  {#snippet children({ checked, indeterminate })}
    {#if indeterminate}
      -
    {:else if checked}

    {/if}
    Notifications
  {/snippet}
</DropdownMenu.CheckboxItem>

The checked state does not persist between menu open/close cycles. To persist the state, you must store it in a $state variable and pass it to the checked prop.

Checkbox Groups

You can use the DropdownMenu.CheckboxGroup component around a set of DropdownMenu.CheckboxItem components to create a checkbox group within a menu, where the value prop is an array of the selected values.

	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
 
  let colors = $state<string[]>([]);
</script>
 
<DropdownMenu.CheckboxGroup bind:value={colors}>
  <DropdownMenu.GroupHeading>Favorite color</DropdownMenu.GroupHeading>
  <DropdownMenu.CheckboxItem value="red">
    {#snippet children({ checked })}
      {#if checked}

      {/if}
      Red
    {/snippet}
  </DropdownMenu.CheckboxItem>
  <DropdownMenu.CheckboxItem value="blue">
    {#snippet children({ checked })}
      {#if checked}

      {/if}
      Blue
    {/snippet}
  </DropdownMenu.CheckboxItem>
  <DropdownMenu.CheckboxItem value="green">
    {#snippet children({ checked })}
      {#if checked}

      {/if}
      Green
    {/snippet}
  </DropdownMenu.CheckboxItem>
</DropdownMenu.CheckboxGroup>

The value state does not persist between menu open/close cycles. To persist the state, you must store it in a $state variable and pass it to the value prop.

Nested Menus

You can create nested menus using the DropdownMenu.Sub component to create complex menu structures.

	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
</script>
 
<DropdownMenu.Content>
  <DropdownMenu.Item>Item 1</DropdownMenu.Item>
  <DropdownMenu.Item>Item 2</DropdownMenu.Item>
  <DropdownMenu.Sub>
    <DropdownMenu.SubTrigger>Open Sub Menu</DropdownMenu.SubTrigger>
    <DropdownMenu.SubContent>
      <DropdownMenu.Item>Sub Item 1</DropdownMenu.Item>
      <DropdownMenu.Item>Sub Item 2</DropdownMenu.Item>
    </DropdownMenu.SubContent>
  </DropdownMenu.Sub>
</DropdownMenu.Content>

Svelte Transitions

You can use the forceMount prop along with the child snippet to forcefully mount the DropdownMenu.Content component to use Svelte Transitions or another animation library that requires more control.

	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
  import { fly } from "svelte/transition";
</script>
 
<DropdownMenu.Content forceMount>
  {#snippet child({ wrapperProps, props, open })}
    {#if open}
      <div {...wrapperProps}>
        <div {...props} transition:fly>
          <DropdownMenu.Item>Item 1</DropdownMenu.Item>
          <DropdownMenu.Item>Item 2</DropdownMenu.Item>
        </div>
      </div>
    {/if}
  {/snippet}
</DropdownMenu.Content>

Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content component that handles this logic if you intend to use this approach. For more information on using transitions with Bits UI components, see the Transitions documentation.

	<script lang="ts">
  import { Avatar, DropdownMenu } from "bits-ui";
  import Cardholder from "phosphor-svelte/lib/Cardholder";
  import CaretRight from "phosphor-svelte/lib/CaretRight";
  import DotsThree from "phosphor-svelte/lib/DotsThree";
  import GearSix from "phosphor-svelte/lib/GearSix";
  import UserCircle from "phosphor-svelte/lib/UserCircle";
  import UserCirclePlus from "phosphor-svelte/lib/UserCirclePlus";
  import Bell from "phosphor-svelte/lib/Bell";
  import Check from "phosphor-svelte/lib/Check";
  import DotOutline from "phosphor-svelte/lib/DotOutline";
  import { fly } from "svelte/transition";
 
  let notifications = $state<boolean>(false);
  let invited = $state("");
</script>
 
<DropdownMenu.Root>
  <DropdownMenu.Trigger
    class="border-input shadow-btn hover:bg-muted inline-flex h-10 w-10 select-none items-center justify-center rounded-full border text-sm font-medium active:scale-[0.98]"
  >
    <DotsThree class="text-foreground h-6 w-6" />
  </DropdownMenu.Trigger>
  <DropdownMenu.Portal>
    <DropdownMenu.Content
      class="border-muted bg-background shadow-popover w-[229px] rounded-xl border px-1 py-1.5 focus-visible:outline-none"
      sideOffset={8}
      forceMount
    >
      {#snippet child({ wrapperProps, props, open })}
        {#if open}
          <div {...wrapperProps}>
            <div {...props} transition:fly={{ duration: 300 }}>
              <DropdownMenu.Item
                class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
              >
                <div class="flex items-center">
                  <UserCircle class="text-foreground-alt mr-2 size-5" />
                  Profile
                </div>
                <div class="ml-auto flex items-center gap-px">
                  <kbd
                    class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-xs"
                  >

                  </kbd>
                  <kbd
                    class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-[10px]"
                  >
                    P
                  </kbd>
                </div>
              </DropdownMenu.Item>
              <DropdownMenu.Item
                class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
              >
                <div class="flex items-center">
                  <Cardholder class="text-foreground-alt mr-2 size-5" />
                  Billing
                </div>
                <div class="ml-auto flex items-center gap-px">
                  <kbd
                    class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-xs"
                  >

                  </kbd>
                  <kbd
                    class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-[10px]"
                  >
                    B
                  </kbd>
                </div>
              </DropdownMenu.Item>
              <DropdownMenu.Item
                class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
              >
                <div class="flex items-center">
                  <GearSix class="text-foreground-alt mr-2 size-5" />
                  Settings
                </div>
                <div class="ml-auto flex items-center gap-px">
                  <kbd
                    class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-xs"
                  >

                  </kbd>
                  <kbd
                    class="rounded-button border-dark-10 bg-background-alt text-muted-foreground shadow-kbd inline-flex size-5 items-center justify-center border text-[10px]"
                  >
                    S
                  </kbd>
                </div>
              </DropdownMenu.Item>
              <DropdownMenu.CheckboxItem
                bind:checked={notifications}
                class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
              >
                {#snippet children({ checked })}
                  <div class="flex items-center pr-4">
                    <Bell class="text-foreground-alt mr-2 size-5" />
                    Notifications
                  </div>
                  <div class="ml-auto flex items-center gap-px">
                    {#if checked}
                      <Check class="size-4" />
                    {/if}
                  </div>
                {/snippet}
              </DropdownMenu.CheckboxItem>
              <DropdownMenu.Sub>
                <DropdownMenu.SubTrigger
                  class="rounded-button data-highlighted:bg-muted data-[state=open]:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
                >
                  <div class="flex items-center">
                    <UserCirclePlus class="text-foreground-alt mr-2 size-5" />
                    Workspace
                  </div>
                  <div class="ml-auto flex items-center gap-px">
                    <CaretRight class="text-foreground-alt size-5" />
                  </div>
                </DropdownMenu.SubTrigger>
                <DropdownMenu.SubContent
                  class="border-muted bg-background shadow-popover w-[209px] rounded-xl border px-1 py-1.5 focus-visible:outline-none"
                  sideOffset={10}
                >
                  <DropdownMenu.RadioGroup bind:value={invited}>
                    <DropdownMenu.RadioItem
                      value="huntabyte"
                      class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
                    >
                      {#snippet children({ checked })}
                        <Avatar.Root
                          class="border-foreground/50 relative mr-3 flex size-5 shrink-0 overflow-hidden rounded-full border"
                        >
                          <Avatar.Image
                            src="https://github.com/huntabyte.png"
                            alt="@huntabyte"
                            class="aspect-square h-full w-full"
                          />
                          <Avatar.Fallback
                            class="bg-muted text-xxs flex h-full w-full items-center justify-center rounded-full"
                            >HJ</Avatar.Fallback
                          >
                        </Avatar.Root>
                        @huntabyte
                        {#if checked}
                          <DotOutline class="ml-auto size-4" />
                        {/if}
                      {/snippet}
                    </DropdownMenu.RadioItem>
                    <DropdownMenu.RadioItem
                      value="pavel"
                      class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
                    >
                      {#snippet children({ checked })}
                        <Avatar.Root
                          class="border-foreground/50 relative mr-3 flex size-5 shrink-0 overflow-hidden rounded-full border"
                        >
                          <Avatar.Image
                            src="https://github.com/pavelstianko.png"
                            alt="@pavel_stianko"
                            class="aspect-square h-full w-full"
                          />
                          <Avatar.Fallback
                            class="bg-muted flex h-full w-full items-center justify-center rounded-full text-xs"
                            >PS</Avatar.Fallback
                          >
                        </Avatar.Root>
                        @pavel_stianko
                        {#if checked}
                          <DotOutline class="ml-auto size-4" />
                        {/if}
                      {/snippet}
                    </DropdownMenu.RadioItem>
                    <DropdownMenu.RadioItem
                      value="cokakoala"
                      class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
                    >
                      {#snippet children({ checked })}
                        <Avatar.Root
                          class="border-foreground/50 relative mr-3 flex size-5 shrink-0 overflow-hidden rounded-full border"
                        >
                          <Avatar.Image
                            src="https://github.com/adriangonz97.png"
                            alt="@cokakoala_"
                            class="aspect-square h-full w-full"
                          />
                          <Avatar.Fallback
                            class="bg-muted flex h-full w-full items-center justify-center rounded-full text-xs"
                            >CK</Avatar.Fallback
                          >
                        </Avatar.Root>
                        @cokakoala_
                        {#if checked}
                          <DotOutline class="ml-auto size-4" />
                        {/if}
                      {/snippet}
                    </DropdownMenu.RadioItem>
                    <DropdownMenu.RadioItem
                      value="tglide"
                      class="rounded-button data-highlighted:bg-muted flex h-10 select-none items-center py-3 pl-3 pr-1.5 text-sm font-medium focus-visible:outline-none"
                    >
                      {#snippet children({ checked })}
                        <Avatar.Root
                          class="border-foreground/50 relative mr-3 flex size-5 shrink-0 overflow-hidden rounded-full border"
                        >
                          <Avatar.Image
                            src="https://github.com/tglide.png"
                            alt="@tglide"
                            class="aspect-square h-full w-full"
                          />
                          <Avatar.Fallback
                            class="bg-muted flex h-full w-full items-center justify-center rounded-full text-xs"
                          >
                            TL
                          </Avatar.Fallback>
                        </Avatar.Root>
                        @thomasglopes
                        {#if checked}
                          <DotOutline class="ml-auto size-4" />
                        {/if}
                      {/snippet}
                    </DropdownMenu.RadioItem>
                  </DropdownMenu.RadioGroup>
                </DropdownMenu.SubContent>
              </DropdownMenu.Sub>
            </div>
          </div>
        {/if}
      {/snippet}
    </DropdownMenu.Content>
  </DropdownMenu.Portal>
</DropdownMenu.Root>

Custom Anchor

By default, the DropdownMenu.Content is anchored to the DropdownMenu.Trigger component, which determines where the content is positioned.

If you wish to instead anchor the content to a different element, you can pass either a selector string or an HTMLElement to the customAnchor prop of the DropdownMenu.Content component.

	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
  let customAnchor = $state<HTMLElement>(null!);
</script>
 
<div bind:this={customAnchor}></div>
 
<DropdownMenu.Root>
  <DropdownMenu.Trigger />
  <DropdownMenu.Content {customAnchor}>
    <!-- ... -->
  </DropdownMenu.Content>
</DropdownMenu.Root>

API Reference

DropdownMenu.Root

The root component which manages & scopes the state of the dropdown menu.

Property Details
open
onOpenChange
onOpenChangeComplete
dir
children
Data Attribute Details

DropdownMenu.Trigger

The button element which toggles the dropdown menu.

Property Details
disabled
ref
children
child
Data Attribute Details
data-state
data-menu-trigger

DropdownMenu.Portal

A component that portals the content of the dropdown menu to the body or a custom target (if provided).

Property Details
to
disabled
children
Data Attribute Details

DropdownMenu.Content

The content displayed when the dropdown menu is open.

Property Details
side
sideOffset
align
alignOffset
arrowPadding
avoidCollisions
collisionBoundary
collisionPadding
sticky
hideWhenDetached
updatePositionStrategy
strategy
preventScroll
customAnchor
onEscapeKeydown
escapeKeydownBehavior
onInteractOutside
onFocusOutside
interactOutsideBehavior
onOpenAutoFocus
onCloseAutoFocus
trapFocus
forceMount
preventOverflowTextSelection
dir
loop
ref
children
child
Data Attribute Details
data-state
data-menu-content
CSS Variable Details
--bits-dropdown-menu-content-transform-origin
--bits-dropdown-menu-content-available-width
--bits-dropdown-menu-content-available-height
--bits-dropdown-menu-anchor-width
--bits-dropdown-menu-anchor-height

DropdownMenu.ContentStatic

The content displayed when the dropdown menu is open. (Static/No Floating UI)

Property Details
onEscapeKeydown
escapeKeydownBehavior
onInteractOutside
onFocusOutside
interactOutsideBehavior
onOpenAutoFocus
onCloseAutoFocus
trapFocus
preventScroll
forceMount
preventOverflowTextSelection
dir
loop
ref
children
child
Data Attribute Details
data-state
data-menu-content

DropdownMenu.Item

A menu item within the dropdown menu.

Property Details
disabled
textValue
onSelect
closeOnSelect
ref
children
child
Data Attribute Details
data-orientation
data-highlighted
data-disabled
data-menu-item

DropdownMenu.CheckboxGroup

A group of checkbox menu items, where multiple can be checked at a time.

Property Details
value
onValueChange
ref
children
child
Data Attribute Details
data-menu-checkbox-group

DropdownMenu.CheckboxItem

A menu item that can be controlled and toggled like a checkbox.

Property Details
disabled
checked
onCheckedChange
indeterminate
onIndeterminateChange
value
textValue
onSelect
closeOnSelect
ref
children
child
Data Attribute Details
data-orientation
data-highlighted
data-disabled
data-state

DropdownMenu.RadioGroup

A group of radio menu items, where only one can be checked at a time.

Property Details
value
onValueChange
ref
children
child
Data Attribute Details
data-menu-radio-group

DropdownMenu.RadioItem

A menu item that can be controlled and toggled like a radio button. It must be a child of a RadioGroup.

Property Details
value
disabled
textValue
onSelect
closeOnSelect
ref
children
child
Data Attribute Details
data-orientation
data-highlighted
data-disabled
data-state
data-value
data-menu-radio-item

DropdownMenu.Separator

A horizontal line to visually separate menu items.

Property Details
ref
children
child
Data Attribute Details
data-orientation
data-menu-separator

DropdownMenu.Arrow

An optional arrow which points to the dropdown menu's anchor/trigger point.

Property Details
width
height
ref
children
child
Data Attribute Details
data-state
data-menu-arrow

DropdownMenu.Group

A group of menu items. It should be passed an aria-label or have a child DropdownMenu.GroupHeading component to provide a label for a group of menu items.

Property Details
ref
children
child
Data Attribute Details
data-menu-group

DropdownMenu.GroupHeading

A heading for a group which will be skipped when navigating with the keyboard. It is used to provide a description for a group of menu items and must be a child of either a DropdownMenu.Group or DropdownMenu.RadioGroup component.

Property Details
ref
children
child
Data Attribute Details
data-menu-group-heading

DropdownMenu.Sub

A submenu belonging to the parent dropdown menu. Responsible for managing the state of the submenu.

Property Details
open
onOpenChange
onOpenChangeComplete
children
Data Attribute Details

DropdownMenu.SubTrigger

A menu item which when pressed or hovered, opens the submenu it is a child of.

Property Details
disabled
textValue
onSelect
ref
children
child
Data Attribute Details
data-orientation
data-highlighted
data-disabled
data-state
data-menu-sub-trigger

DropdownMenu.SubContent

The submenu content displayed when the parent submenu is open.

Property Details
side
sideOffset
align
alignOffset
arrowPadding
avoidCollisions
collisionBoundary
collisionPadding
sticky
hideWhenDetached
updatePositionStrategy
strategy
preventScroll
customAnchor
onEscapeKeydown
escapeKeydownBehavior
onInteractOutside
onFocusOutside
interactOutsideBehavior
onOpenAutoFocus
onCloseAutoFocus
trapFocus
forceMount
preventOverflowTextSelection
dir
loop
ref
children
child
Data Attribute Details
data-state
data-menu-sub-content

DropdownMenu.SubContentStatic

The submenu content displayed when the parent submenu menu is open. (Static/No Floating UI)

Property Details
onEscapeKeydown
escapeKeydownBehavior
onInteractOutside
onFocusOutside
interactOutsideBehavior
onOpenAutoFocus
onCloseAutoFocus
trapFocus
forceMount
preventOverflowTextSelection
dir
loop
ref
children
child
Data Attribute Details
data-state
data-menu-sub-content