1import { Button } from "~/components/ui/button";2import {3 DropdownMenu,4 DropdownMenuContent,5 DropdownMenuGroup,6 DropdownMenuItem,7 DropdownMenuLabel,8 DropdownMenuPortal,9 DropdownMenuSeparator,10 DropdownMenuShortcut,11 DropdownMenuSub,12 DropdownMenuSubContent,13 DropdownMenuSubTrigger,14 DropdownMenuTrigger,15} from "~/components/ui/dropdown-menu";16
17export default function DropdownMenuDemo() {18 return (19 <DropdownMenu>20 <DropdownMenuTrigger as={Button<"button">} variant="no-shadow">21 Open22 </DropdownMenuTrigger>23 <DropdownMenuContent class="w-56">24 <DropdownMenuLabel>My Account</DropdownMenuLabel>25 <DropdownMenuGroup>26 <DropdownMenuItem>27 Profile28 <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>29 </DropdownMenuItem>30 <DropdownMenuItem>31 Billing32 <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>33 </DropdownMenuItem>34 <DropdownMenuItem>35 Settings36 <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>37 </DropdownMenuItem>38 <DropdownMenuItem>39 Keyboard shortcuts40 <DropdownMenuShortcut>⌘K</DropdownMenuShortcut>41 </DropdownMenuItem>42 </DropdownMenuGroup>43 <DropdownMenuSeparator />44 <DropdownMenuGroup>45 <DropdownMenuItem>Team</DropdownMenuItem>46 <DropdownMenuSub>47 <DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>48 <DropdownMenuPortal>49 <DropdownMenuSubContent>50 <DropdownMenuItem>Email</DropdownMenuItem>51 <DropdownMenuItem>Message</DropdownMenuItem>52 <DropdownMenuSeparator />53 <DropdownMenuItem>More...</DropdownMenuItem>54 </DropdownMenuSubContent>55 </DropdownMenuPortal>56 </DropdownMenuSub>57 <DropdownMenuItem>58 New Team59 <DropdownMenuShortcut>⌘+T</DropdownMenuShortcut>60 </DropdownMenuItem>61 </DropdownMenuGroup>62 <DropdownMenuSeparator />63 <DropdownMenuItem>GitHub</DropdownMenuItem>64 <DropdownMenuItem>Support</DropdownMenuItem>65 <DropdownMenuItem disabled>API</DropdownMenuItem>66 <DropdownMenuSeparator />67 <DropdownMenuItem>68 Log out69 <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>70 </DropdownMenuItem>71 </DropdownMenuContent>72 </DropdownMenu>73 );74}
npx shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/dropdown-menu.json
yarn shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/dropdown-menu.json
pnpm dlx shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/dropdown-menu.json
bunx --bun shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/dropdown-menu.json
Install the following dependencies
npm install @kobalte/core
yarn add @kobalte/core
pnpm add @kobalte/core
bun add @kobalte/core
Copy and paste the following code into your project
1import type { PolymorphicProps } from "@kobalte/core/polymorphic";2import type { Component, ComponentProps, JSX, ValidComponent } from "solid-js";3
4import { splitProps } from "solid-js";5import * as DropdownMenuPrimitive from "@kobalte/core/dropdown-menu";6import CheckIcon from "lucide-solid/icons/check";7import ChevronRightIcon from "lucide-solid/icons/chevron-right";8import DotIcon from "lucide-solid/icons/dot";9
10import { cn } from "~/lib/utils";11
12const DropdownMenuTrigger = <T extends ValidComponent = "button">(13 props: PolymorphicProps<T, DropdownMenuPrimitive.DropdownMenuTriggerProps<T>>,14) => {15 return (16 <DropdownMenuPrimitive.Trigger17 data-slot="dropdown-menu-trigger"18 {...props}19 />20 );21};22
23const DropdownMenuPortal = (24 props: DropdownMenuPrimitive.DropdownMenuPortalProps,25) => {26 return (27 <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />28 );29};30
31const DropdownMenuSub = (props: DropdownMenuPrimitive.DropdownMenuSubProps) => {32 return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;33};34
35const DropdownMenuGroup = <T extends ValidComponent = "div">(36 props: PolymorphicProps<T, DropdownMenuPrimitive.DropdownMenuGroupProps<T>>,37) => {38 return (39 <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />40 );41};42
43const DropdownMenuRadioGroup = <44 TValue = string,45 T extends ValidComponent = "div",46>(47 props: PolymorphicProps<48 T,49 DropdownMenuPrimitive.DropdownMenuRadioGroupProps<T, TValue>50 >,51) => {52 return (53 <DropdownMenuPrimitive.RadioGroup54 data-slot="dropdown-menu-radio-group"55 {...props}56 />57 );58};59
60const DropdownMenu: Component<DropdownMenuPrimitive.DropdownMenuRootProps> = (61 props,62) => {63 return (64 <DropdownMenuPrimitive.Root65 data-slot="dropdown-menu"66 gutter={4}67 {...props}68 />69 );70};71
72type DropdownMenuContentProps<T extends ValidComponent = "div"> =73 DropdownMenuPrimitive.DropdownMenuContentProps<T> & {74 class?: string | undefined;75 };76
77const DropdownMenuContent = <T extends ValidComponent = "div">(78 props: PolymorphicProps<T, DropdownMenuContentProps<T>>,79) => {80 const [, rest] = splitProps(props as DropdownMenuContentProps, ["class"]);81 return (82 <DropdownMenuPrimitive.Portal>83 <DropdownMenuPrimitive.Content84 data-slot="dropdown-menu-content"85 class={cn(86 "z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] animate-out overflow-hidden rounded-base border-2 border-border bg-background p-1 text-foreground shadow-md ui-expanded:animate-in",87 props.class,88 )}89 {...rest}90 />91 </DropdownMenuPrimitive.Portal>92 );93};94
95type DropdownMenuItemProps<T extends ValidComponent = "div"> =96 DropdownMenuPrimitive.DropdownMenuItemProps<T> & {97 class?: string | undefined;98 };99
100const DropdownMenuItem = <T extends ValidComponent = "div">(101 props: PolymorphicProps<T, DropdownMenuItemProps<T>>,102) => {103 const [, rest] = splitProps(props as DropdownMenuItemProps, ["class"]);104 return (105 <DropdownMenuPrimitive.Item106 data-slot="dropdown-menu-item"107 class={cn(108 "relative flex cursor-default items-center gap-2 rounded-base px-2 py-1.5 text-sm transition-colors outline-none select-none hover:bg-primary hover:text-primary-foreground focus:border-border ui-disabled:pointer-events-none ui-disabled:opacity-50",109 props.class,110 )}111 {...rest}112 />113 );114};115
116const DropdownMenuShortcut: Component<ComponentProps<"span">> = (props) => {117 const [, rest] = splitProps(props, ["class"]);118 return (119 <span120 data-slot="dropdown-menu-shortcut"121 class={cn("ml-auto text-xs tracking-widest opacity-60", props.class)}122 {...rest}123 />124 );125};126
127const DropdownMenuLabel: Component<128 ComponentProps<"div"> & { inset?: boolean }129> = (props) => {130 const [, rest] = splitProps(props, ["class", "inset"]);131 return (132 <div133 data-slot="dropdown-menu-label"134 class={cn(135 "px-2 py-1.5 text-sm font-semibold",136 props.inset && "pl-8",137 props.class,138 )}139 {...rest}140 />141 );142};143
144type DropdownMenuSeparatorProps<T extends ValidComponent = "hr"> =145 DropdownMenuPrimitive.DropdownMenuSeparatorProps<T> & {146 class?: string | undefined;147 };148
149const DropdownMenuSeparator = <T extends ValidComponent = "hr">(150 props: PolymorphicProps<T, DropdownMenuSeparatorProps<T>>,151) => {152 const [, rest] = splitProps(props as DropdownMenuSeparatorProps, ["class"]);153 return (154 <DropdownMenuPrimitive.Separator155 data-slot="dropdown-menu-separator"156 class={cn("-mx-1 my-1 h-0.5 bg-border", props.class)}157 {...rest}158 />159 );160};161
162type DropdownMenuSubTriggerProps<T extends ValidComponent = "div"> =163 DropdownMenuPrimitive.DropdownMenuSubTriggerProps<T> & {164 class?: string | undefined;165 children?: JSX.Element;166 };167
168const DropdownMenuSubTrigger = <T extends ValidComponent = "div">(169 props: PolymorphicProps<T, DropdownMenuSubTriggerProps<T>>,170) => {171 const [, rest] = splitProps(props as DropdownMenuSubTriggerProps, [172 "class",173 "children",174 ]);175 return (176 <DropdownMenuPrimitive.SubTrigger177 data-slot="dropdown-menu-sub-trigger"178 class={cn(179 "flex cursor-default items-center rounded-base px-2 py-1.5 text-sm outline-none select-none focus:bg-primary ui-expanded:bg-primary",180 props.class,181 )}182 {...rest}183 >184 {props.children}185 <ChevronRightIcon class="ml-auto size-4" />186 </DropdownMenuPrimitive.SubTrigger>187 );188};189
190type DropdownMenuSubContentProps<T extends ValidComponent = "div"> =191 DropdownMenuPrimitive.DropdownMenuSubContentProps<T> & {192 class?: string | undefined;193 };194
195const DropdownMenuSubContent = <T extends ValidComponent = "div">(196 props: PolymorphicProps<T, DropdownMenuSubContentProps<T>>,197) => {198 const [, rest] = splitProps(props as DropdownMenuSubContentProps, ["class"]);199 return (200 <DropdownMenuPrimitive.SubContent201 data-slot="dropdown-menu-sub-content"202 class={cn(203 "shadow-base z-50 min-w-32 origin-[var(--kb-menu-content-transform-origin)] animate-in overflow-hidden rounded-md border-2 bg-background p-1 text-foreground",204 props.class,205 )}206 {...rest}207 />208 );209};210
211type DropdownMenuCheckboxItemProps<T extends ValidComponent = "div"> =212 DropdownMenuPrimitive.DropdownMenuCheckboxItemProps<T> & {213 class?: string | undefined;214 children?: JSX.Element;215 };216
217const DropdownMenuCheckboxItem = <T extends ValidComponent = "div">(218 props: PolymorphicProps<T, DropdownMenuCheckboxItemProps<T>>,219) => {220 const [, rest] = splitProps(props as DropdownMenuCheckboxItemProps, [221 "class",222 "children",223 ]);224 return (225 <DropdownMenuPrimitive.CheckboxItem226 data-slot="dropdown-menu-checkbox-item"227 class={cn(228 "relative flex cursor-default items-center rounded-base py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none focus:bg-primary focus:text-primary-foreground ui-disabled:pointer-events-none ui-disabled:opacity-50",229 props.class,230 )}231 {...rest}232 >233 <span class="absolute left-2 flex size-3.5 items-center justify-center">234 <DropdownMenuPrimitive.ItemIndicator>235 <CheckIcon class="size-4" />236 </DropdownMenuPrimitive.ItemIndicator>237 </span>238 {props.children}239 </DropdownMenuPrimitive.CheckboxItem>240 );241};242
243type DropdownMenuGroupLabelProps<T extends ValidComponent = "span"> =244 DropdownMenuPrimitive.DropdownMenuGroupLabelProps<T> & {245 class?: string | undefined;246 };247
248const DropdownMenuGroupLabel = <T extends ValidComponent = "span">(249 props: PolymorphicProps<T, DropdownMenuGroupLabelProps<T>>,250) => {251 const [, rest] = splitProps(props as DropdownMenuGroupLabelProps, ["class"]);252 return (253 <DropdownMenuPrimitive.GroupLabel254 data-slot="dropdown-menu-group-label"255 class={cn("px-2 py-1.5 text-sm font-semibold", props.class)}256 {...rest}257 />258 );259};260
261type DropdownMenuRadioItemProps<T extends ValidComponent = "div"> =262 DropdownMenuPrimitive.DropdownMenuRadioItemProps<T> & {263 class?: string | undefined;264 children?: JSX.Element;265 };266
267const DropdownMenuRadioItem = <T extends ValidComponent = "div">(268 props: PolymorphicProps<T, DropdownMenuRadioItemProps<T>>,269) => {270 const [, rest] = splitProps(props as DropdownMenuRadioItemProps, [271 "class",272 "children",273 ]);274 return (275 <DropdownMenuPrimitive.RadioItem276 data-slot="dropdown-menu-radio-item"277 class={cn(278 "relative flex cursor-default items-center rounded-base py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none focus:bg-primary focus:text-primary-foreground ui-disabled:pointer-events-none ui-disabled:opacity-50",279 props.class,280 )}281 {...rest}282 >283 <span class="absolute left-2 flex size-3.5 items-center justify-center">284 <DropdownMenuPrimitive.ItemIndicator>285 <DotIcon class="size-10" />286 </DropdownMenuPrimitive.ItemIndicator>287 </span>288 {props.children}289 </DropdownMenuPrimitive.RadioItem>290 );291};292
293export {294 DropdownMenu,295 DropdownMenuTrigger,296 DropdownMenuPortal,297 DropdownMenuContent,298 DropdownMenuItem,299 DropdownMenuShortcut,300 DropdownMenuLabel,301 DropdownMenuSeparator,302 DropdownMenuSub,303 DropdownMenuSubTrigger,304 DropdownMenuSubContent,305 DropdownMenuCheckboxItem,306 DropdownMenuGroup,307 DropdownMenuGroupLabel,308 DropdownMenuRadioGroup,309 DropdownMenuRadioItem,310};
Update the import paths to match your project setup.
1import {2 DropdownMenu,3 DropdownMenuCheckboxItem,4 DropdownMenuContent,5 DropdownMenuGroup,6 DropdownMenuGroupLabel,7 DropdownMenuItem,8 DropdownMenuLabel,9 DropdownMenuPortal,10 DropdownMenuRadioGroup,11 DropdownMenuRadioItem,12 DropdownMenuSeparator,13 DropdownMenuShortcut,14 DropdownMenuSub,15 DropdownMenuSubContent,16 DropdownMenuSubTrigger,17 DropdownMenuTrigger,18} from "~/components/ui/dropdown-menu";
1<DropdownMenu>2 <DropdownMenuTrigger>Open</DropdownMenuTrigger>3 <DropdownMenuContent>4 <DropdownMenuLabel>My Account</DropdownMenuLabel>5 <DropdownMenuSeparator />6 <DropdownMenuItem>Profile</DropdownMenuItem>7 <DropdownMenuItem>Billing</DropdownMenuItem>8 <DropdownMenuItem>Team</DropdownMenuItem>9 <DropdownMenuItem>Subscription</DropdownMenuItem>10 </DropdownMenuContent>11</DropdownMenu>