Displays a menu to the user — such as a set of actions or functions — triggered by a button.
1<script module lang="ts">
2 import { Button } from "@/components/ui/button"
3 import {
4 DropdownMenu,
Installation
pnpm dlx sprawlify@latest add dropdown-menunpx sprawlify@latest add dropdown-menuyarn sprawlify@latest add dropdown-menubunx --bun sprawlify@latest add dropdown-menu
Install the following dependencies:
pnpm add @sprawlify/primitives @sprawlify/sveltenpm install @sprawlify/primitives @sprawlify/svelteyarn add @sprawlify/primitives @sprawlify/sveltebun add @sprawlify/primitives @sprawlify/svelte
Add the following files to your project:
1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import { CheckIcon } from "lucide-svelte"
4import { cn } from "@/lib/utils"
5import type { ComponentProps } from "svelte"
6
7interface Props extends ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> {
8 inset?: boolean
9}
10
11let { class: className, inset, checked, children, ...rest }: Props = $props()
12</script>
13
14<DropdownMenuPrimitive.CheckboxItem
15 data-slot="dropdown-menu-checkbox-item"
16 data-inset={inset}
17 class={cn(
18 "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
19 className
20 )}
21 {checked}
22 {...rest}
23>
24 <span
25 class="absolute right-2 flex items-center justify-center pointer-events-none"
26 data-slot="dropdown-menu-checkbox-item-indicator"
27 >
28 <DropdownMenuPrimitive.ItemIndicator>
29 <CheckIcon />
30 </DropdownMenuPrimitive.ItemIndicator>
31 </span>
32 {@render children?.()}
33</DropdownMenuPrimitive.CheckboxItem>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import { Portal } from "@sprawlify/svelte/portal";
4import { cn } from "@/lib/utils"
5import type { ComponentProps } from "svelte"
6
7interface Props extends ComponentProps<typeof DropdownMenuPrimitive.Content> {}
8
9let { class: className, children, ...rest }: Props = $props()
10</script>
11
12<Portal>
13 <DropdownMenuPrimitive.Positioner>
14 <DropdownMenuPrimitive.Content
15 data-slot="dropdown-menu-content"
16 class={cn("focus-visible:outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 z-(--z-index) max-h-(--available-height) w-(--reference-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto data-[state=closed]:overflow-hidden", className)}
17 {...rest}
18 >
19 {@render children?.()}
20 </DropdownMenuPrimitive.Content>
21 </DropdownMenuPrimitive.Positioner>
22</Portal>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import type { ComponentProps } from "svelte"
4
5interface Props extends ComponentProps<typeof DropdownMenuPrimitive.ItemGroup> { }
6
7let { children, ...rest }: Props = $props()
8</script>
9
10<DropdownMenuPrimitive.ItemGroup data-slot="dropdown-menu-group" {...rest}>
11 {@render children?.()}
12</DropdownMenuPrimitive.ItemGroup>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import { cn } from "@/lib/utils"
4import type { ComponentProps } from "svelte"
5
6interface Props extends ComponentProps<typeof DropdownMenuPrimitive.Item> {
7 inset?: boolean
8 variant?: "default" | "destructive"
9}
10
11let { class: className, inset, variant = "default", children, ...rest }: Props = $props()
12</script>
13
14<DropdownMenuPrimitive.Item
15 data-slot="dropdown-menu-item"
16 data-inset={inset}
17 data-variant={variant}
18 class={cn(
19 "gap-1.5 rounded-md px-1.5 py-1 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
20 "data-[variant=destructive]:text-destructive data-highlighted:bg-accent data-highlighted:text-accent-foreground data-[variant=destructive]:data-highlighted:bg-destructive/10 dark:data-[variant=destructive]:data-highlighted:bg-destructive/20 data-[variant=destructive]:data-highlighted:text-destructive data-[variant=destructive]:data-highlighted:*:[svg]:text-destructive not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground",
21 className
22 )}
23 {...rest}
24>
25 {@render children?.()}
26</DropdownMenuPrimitive.Item>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import { cn } from "@/lib/utils"
4import type { ComponentProps } from "svelte"
5
6interface Props extends ComponentProps<typeof DropdownMenuPrimitive.ItemGroupLabel> {
7 inset?: boolean
8}
9
10let { class: className, inset, children, ...rest }: Props = $props()
11</script>
12
13<DropdownMenuPrimitive.ItemGroupLabel
14 data-slot="dropdown-menu-label"
15 data-inset={inset}
16 class={cn("text-muted-foreground px-1.5 py-1 text-xs font-medium data-inset:pl-7", className)}
17 {...rest}
18>
19 {@render children?.()}
20</DropdownMenuPrimitive.ItemGroupLabel>1<script lang="ts">
2import { Portal } from "@sprawlify/svelte/portal";
3import type { ComponentProps } from "svelte"
4
5interface Props extends ComponentProps<typeof Portal> {
6 "data-slot"?: string
7}
8
9let { children, ...rest }: Props = $props()
10</script>
11
12<Portal data-slot="dropdown-menu-portal" {...rest}>
13 {@render children?.()}
14</Portal>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import type { ComponentProps } from "svelte"
4
5interface Props extends ComponentProps<typeof DropdownMenuPrimitive.RadioItemGroup> { }
6
7let { children, ...rest }: Props = $props()
8</script>
9
10<DropdownMenuPrimitive.RadioItemGroup data-slot="dropdown-menu-radio-group" {...rest}>
11 {@render children?.()}
12</DropdownMenuPrimitive.RadioItemGroup>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import { CheckIcon } from "lucide-svelte"
4import { cn } from "@/lib/utils"
5import type { ComponentProps } from "svelte"
6
7interface Props extends ComponentProps<typeof DropdownMenuPrimitive.RadioItem> { inset?: boolean }
8
9let { class: className, inset, children, ...rest }: Props = $props()
10</script>
11
12<DropdownMenuPrimitive.RadioItem
13 data-slot="dropdown-menu-radio-item"
14 data-inset={inset}
15 class={cn(
16 "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
17 className
18 )}
19 {...rest}
20>
21 <span
22 class="absolute right-2 flex items-center justify-center pointer-events-none"
23 data-slot="dropdown-menu-radio-item-indicator"
24 >
25 <DropdownMenuPrimitive.ItemIndicator>
26 <CheckIcon />
27 </DropdownMenuPrimitive.ItemIndicator>
28 </span>
29 {@render children?.()}
30</DropdownMenuPrimitive.RadioItem>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import { cn } from "@/lib/utils"
4import type { ComponentProps } from "svelte"
5
6interface Props extends ComponentProps<typeof DropdownMenuPrimitive.Separator> { }
7
8let { class: className, ...rest }: Props = $props()
9</script>
10
11<DropdownMenuPrimitive.Separator
12 data-slot="dropdown-menu-separator"
13 class={cn("bg-border -mx-1 my-1 h-px", className)}
14 {...rest}
15/>1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte";
4import type { HTMLAttributes } from "svelte/elements";
5
6interface Props extends HTMLAttributes<HTMLSpanElement>, PolymorphicProps<"span"> { }
7
8let { class: className, children, ...rest }: Props = $props()
9</script>
10
11<Sprawlify
12 as="span"
13 data-slot="dropdown-menu-shortcut"
14 class={cn("text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-xs tracking-widest", className)}
15 {...rest}
16>
17 {@render children?.()}
18</Sprawlify>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import { cn } from "@/lib/utils"
4import type { ComponentProps } from "svelte"
5import { Portal } from "@sprawlify/svelte/portal";
6
7interface Props extends ComponentProps<typeof DropdownMenuPrimitive.Content> { }
8
9let { class: className, children, ...rest }: Props = $props()
10</script>
11
12<Portal>
13 <DropdownMenuPrimitive.Positioner>
14 <DropdownMenuPrimitive.Content
15 data-slot="dropdown-menu-sub-content"
16 class={cn("focus-visible:outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-[96px] rounded-lg p-1 shadow-lg ring-1 duration-100 origin-(--transform-origin) overflow-hidden", className)}
17 {...rest}
18 >
19 {@render children?.()}
20 </DropdownMenuPrimitive.Content>
21 </DropdownMenuPrimitive.Positioner>
22</Portal>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import { ChevronRightIcon } from "lucide-svelte"
4import { cn } from "@/lib/utils"
5import type { ComponentProps } from "svelte"
6
7interface Props extends ComponentProps<typeof DropdownMenuPrimitive.TriggerItem> { inset?: boolean }
8
9let { class: className, inset, children, ...rest }: Props = $props()
10</script>
11
12<DropdownMenuPrimitive.TriggerItem
13 data-slot="dropdown-menu-sub-trigger"
14 data-inset={inset}
15 class={cn(
16 "w-full data-[state=open]:bg-accent data-[state=open]:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md px-1.5 py-1 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 flex cursor-default items-center outline-hidden select-none [&_svg]:pointer-events-none [&_svg]:shrink-0",
17 className
18 )}
19 {...rest}
20>
21 {@render children?.()}
22 <ChevronRightIcon class="ml-auto" />
23</DropdownMenuPrimitive.TriggerItem>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import type { ComponentProps } from "svelte"
4
5interface Props extends ComponentProps<typeof DropdownMenuPrimitive.Root> {
6 "data-slot"?: string
7}
8
9let { children, ...rest }: Props = $props()
10</script>
11
12<DropdownMenuPrimitive.Root data-slot="dropdown-menu-sub" {...rest}>
13 {@render children?.()}
14</DropdownMenuPrimitive.Root>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import type { ComponentProps } from "svelte"
4
5interface Props extends ComponentProps<typeof DropdownMenuPrimitive.Trigger> { }
6
7let { children, ...rest }: Props = $props()
8</script>
9
10<DropdownMenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...rest}>
11 {@render children?.()}
12</DropdownMenuPrimitive.Trigger>1<script lang="ts">
2import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/svelte/dropdown-menu"
3import type { ComponentProps } from "svelte"
4
5interface Props extends ComponentProps<typeof DropdownMenuPrimitive.Root> {
6 "data-slot"?: string
7}
8
9let { children, ...rest }: Props = $props()
10</script>
11
12<DropdownMenuPrimitive.Root data-slot="dropdown-menu" positioning={{ offset: { mainAxis: 4 } }} {...rest}>
13 {@render children?.()}
14</DropdownMenuPrimitive.Root>1export { default as DropdownMenu } from "./dropdown-menu.svelte";2export { default as DropdownMenuPortal } from "./dropdown-menu-portal.svelte";3export { default as DropdownMenuTrigger } from "./dropdown-menu-trigger.svelte";4export { default as DropdownMenuContent } from "./dropdown-menu-content.svelte";5export { default as DropdownMenuGroup } from "./dropdown-menu-group.svelte";6export { default as DropdownMenuItem } from "./dropdown-menu-item.svelte";7export { default as DropdownMenuCheckboxItem } from "./dropdown-menu-checkbox-item.svelte";8export { default as DropdownMenuRadioGroup } from "./dropdown-menu-radio-group.svelte";9export { default as DropdownMenuRadioItem } from "./dropdown-menu-radio-item.svelte";10export { default as DropdownMenuLabel } from "./dropdown-menu-label.svelte";11export { default as DropdownMenuSeparator } from "./dropdown-menu-separator.svelte";12export { default as DropdownMenuShortcut } from "./dropdown-menu-shortcut.svelte";13export { default as DropdownMenuSub } from "./dropdown-menu-sub.svelte";14export { default as DropdownMenuSubTrigger } from "./dropdown-menu-sub-trigger.svelte";15export { default as DropdownMenuSubContent } from "./dropdown-menu-sub-content.svelte";16Update the import paths to match your project setup.
Usage
1import {
2 DropdownMenu,
3 DropdownMenuPortal,
4 DropdownMenuTrigger,
5 DropdownMenuContent,
6 DropdownMenuGroup,
7 DropdownMenuLabel,
8 DropdownMenuItem,
9 DropdownMenuCheckboxItem,
10 DropdownMenuRadioGroup,
11 DropdownMenuRadioItem,
12 DropdownMenuSeparator,
13 DropdownMenuShortcut,
14 DropdownMenuSub,
15 DropdownMenuSubTrigger,
16 DropdownMenuSubContent
17} from "@/components/ui/dropdown-menu"1<DropdownMenu>
2 <DropdownMenuTrigger>
3 {#snippet asChild(props)}
4 <Button variant="outline" {...props()}>Open</Button>
5 {/snippet}
6 </DropdownMenuTrigger>
7 <DropdownMenuContent>
8 <DropdownMenuGroup>
9 <DropdownMenuLabel>My Account</DropdownMenuLabel>
10 <DropdownMenuItem>Profile</DropdownMenuItem>
11 <DropdownMenuItem>Billing</DropdownMenuItem>
12 </DropdownMenuGroup>
13 <DropdownMenuSeparator />
14 <DropdownMenuGroup>
15 <DropdownMenuItem>Team</DropdownMenuItem>
16 <DropdownMenuItem>Subscription</DropdownMenuItem>
17 </DropdownMenuGroup>
18 </DropdownMenuContent>
19</DropdownMenu>Examples
Avatar
An account switcher dropdown triggered by an avatar.
1<script module lang="ts">
2 import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
3 import { Button } from "@/components/ui/button"
4 import {
Basic
A basic dropdown menu with labels and separators.
1<script module lang="ts">
2 import { Button } from "@/components/ui/button"
3 import {
4 DropdownMenu,
Checkboxes
Use DropdownMenuCheckboxItem for toggles.
1<script lang="ts">
2 import { Button } from "@/components/ui/button"
3 import {
4 DropdownMenu,
Checkboxes Icons
Add icons to checkbox items.
1<script lang="ts">
2 import { Button } from "@/components/ui/button"
3 import {
4 DropdownMenu,
Complex
A richer example combining groups, icons, and submenus.
1<script lang="ts">
2 import { Button } from "@/components/ui/button";
3 import {
4 DropdownMenu,
Destructive
Use variant="destructive" for irreversible actions.
1<script module lang="ts">
2 import { Button } from "@/components/ui/button"
3 import {
4 DropdownMenu,
Icons
Combine icons with labels for quick scanning.
1<script module lang="ts">
2 import { Button } from "@/components/ui/button"
3 import {
4 DropdownMenu,
Radio Icons
Show radio options with icons.
1<script lang="ts">
2 import { Button } from "@/components/ui/button"
3 import {
4 DropdownMenu,
Shortcuts
Add DropdownMenuShortcut to show keyboard hints.
1<script module lang="ts">
2 import { Button } from "@/components/ui/button"
3 import {
4 DropdownMenu,
Submenu
Use DropdownMenuSub to nest secondary actions.
1<script module lang="ts">
2 import { Button } from "@/components/ui/button"
3 import {
4 DropdownMenu,
On This Page
InstallationUsageExamplesAvatarBasicCheckboxesCheckboxes IconsComplexDestructiveIconsRadio IconsShortcutsSubmenuGet PRO
Need premium blocks and templates? Upgrade to PRO and get access.