Presets

Blocks

Get PRO

Need premium blocks and templates? Upgrade to PRO and get access.

Upgrade
JoinLogin
Presets
Monochrome
Overview
  • Introduction
  • Components
  • Installation
Components
  • Accordion
  • Alert
  • Alert Dialog
  • Aspect Ratio
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • CalendarNEW
  • Card
  • CarouselNEW
  • Checkbox
  • Collapsible
  • Dialog
  • Dropdown Menu
  • Empty
  • Field
  • Input
  • Input Group
  • Item
  • Kbd
  • Label
  • Native Select
  • Scroll Area
  • SelectNEW
  • Separator
  • SwitchNEW
  • Table
  • Tabs
  • Textarea
  • TooltipNEW

Dropdown Menu

PreviousNext

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-menu
npx sprawlify@latest add dropdown-menu
yarn sprawlify@latest add dropdown-menu
bunx --bun sprawlify@latest add dropdown-menu

Install the following dependencies:

pnpm add @sprawlify/primitives @sprawlify/svelte
npm install @sprawlify/primitives @sprawlify/svelte
yarn add @sprawlify/primitives @sprawlify/svelte
bun add @sprawlify/primitives @sprawlify/svelte

Add the following files to your project:

dropdown-menu/dropdown-menu-checkbox-item.svelte
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>
dropdown-menu/dropdown-menu-content.svelte
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>
dropdown-menu/dropdown-menu-group.svelte
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>
dropdown-menu/dropdown-menu-item.svelte
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>
dropdown-menu/dropdown-menu-label.svelte
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>
dropdown-menu/dropdown-menu-portal.svelte
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>
dropdown-menu/dropdown-menu-radio-group.svelte
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>
dropdown-menu/dropdown-menu-radio-item.svelte
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>
dropdown-menu/dropdown-menu-separator.svelte
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/>
dropdown-menu/dropdown-menu-shortcut.svelte
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>
dropdown-menu/dropdown-menu-sub-content.svelte
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>
dropdown-menu/dropdown-menu-sub-trigger.svelte
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>
dropdown-menu/dropdown-menu-sub.svelte
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>
dropdown-menu/dropdown-menu-trigger.svelte
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>
dropdown-menu/dropdown-menu.svelte
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>
dropdown-menu/index.ts
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";16

Update 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 IconsShortcutsSubmenu

Get PRO

Need premium blocks and templates? Upgrade to PRO and get access.