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.

1import { Button } from "@/components/ui/button";2import {3  DropdownMenu,4  DropdownMenuContent,

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/react
npm install @sprawlify/primitives @sprawlify/react
yarn add @sprawlify/primitives @sprawlify/react
bun add @sprawlify/primitives @sprawlify/react

Add the following files to your project:

dropdown-menu.tsx
1"use client";23import * as React from "react";4import { DropdownMenu as DropdownMenuPrimitive } from "@sprawlify/react/dropdown-menu";5import { cn } from "@/lib/utils";6import { CheckIcon, ChevronRightIcon } from "lucide-react";7import { Portal } from "@sprawlify/react/portal";8import { sprawlify } from "@sprawlify/react";910function DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {11  return (12    <DropdownMenuPrimitive.Root13      data-slot="dropdown-menu"14      positioning={{ offset: { mainAxis: 4 } }}15      {...props}16    />17  );18}1920function DropdownMenuPortal({ ...props }: React.ComponentProps<typeof Portal>) {21  return <Portal data-slot="dropdown-menu-portal" {...props} />;22}2324function DropdownMenuTrigger({25  ...props26}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {27  return <DropdownMenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />;28}2930function DropdownMenuContent({31  className,32  ...props33}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {34  return (35    <Portal>36      <DropdownMenuPrimitive.Positioner>37        <DropdownMenuPrimitive.Content38          data-slot="dropdown-menu-content"39          className={cn(40            "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",41            className,42          )}43          {...props}44        />45      </DropdownMenuPrimitive.Positioner>46    </Portal>47  );48}4950function DropdownMenuGroup({51  ...props52}: React.ComponentProps<typeof DropdownMenuPrimitive.ItemGroup>) {53  return <DropdownMenuPrimitive.ItemGroup data-slot="dropdown-menu-group" {...props} />;54}5556function DropdownMenuItem({57  className,58  inset,59  variant = "default",60  ...props61}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {62  inset?: boolean;63  variant?: "default" | "destructive";64}) {65  return (66    <DropdownMenuPrimitive.Item67      data-slot="dropdown-menu-item"68      data-inset={inset}69      data-variant={variant}70      className={cn(71        "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",72        "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",73        className,74      )}75      {...props}76    />77  );78}7980function DropdownMenuCheckboxItem({81  className,82  children,83  checked,84  inset,85  ...props86}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> & {87  inset?: boolean;88}) {89  return (90    <DropdownMenuPrimitive.CheckboxItem91      data-slot="dropdown-menu-checkbox-item"92      data-inset={inset}93      className={cn(94        "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",95        className,96      )}97      checked={checked}98      {...props}99    >100      <span101        className="absolute right-2 flex items-center justify-center pointer-events-none"102        data-slot="dropdown-menu-checkbox-item-indicator"103      >104        <DropdownMenuPrimitive.ItemIndicator>105          <CheckIcon />106        </DropdownMenuPrimitive.ItemIndicator>107      </span>108      {children}109    </DropdownMenuPrimitive.CheckboxItem>110  );111}112113function DropdownMenuRadioGroup({114  ...props115}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItemGroup>) {116  return <DropdownMenuPrimitive.RadioItemGroup data-slot="dropdown-menu-radio-group" {...props} />;117}118119function DropdownMenuRadioItem({120  className,121  children,122  inset,123  ...props124}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem> & {125  inset?: boolean;126}) {127  return (128    <DropdownMenuPrimitive.RadioItem129      data-slot="dropdown-menu-radio-item"130      data-inset={inset}131      className={cn(132        "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",133        className,134      )}135      {...props}136    >137      <span138        className="absolute right-2 flex items-center justify-center pointer-events-none"139        data-slot="dropdown-menu-radio-item-indicator"140      >141        <DropdownMenuPrimitive.ItemIndicator>142          <CheckIcon />143        </DropdownMenuPrimitive.ItemIndicator>144      </span>145      {children}146    </DropdownMenuPrimitive.RadioItem>147  );148}149150function DropdownMenuLabel({151  className,152  inset,153  ...props154}: React.ComponentProps<typeof DropdownMenuPrimitive.ItemGroupLabel> & {155  inset?: boolean;156}) {157  return (158    <DropdownMenuPrimitive.ItemGroupLabel159      data-slot="dropdown-menu-label"160      data-inset={inset}161      className={cn(162        "text-muted-foreground px-1.5 py-1 text-xs font-medium data-inset:pl-7",163        className,164      )}165      {...props}166    />167  );168}169170function DropdownMenuSeparator({171  className,172  ...props173}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {174  return (175    <DropdownMenuPrimitive.Separator176      data-slot="dropdown-menu-separator"177      className={cn("bg-border -mx-1 my-1 h-px", className)}178      {...props}179    />180  );181}182183function DropdownMenuShortcut({184  className,185  ...props186}: React.ComponentProps<typeof sprawlify.span>) {187  return (188    <sprawlify.span189      data-slot="dropdown-menu-shortcut"190      className={cn(191        "text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-xs tracking-widest",192        className,193      )}194      {...props}195    />196  );197}198199function DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {200  return <DropdownMenuPrimitive.Root data-slot="dropdown-menu-sub" {...props} />;201}202203function DropdownMenuSubTrigger({204  className,205  inset,206  children,207  ...props208}: React.ComponentProps<typeof DropdownMenuPrimitive.TriggerItem> & {209  inset?: boolean;210}) {211  return (212    <DropdownMenuPrimitive.TriggerItem213      data-slot="dropdown-menu-sub-trigger"214      data-inset={inset}215      className={cn(216        "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",217        className,218      )}219      {...props}220    >221      {children}222      <ChevronRightIcon className="ml-auto" />223    </DropdownMenuPrimitive.TriggerItem>224  );225}226227function DropdownMenuSubContent({228  className,229  ...props230}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {231  return (232    <Portal>233      <DropdownMenuPrimitive.Positioner>234        <DropdownMenuPrimitive.Content235          data-slot="dropdown-menu-sub-content"236          className={cn(237            "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",238            className,239          )}240          {...props}241        />242      </DropdownMenuPrimitive.Positioner>243    </Portal>244  );245}246247export {248  DropdownMenu,249  DropdownMenuPortal,250  DropdownMenuTrigger,251  DropdownMenuContent,252  DropdownMenuGroup,253  DropdownMenuLabel,254  DropdownMenuItem,255  DropdownMenuCheckboxItem,256  DropdownMenuRadioGroup,257  DropdownMenuRadioItem,258  DropdownMenuSeparator,259  DropdownMenuShortcut,260  DropdownMenuSub,261  DropdownMenuSubTrigger,262  DropdownMenuSubContent,263};264

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 asChild>
3    <Button variant="outline">Open</Button>
4  </DropdownMenuTrigger>
5  <DropdownMenuContent>
6    <DropdownMenuGroup>
7      <DropdownMenuLabel>My Account</DropdownMenuLabel>
8      <DropdownMenuItem>Profile</DropdownMenuItem>
9      <DropdownMenuItem>Billing</DropdownMenuItem>
10    </DropdownMenuGroup>
11    <DropdownMenuSeparator />
12    <DropdownMenuGroup>
13      <DropdownMenuItem>Team</DropdownMenuItem>
14      <DropdownMenuItem>Subscription</DropdownMenuItem>
15    </DropdownMenuGroup>
16  </DropdownMenuContent>
17</DropdownMenu>

Examples

Avatar

An account switcher dropdown triggered by an avatar.

1import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";2import { Button } from "@/components/ui/button";3import {4  DropdownMenu,

Basic

A basic dropdown menu with labels and separators.

1import { Button } from "@/components/ui/button";2import {3  DropdownMenu,4  DropdownMenuContent,

Checkboxes

Use DropdownMenuCheckboxItem for toggles.

1import * as React from "react";2import { Button } from "@/components/ui/button";3import {4  DropdownMenu,

Checkboxes Icons

Add icons to checkbox items.

1import * as React from "react";2import { Button } from "@/components/ui/button";3import {4  DropdownMenu,

Complex

A richer example combining groups, icons, and submenus.

1import * as React from "react";2import { Button } from "@/components/ui/button";3import {4  DropdownMenu,

Destructive

Use variant="destructive" for irreversible actions.

1import { Button } from "@/components/ui/button";2import {3  DropdownMenu,4  DropdownMenuContent,

Icons

Combine icons with labels for quick scanning.

1import { Button } from "@/components/ui/button";2import {3  DropdownMenu,4  DropdownMenuContent,

Radio Icons

Show radio options with icons.

1import * as React from "react";2import { Button } from "@/components/ui/button";3import {4  DropdownMenu,

Shortcuts

Add DropdownMenuShortcut to show keyboard hints.

1import { Button } from "@/components/ui/button";2import {3  DropdownMenu,4  DropdownMenuContent,

Submenu

Use DropdownMenuSub to nest secondary actions.

1import { Button } from "@/components/ui/button";2import {3  DropdownMenu,4  DropdownMenuContent,

On This Page

InstallationUsageExamplesAvatarBasicCheckboxesCheckboxes IconsComplexDestructiveIconsRadio IconsShortcutsSubmenu

Get PRO

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