Dropdown Menu
Displays a menu of items that users can select from when triggered.
	<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.Portal>
          <DropdownMenu.SubContent
            class="border-muted bg-background shadow-popover ring-0! ring-transparent! w-[209px] rounded-xl border px-1 py-1.5 outline-none"
            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.Portal>
      </DropdownMenu.Sub>
    </DropdownMenu.Content>
  </DropdownMenu.Portal>
</DropdownMenu.Root>
	@import url("https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap");
 
@import "tailwindcss";
@plugin "tailwindcss-animate";
 
@custom-variant dark (&:is(.dark *));
 
@font-face {
	font-family: "Cal Sans";
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url("/CalSans-SemiBold.woff2") format("woff2");
}
 
:root {
	/* Colors */
	--background: hsl(0 0% 100%);
	--background-alt: hsl(0 0% 100%);
	--foreground: hsl(0 0% 9%);
	--foreground-alt: hsl(0 0% 32%);
	--muted: hsl(240 5% 96%);
	--muted-foreground: hsla(0 0% 9% / 0.4);
	--border: hsl(240 6% 10%);
	--border-input: hsla(240 6% 10% / 0.17);
	--border-input-hover: hsla(240 6% 10% / 0.4);
	--border-card: hsla(240 6% 10% / 0.1);
	--dark: hsl(240 6% 10%);
	--dark-10: hsla(240 6% 10% / 0.1);
	--dark-40: hsla(240 6% 10% / 0.4);
	--dark-04: hsla(240 6% 10% / 0.04);
	--accent: hsl(204 94% 94%);
	--accent-foreground: hsl(204 80% 16%);
	--destructive: hsl(347 77% 50%);
	--tertiary: hsl(37.7 92.1% 50.2%);
	--line: hsl(0 0% 100%);
 
	/* black */
	--contrast: hsl(0 0% 0%);
 
	/* Shadows */
	--shadow-mini: 0px 1px 0px 1px rgba(0, 0, 0, 0.04);
	--shadow-mini-inset: 0px 1px 0px 0px rgba(0, 0, 0, 0.04) inset;
	--shadow-popover: 0px 7px 12px 3px hsla(var(--dark-10));
	--shadow-kbd: 0px 2px 0px 0px rgba(0, 0, 0, 0.07);
	--shadow-btn: 0px 1px 0px 1px rgba(0, 0, 0, 0.03);
	--shadow-card: 0px 2px 0px 1px rgba(0, 0, 0, 0.04);
	--shadow-date-field-focus: 0px 0px 0px 3px rgba(24, 24, 27, 0.17);
}
 
.dark {
	/* Colors */
	--background: hsl(0 0% 5%);
	--background-alt: hsl(0 0% 8%);
	--foreground: hsl(0 0% 95%);
	--foreground-alt: hsl(0 0% 70%);
	--muted: hsl(240 4% 16%);
	--muted-foreground: hsla(0 0% 100% / 0.4);
	--border: hsl(0 0% 96%);
	--border-input: hsla(0 0% 96% / 0.17);
	--border-input-hover: hsla(0 0% 96% / 0.4);
	--border-card: hsla(0 0% 96% / 0.1);
	--dark: hsl(0 0% 96%);
	--dark-40: hsl(0 0% 96% / 0.4);
	--dark-10: hsl(0 0% 96% / 0.1);
	--dark-04: hsl(0 0% 96% / 0.04);
	--accent: hsl(204 90% 90%);
	--accent-foreground: hsl(204 94% 94%);
	--destructive: hsl(350 89% 60%);
	--line: hsl(0 0% 9.02%);
	--tertiary: hsl(61.3 100% 82.2%);
	/* white */
	--contrast: hsl(0 0% 100%);
 
	/* Shadows */
	--shadow-mini: 0px 1px 0px 1px rgba(0, 0, 0, 0.3);
	--shadow-mini-inset: 0px 1px 0px 0px rgba(0, 0, 0, 0.5) inset;
	--shadow-popover: 0px 7px 12px 3px hsla(0deg 0% 0% / 30%);
	--shadow-kbd: 0px 2px 0px 0px rgba(255, 255, 255, 0.07);
	--shadow-btn: 0px 1px 0px 1px rgba(0, 0, 0, 0.2);
	--shadow-card: 0px 2px 0px 1px rgba(0, 0, 0, 0.4);
	--shadow-date-field-focus: 0px 0px 0px 3px rgba(244, 244, 245, 0.1);
}
 
@theme inline {
	--color-background: var(--background);
	--color-background-alt: var(--background-alt);
	--color-foreground: var(--foreground);
	--color-foreground-alt: var(--foreground-alt);
	--color-muted: var(--muted);
	--color-muted-foreground: var(--muted-foreground);
	--color-border: var(--border-card);
	--color-border-input: var(--border-input);
	--color-border-input-hover: var(--border-input-hover);
	--color-border-card: var(--border-card);
	--color-dark: var(--dark);
	--color-dark-10: var(--dark-10);
	--color-dark-40: var(--dark-40);
	--color-dark-04: var(--dark-04);
	--color-accent: var(--accent);
	--color-accent-foreground: var(--accent-foreground);
	--color-destructive: var(--destructive);
	--color-tertiary: var(--tertiary);
	--color-line: var(--line);
	--color-contrast: var(--contrast);
 
	--shadow-mini: var(--shadow-mini);
	--shadow-mini-inset: var(--shadow-mini-inset);
	--shadow-popover: var(--shadow-popover);
	--shadow-kbd: var(--shadow-kbd);
	--shadow-btn: var(--shadow-btn);
	--shadow-card: var(--shadow-card);
	--shadow-date-field-focus: var(--shadow-date-field-focus);
 
	--text-xxs: 10px;
 
	--radius-card: 16px;
	--radius-card-lg: 20px;
	--radius-card-sm: 10px;
	--radius-input: 9px;
	--radius-button: 5px;
	--radius-5px: 5px;
	--radius-9px: 9px;
	--radius-10px: 10px;
	--radius-15px: 15px;
 
	--spacing-input: 3rem;
	--spacing-input-sm: 2.5rem;
 
	--breakpoint-desktop: 1440px;
 
	--animate-accordion-down: accordion-down 0.2s ease-out;
	--animate-accordion-up: accordion-up 0.2s ease-out;
	--animate-caret-blink: caret-blink 1s ease-out infinite;
	--animate-scale-in: scale-in 0.2s ease;
	--animate-scale-out: scale-out 0.15s ease;
	--animate-fade-in: fade-in 0.2s ease;
	--animate-fade-out: fade-out 0.15s ease;
	--animate-enter-from-left: enter-from-left 0.2s ease;
	--animate-enter-from-right: enter-from-right 0.2s ease;
	--animate-exit-to-left: exit-to-left 0.2s ease;
	--animate-exit-to-right: exit-to-right 0.2s ease;
 
	--font-sans: "Inter", "sans-serif";
	--font-mono: "Source Code Pro", "monospace";
	--font-alt: "Courier", "sans-serif";
	--font-display: "Cal Sans", "sans-serif";
 
	@keyframes accordion-down {
		from {
			height: 0;
		}
		to {
			height: var(--bits-accordion-content-height);
		}
	}
 
	@keyframes accordion-up {
		from {
			height: var(--bits-accordion-content-height);
		}
		to {
			height: 0;
		}
	}
 
	@keyframes caret-blink {
		0%,
		70%,
		100% {
			opacity: 1;
		}
		20%,
		50% {
			opacity: 0;
		}
	}
 
	@keyframes enter-from-right {
		from {
			opacity: 0;
			transform: translateX(200px);
		}
		to {
			opacity: 1;
			transform: translateX(0);
		}
	}
 
	@keyframes enter-from-left {
		from {
			opacity: 0;
			transform: translateX(-200px);
		}
		to {
			opacity: 1;
			transform: translateX(0);
		}
	}
 
	@keyframes exit-to-right {
		from {
			opacity: 1;
			transform: translateX(0);
		}
		to {
			opacity: 0;
			transform: translateX(200px);
		}
	}
 
	@keyframes exit-to-left {
		from {
			opacity: 1;
			transform: translateX(0);
		}
		to {
			opacity: 0;
			transform: translateX(-200px);
		}
	}
 
	@keyframes scale-in {
		from {
			opacity: 0;
			transform: rotateX(-10deg) scale(0.9);
		}
		to {
			opacity: 1;
			transform: rotateX(0deg) scale(1);
		}
	}
 
	@keyframes scale-out {
		from {
			opacity: 1;
			transform: rotateX(0deg) scale(1);
		}
		to {
			opacity: 0;
			transform: rotateX(-10deg) scale(0.95);
		}
	}
 
	@keyframes fade-in {
		from {
			opacity: 0;
		}
		to {
			opacity: 1;
		}
	}
 
	@keyframes fade-out {
		from {
			opacity: 1;
		}
		to {
			opacity: 0;
		}
	}
}
 
@layer base {
	*,
	::after,
	::before,
	::backdrop,
	::file-selector-button {
		border-color: var(--color-border-card, currentColor);
	}
 
	* {
		@apply border-border;
	}
	html {
		-webkit-text-size-adjust: 100%;
		font-variation-settings: normal;
		scrollbar-color: var(--bg-muted);
	}
 
	body {
		@apply bg-background text-foreground;
		font-feature-settings:
			"rlig" 1,
			"calt" 1;
	}
 
	::selection {
		background: #fdffa4;
		color: black;
	}
}
 
@layer components {
	*:not(body):not(.focus-override) {
		outline: none !important;
		&:focus-visible {
			@apply focus-visible:ring-foreground focus-visible:ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-1;
		}
	}
 
	.link {
		@apply hover:text-foreground/80 focus-visible:ring-foreground focus-visible:ring-offset-background rounded-xs focus-visible:outline-hidden inline-flex items-center gap-1 font-medium underline underline-offset-4 focus-visible:ring-2 focus-visible:ring-offset-2;
	}
}
Structure
	<script lang="ts">
  import { DropdownMenu } from "bits-ui";
</script>
 
<DropdownMenu.Root>
  <DropdownMenu.Trigger />
 
  <DropdownMenu.Portal>
    <DropdownMenu.Content>
      <DropdownMenu.Group>
        <DropdownMenu.GroupHeading />
        <DropdownMenu.Item />
      </DropdownMenu.Group>
 
      <DropdownMenu.Group>
        <DropdownMenu.Item />
      </DropdownMenu.Group>
 
      <DropdownMenu.Item />
      <DropdownMenu.CheckboxItem />
 
      <DropdownMenu.RadioGroup>
        <DropdownMenu.RadioItem />
      </DropdownMenu.RadioGroup>
 
      <DropdownMenu.CheckboxGroup>
        <DropdownMenu.CheckboxItem />
      </DropdownMenu.CheckboxGroup>
 
      <DropdownMenu.Sub>
        <DropdownMenu.SubTrigger />
        <DropdownMenu.Portal>
          <DropdownMenu.SubContent />
        </DropdownMenu.Portal>
      </DropdownMenu.Sub>
 
      <DropdownMenu.Separator />
      <DropdownMenu.Arrow />
    </DropdownMenu.Content>
  </DropdownMenu.Portal>
</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.
	<script lang="ts">
  import type { Snippet } from "svelte";
  import { DropdownMenu, type WithoutChild } from "bits-ui";
 
  type Props = DropdownMenu.RootProps & {
    buttonText: string;
    items: string[];
    contentProps?: WithoutChild<DropdownMenu.ContentProps>;
    // 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>
	@import url("https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap");
 
@import "tailwindcss";
@plugin "tailwindcss-animate";
 
@custom-variant dark (&:is(.dark *));
 
@font-face {
	font-family: "Cal Sans";
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url("/CalSans-SemiBold.woff2") format("woff2");
}
 
:root {
	/* Colors */
	--background: hsl(0 0% 100%);
	--background-alt: hsl(0 0% 100%);
	--foreground: hsl(0 0% 9%);
	--foreground-alt: hsl(0 0% 32%);
	--muted: hsl(240 5% 96%);
	--muted-foreground: hsla(0 0% 9% / 0.4);
	--border: hsl(240 6% 10%);
	--border-input: hsla(240 6% 10% / 0.17);
	--border-input-hover: hsla(240 6% 10% / 0.4);
	--border-card: hsla(240 6% 10% / 0.1);
	--dark: hsl(240 6% 10%);
	--dark-10: hsla(240 6% 10% / 0.1);
	--dark-40: hsla(240 6% 10% / 0.4);
	--dark-04: hsla(240 6% 10% / 0.04);
	--accent: hsl(204 94% 94%);
	--accent-foreground: hsl(204 80% 16%);
	--destructive: hsl(347 77% 50%);
	--tertiary: hsl(37.7 92.1% 50.2%);
	--line: hsl(0 0% 100%);
 
	/* black */
	--contrast: hsl(0 0% 0%);
 
	/* Shadows */
	--shadow-mini: 0px 1px 0px 1px rgba(0, 0, 0, 0.04);
	--shadow-mini-inset: 0px 1px 0px 0px rgba(0, 0, 0, 0.04) inset;
	--shadow-popover: 0px 7px 12px 3px hsla(var(--dark-10));
	--shadow-kbd: 0px 2px 0px 0px rgba(0, 0, 0, 0.07);
	--shadow-btn: 0px 1px 0px 1px rgba(0, 0, 0, 0.03);
	--shadow-card: 0px 2px 0px 1px rgba(0, 0, 0, 0.04);
	--shadow-date-field-focus: 0px 0px 0px 3px rgba(24, 24, 27, 0.17);
}
 
.dark {
	/* Colors */
	--background: hsl(0 0% 5%);
	--background-alt: hsl(0 0% 8%);
	--foreground: hsl(0 0% 95%);
	--foreground-alt: hsl(0 0% 70%);
	--muted: hsl(240 4% 16%);
	--muted-foreground: hsla(0 0% 100% / 0.4);
	--border: hsl(0 0% 96%);
	--border-input: hsla(0 0% 96% / 0.17);
	--border-input-hover: hsla(0 0% 96% / 0.4);
	--border-card: hsla(0 0% 96% / 0.1);
	--dark: hsl(0 0% 96%);
	--dark-40: hsl(0 0% 96% / 0.4);
	--dark-10: hsl(0 0% 96% / 0.1);
	--dark-04: hsl(0 0% 96% / 0.04);
	--accent: hsl(204 90% 90%);
	--accent-foreground: hsl(204 94% 94%);
	--destructive: hsl(350 89% 60%);
	--line: hsl(0 0% 9.02%);
	--tertiary: hsl(61.3 100% 82.2%);
	/* white */
	--contrast: hsl(0 0% 100%);
 
	/* Shadows */
	--shadow-mini: 0px 1px 0px 1px rgba(0, 0, 0, 0.3);
	--shadow-mini-inset: 0px 1px 0px 0px rgba(0, 0, 0, 0.5) inset;
	--shadow-popover: 0px 7px 12px 3px hsla(0deg 0% 0% / 30%);
	--shadow-kbd: 0px 2px 0px 0px rgba(255, 255, 255, 0.07);
	--shadow-btn: 0px 1px 0px 1px rgba(0, 0, 0, 0.2);
	--shadow-card: 0px 2px 0px 1px rgba(0, 0, 0, 0.4);
	--shadow-date-field-focus: 0px 0px 0px 3px rgba(244, 244, 245, 0.1);
}
 
@theme inline {
	--color-background: var(--background);
	--color-background-alt: var(--background-alt);
	--color-foreground: var(--foreground);
	--color-foreground-alt: var(--foreground-alt);
	--color-muted: var(--muted);
	--color-muted-foreground: var(--muted-foreground);
	--color-border: var(--border-card);
	--color-border-input: var(--border-input);
	--color-border-input-hover: var(--border-input-hover);
	--color-border-card: var(--border-card);
	--color-dark: var(--dark);
	--color-dark-10: var(--dark-10);
	--color-dark-40: var(--dark-40);
	--color-dark-04: var(--dark-04);
	--color-accent: var(--accent);
	--color-accent-foreground: var(--accent-foreground);
	--color-destructive: var(--destructive);
	--color-tertiary: var(--tertiary);
	--color-line: var(--line);
	--color-contrast: var(--contrast);
 
	--shadow-mini: var(--shadow-mini);
	--shadow-mini-inset: var(--shadow-mini-inset);
	--shadow-popover: var(--shadow-popover);
	--shadow-kbd: var(--shadow-kbd);
	--shadow-btn: var(--shadow-btn);
	--shadow-card: var(--shadow-card);
	--shadow-date-field-focus: var(--shadow-date-field-focus);
 
	--text-xxs: 10px;
 
	--radius-card: 16px;
	--radius-card-lg: 20px;
	--radius-card-sm: 10px;
	--radius-input: 9px;
	--radius-button: 5px;
	--radius-5px: 5px;
	--radius-9px: 9px;
	--radius-10px: 10px;
	--radius-15px: 15px;
 
	--spacing-input: 3rem;
	--spacing-input-sm: 2.5rem;
 
	--breakpoint-desktop: 1440px;
 
	--animate-accordion-down: accordion-down 0.2s ease-out;
	--animate-accordion-up: accordion-up 0.2s ease-out;
	--animate-caret-blink: caret-blink 1s ease-out infinite;
	--animate-scale-in: scale-in 0.2s ease;
	--animate-scale-out: scale-out 0.15s ease;
	--animate-fade-in: fade-in 0.2s ease;
	--animate-fade-out: fade-out 0.15s ease;
	--animate-enter-from-left: enter-from-left 0.2s ease;
	--animate-enter-from-right: enter-from-right 0.2s ease;
	--animate-exit-to-left: exit-to-left 0.2s ease;
	--animate-exit-to-right: exit-to-right 0.2s ease;
 
	--font-sans: "Inter", "sans-serif";
	--font-mono: "Source Code Pro", "monospace";
	--font-alt: "Courier", "sans-serif";
	--font-display: "Cal Sans", "sans-serif";
 
	@keyframes accordion-down {
		from {
			height: 0;
		}
		to {
			height: var(--bits-accordion-content-height);
		}
	}
 
	@keyframes accordion-up {
		from {
			height: var(--bits-accordion-content-height);
		}
		to {
			height: 0;
		}
	}
 
	@keyframes caret-blink {
		0%,
		70%,
		100% {
			opacity: 1;
		}
		20%,
		50% {
			opacity: 0;
		}
	}
 
	@keyframes enter-from-right {
		from {
			opacity: 0;
			transform: translateX(200px);
		}
		to {
			opacity: 1;
			transform: translateX(0);
		}
	}
 
	@keyframes enter-from-left {
		from {
			opacity: 0;
			transform: translateX(-200px);
		}
		to {
			opacity: 1;
			transform: translateX(0);
		}
	}
 
	@keyframes exit-to-right {
		from {
			opacity: 1;
			transform: translateX(0);
		}
		to {
			opacity: 0;
			transform: translateX(200px);
		}
	}
 
	@keyframes exit-to-left {
		from {
			opacity: 1;
			transform: translateX(0);
		}
		to {
			opacity: 0;
			transform: translateX(-200px);
		}
	}
 
	@keyframes scale-in {
		from {
			opacity: 0;
			transform: rotateX(-10deg) scale(0.9);
		}
		to {
			opacity: 1;
			transform: rotateX(0deg) scale(1);
		}
	}
 
	@keyframes scale-out {
		from {
			opacity: 1;
			transform: rotateX(0deg) scale(1);
		}
		to {
			opacity: 0;
			transform: rotateX(-10deg) scale(0.95);
		}
	}
 
	@keyframes fade-in {
		from {
			opacity: 0;
		}
		to {
			opacity: 1;
		}
	}
 
	@keyframes fade-out {
		from {
			opacity: 1;
		}
		to {
			opacity: 0;
		}
	}
}
 
@layer base {
	*,
	::after,
	::before,
	::backdrop,
	::file-selector-button {
		border-color: var(--color-border-card, currentColor);
	}
 
	* {
		@apply border-border;
	}
	html {
		-webkit-text-size-adjust: 100%;
		font-variation-settings: normal;
		scrollbar-color: var(--bg-muted);
	}
 
	body {
		@apply bg-background text-foreground;
		font-feature-settings:
			"rlig" 1,
			"calt" 1;
	}
 
	::selection {
		background: #fdffa4;
		color: black;
	}
}
 
@layer components {
	*:not(body):not(.focus-override) {
		outline: none !important;
		&:focus-visible {
			@apply focus-visible:ring-foreground focus-visible:ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-1;
		}
	}
 
	.link {
		@apply hover:text-foreground/80 focus-visible:ring-foreground focus-visible:ring-offset-background rounded-xs focus-visible:outline-hidden inline-flex items-center gap-1 font-medium underline underline-offset-4 focus-visible:ring-2 focus-visible:ring-offset-2;
	}
}
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
The root component which manages & scopes the state of the dropdown menu.
| Property | Details | 
|---|---|
| open | |
| onOpenChange | |
| onOpenChangeComplete | |
| dir | |
| children | 
The button element which toggles the dropdown menu.
| Property | Details | 
|---|---|
| disabled | |
| ref | |
| children | |
| child | 
| Data Attribute | Details | 
|---|---|
| data-state | |
| data-dropdown-menu-trigger | 
A component that portals the content of the dropdown menu to the body or a custom target (if provided).
| Property | Details | 
|---|---|
| to | |
| disabled | |
| children | 
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-dropdown-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 | 
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-dropdown-menu-content | 
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-dropdown-menu-item | 
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-dropdown-menu-checkbox-group | 
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 | |
| data-dropdown-menu-checkbox-item | 
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-dropdown-menu-radio-group | 
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-dropdown-menu-radio-item | 
A horizontal line to visually separate menu items.
| Property | Details | 
|---|---|
| ref | |
| children | |
| child | 
| Data Attribute | Details | 
|---|---|
| data-orientation | |
| data-menu-separator | |
| data-dropdown-menu-separator | 
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-dropdown-menu-arrow | 
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-dropdown-menu-group | 
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-dropdown-menu-group-heading | 
A submenu belonging to the parent dropdown menu. Responsible for managing the state of the submenu.
| Property | Details | 
|---|---|
| open | |
| onOpenChange | |
| onOpenChangeComplete | |
| children | 
A menu item which when pressed or hovered, opens the submenu it is a child of.
| Property | Details | 
|---|---|
| disabled | |
| openDelay | |
| textValue | |
| onSelect | |
| ref | |
| children | |
| child | 
| Data Attribute | Details | 
|---|---|
| data-orientation | |
| data-highlighted | |
| data-disabled | |
| data-state | |
| data-dropdown-menu-sub-trigger | 
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-dropdown-menu-sub-content | 
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-dropdown-menu-sub-content |