Inputs

Dropdown Menu

List of options or actions presented to the user.

Installation

  1. 1

    Install dependencies:

    npm install @radix-ui/react-dropdown-menu @remixicon/react
  2. 2

    Add component:

    Copy and paste the code into your project’s component directory. Do not forget to update the import paths.
    // Tremor Dropdown Menu [v0.0.2]
    "use client"
    import * as React from "react"import * as DropdownMenuPrimitives from "@radix-ui/react-dropdown-menu"import {  RiArrowRightSLine,  RiCheckboxBlankCircleLine,  RiCheckLine,  RiRadioButtonFill,} from "@remixicon/react"
    import { cx } from "@/lib/utils"
    const DropdownMenu = DropdownMenuPrimitives.RootDropdownMenu.displayName = "DropdownMenu"
    const DropdownMenuTrigger = DropdownMenuPrimitives.TriggerDropdownMenuTrigger.displayName = "DropdownMenuTrigger"
    const DropdownMenuGroup = DropdownMenuPrimitives.GroupDropdownMenuGroup.displayName = "DropdownMenuGroup"
    const DropdownMenuSubMenu = DropdownMenuPrimitives.SubDropdownMenuSubMenu.displayName = "DropdownMenuSubMenu"
    const DropdownMenuRadioGroup = DropdownMenuPrimitives.RadioGroupDropdownMenuRadioGroup.displayName = "DropdownMenuRadioGroup"
    const DropdownMenuSubMenuTrigger = React.forwardRef<  React.ElementRef<typeof DropdownMenuPrimitives.SubTrigger>,  Omit<    React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitives.SubTrigger>,    "asChild"  >>(({ className, children, ...props }, forwardedRef) => (  <DropdownMenuPrimitives.SubTrigger    ref={forwardedRef}    className={cx(      // base      "relative flex cursor-default select-none items-center rounded py-1.5 pl-2 pr-1 outline-none transition-colors data-[state=checked]:font-semibold sm:text-sm",      // text color      "text-gray-900 dark:text-gray-50",      // disabled      "data-[disabled]:pointer-events-none data-[disabled]:text-gray-400 data-[disabled]:hover:bg-none dark:data-[disabled]:text-gray-600",      // focus      "focus-visible:bg-gray-100 data-[state=open]:bg-gray-100 focus-visible:dark:bg-gray-900 data-[state=open]:dark:bg-gray-900",      // hover      "hover:bg-gray-100 hover:dark:bg-gray-900",      //      className,    )}    {...props}  >    {children}    <RiArrowRightSLine className="ml-auto size-4 shrink-0" aria-hidden="true" />  </DropdownMenuPrimitives.SubTrigger>))DropdownMenuSubMenuTrigger.displayName = "DropdownMenuSubMenuTrigger"
    const DropdownMenuSubMenuContent = React.forwardRef<  React.ElementRef<typeof DropdownMenuPrimitives.SubContent>,  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitives.SubContent>>(({ className, collisionPadding = 8, ...props }, forwardedRef) => (  <DropdownMenuPrimitives.Portal>    <DropdownMenuPrimitives.SubContent      ref={forwardedRef}      collisionPadding={collisionPadding}      className={cx(        // base        "relative z-50 overflow-hidden rounded-md border p-1 shadow-xl shadow-black/[2.5%]",        // widths        "min-w-32",        // heights        "max-h-[var(--radix-popper-available-height)]",        // background color        "bg-white dark:bg-gray-950",        // text color        "text-gray-900 dark:text-gray-50",        // border color        "border-gray-200 dark:border-gray-800",        // transition        "will-change-[transform,opacity]",        // "data-[state=open]:animate-slideDownAndFade",        "data-[state=closed]:animate-hide",        "data-[side=bottom]:animate-slideDownAndFade data-[side=left]:animate-slideLeftAndFade data-[side=right]:animate-slideRightAndFade data-[side=top]:animate-slideUpAndFade",        className,      )}      {...props}    />  </DropdownMenuPrimitives.Portal>))DropdownMenuSubMenuContent.displayName = "DropdownMenuSubMenuContent"
    const DropdownMenuContent = React.forwardRef<  React.ElementRef<typeof DropdownMenuPrimitives.Content>,  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitives.Content>>(  (    {      className,      sideOffset = 8,      collisionPadding = 8,      align = "center",      loop = true,      ...props    },    forwardedRef,  ) => (    <DropdownMenuPrimitives.Portal>      <DropdownMenuPrimitives.Content        ref={forwardedRef}        className={cx(          // base          "relative z-50 overflow-hidden rounded-md border p-1 shadow-xl shadow-black/[2.5%]",          // widths          "min-w-48",          // heights          "max-h-[var(--radix-popper-available-height)]",          // background color          "bg-white dark:bg-gray-950",          // text color          "text-gray-900 dark:text-gray-50",          // border color          "border-gray-200 dark:border-gray-800",          // transition          "will-change-[transform,opacity]",          "data-[state=closed]:animate-hide",          "data-[side=bottom]:animate-slideDownAndFade data-[side=left]:animate-slideLeftAndFade data-[side=right]:animate-slideRightAndFade data-[side=top]:animate-slideUpAndFade",          className,        )}        sideOffset={sideOffset}        align={align}        collisionPadding={collisionPadding}        loop={loop}        {...props}      />    </DropdownMenuPrimitives.Portal>  ),)DropdownMenuContent.displayName = "DropdownMenuContent"
    const DropdownMenuItem = React.forwardRef<  React.ElementRef<typeof DropdownMenuPrimitives.Item>,  Omit<    React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitives.Item>,    "asChild"  > & {    shortcut?: string    hint?: string  }>(({ className, shortcut, hint, children, ...props }, forwardedRef) => (  <DropdownMenuPrimitives.Item    ref={forwardedRef}    className={cx(      // base      "group/DropdownMenuItem relative flex cursor-pointer select-none items-center rounded py-1.5 pl-2 pr-1 outline-none transition-colors data-[state=checked]:font-semibold sm:text-sm",      // text color      "text-gray-900 dark:text-gray-50",      // disabled      "data-[disabled]:pointer-events-none data-[disabled]:text-gray-400 data-[disabled]:hover:bg-none dark:data-[disabled]:text-gray-600",      // focus      "focus-visible:bg-gray-100 focus-visible:dark:bg-gray-900",      // hover      "hover:bg-gray-100 hover:dark:bg-gray-900",      className,    )}    tremor-id="tremor-raw"    {...props}  >    {children}    {hint && (      <span        className={cx("ml-auto pl-2 text-sm text-gray-400 dark:text-gray-600")}      >        {hint}      </span>    )}    {shortcut && (      <span        className={cx("ml-auto pl-2 text-sm text-gray-400 dark:text-gray-600")}      >        {shortcut}      </span>    )}  </DropdownMenuPrimitives.Item>))DropdownMenuItem.displayName = "DropdownMenuItem"
    const DropdownMenuCheckboxItem = React.forwardRef<  React.ElementRef<typeof DropdownMenuPrimitives.CheckboxItem>,  Omit<    React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitives.CheckboxItem>,    "asChild"  > & {    shortcut?: string    hint?: string  }>(  (    { className, hint, shortcut, children, checked, ...props },    forwardedRef,  ) => (    <DropdownMenuPrimitives.CheckboxItem      ref={forwardedRef}      className={cx(        // base        "relative flex cursor-pointer select-none items-center gap-x-2 rounded py-1.5 pl-8 pr-1 outline-none transition-colors data-[state=checked]:font-semibold sm:text-sm",        // text color        "text-gray-900 dark:text-gray-50",        // disabled        "data-[disabled]:pointer-events-none data-[disabled]:text-gray-400 data-[disabled]:hover:bg-none dark:data-[disabled]:text-gray-600",        // focus        "focus-visible:bg-gray-100 focus-visible:dark:bg-gray-900",        // hover        "hover:bg-gray-100 hover:dark:bg-gray-900",        className,      )}      checked={checked}      {...props}    >      <span className="absolute left-2 flex size-4 items-center justify-center">        <DropdownMenuPrimitives.ItemIndicator>          <RiCheckLine            aria-hidden="true"            className="size-full shrink-0 text-gray-800 dark:text-gray-200"          />        </DropdownMenuPrimitives.ItemIndicator>      </span>      {children}      {hint && (        <span          className={cx(            "ml-auto text-sm font-normal text-gray-400 dark:text-gray-600",          )}        >          {hint}        </span>      )}      {shortcut && (        <span          className={cx(            "ml-auto text-sm font-normal tracking-widest text-gray-400 dark:border-gray-800 dark:text-gray-600",          )}        >          {shortcut}        </span>      )}    </DropdownMenuPrimitives.CheckboxItem>  ),)DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem"
    const DropdownMenuRadioItem = React.forwardRef<  React.ElementRef<typeof DropdownMenuPrimitives.RadioItem>,  Omit<    React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitives.RadioItem>,    "asChild"  > & {    shortcut?: string    hint?: string  }>(({ className, hint, shortcut, children, ...props }, forwardedRef) => (  <DropdownMenuPrimitives.RadioItem    ref={forwardedRef}    className={cx(      // base      "group/DropdownMenuRadioItem relative flex cursor-pointer select-none items-center gap-x-2 rounded py-1.5 pl-8 pr-1 outline-none transition-colors data-[state=checked]:font-semibold sm:text-sm",      // text color      "text-gray-900 dark:text-gray-50",      // disabled      "data-[disabled]:pointer-events-none data-[disabled]:text-gray-400 data-[disabled]:hover:bg-none dark:data-[disabled]:text-gray-600",      // focus      "focus-visible:bg-gray-100 focus-visible:dark:bg-gray-900",      // hover      "hover:bg-gray-100 hover:dark:bg-gray-900",      className,    )}    {...props}  >    <span className="absolute left-2 flex size-4 items-center justify-center">      <RiRadioButtonFill        aria-hidden="true"        className="size-full shrink-0 text-blue-500 group-data-[state=checked]/DropdownMenuRadioItem:flex group-data-[state=unchecked]/DropdownMenuRadioItem:hidden dark:text-blue-500"      />      <RiCheckboxBlankCircleLine        aria-hidden="true"        className="size-full shrink-0 text-gray-300 group-data-[state=unchecked]/DropdownMenuRadioItem:flex group-data-[state=checked]/DropdownMenuRadioItem:hidden dark:text-gray-700"      />    </span>    {children}    {hint && (      <span        className={cx(          "ml-auto text-sm font-normal text-gray-400 dark:text-gray-600",        )}      >        {hint}      </span>    )}    {shortcut && (      <span        className={cx(          "ml-auto text-sm font-normal tracking-widest text-gray-400 dark:border-gray-800 dark:text-gray-600",        )}      >        {shortcut}      </span>    )}  </DropdownMenuPrimitives.RadioItem>))DropdownMenuRadioItem.displayName = "DropdownMenuRadioItem"
    const DropdownMenuLabel = React.forwardRef<  React.ElementRef<typeof DropdownMenuPrimitives.Label>,  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitives.Label>>(({ className, ...props }, forwardedRef) => (  <DropdownMenuPrimitives.Label    ref={forwardedRef}    className={cx(      // base      "px-2 py-2 text-xs font-medium tracking-wide",      // text color      "text-gray-500 dark:text-gray-500",      className,    )}    {...props}  />))DropdownMenuLabel.displayName = "DropdownMenuLabel"
    const DropdownMenuSeparator = React.forwardRef<  React.ElementRef<typeof DropdownMenuPrimitives.Separator>,  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitives.Separator>>(({ className, ...props }, forwardedRef) => (  <DropdownMenuPrimitives.Separator    ref={forwardedRef}    className={cx(      "-mx-1 my-1 h-px border-t border-gray-200 dark:border-gray-800",      className,    )}    {...props}  />))DropdownMenuSeparator.displayName = "DropdownMenuSeparator"
    const DropdownMenuIconWrapper = ({  className,  ...props}: React.HTMLAttributes<HTMLSpanElement>) => {  return (    <div      className={cx(        // text color        "text-gray-600 dark:text-gray-400",        // disabled        "group-data-[disabled]/DropdownMenuItem:text-gray-400 group-data-[disabled]/DropdownMenuItem:dark:text-gray-700",        className,      )}      {...props}    />  )}DropdownMenuIconWrapper.displayName = "DropdownMenuIconWrapper"
    export {  DropdownMenu,  DropdownMenuTrigger,  DropdownMenuSubMenuTrigger,  DropdownMenuSubMenu,  DropdownMenuSubMenuContent,  DropdownMenuGroup,  DropdownMenuContent,  DropdownMenuItem,  DropdownMenuRadioGroup,  DropdownMenuRadioItem,  DropdownMenuCheckboxItem,  DropdownMenuIconWrapper,  DropdownMenuLabel,  DropdownMenuSeparator,}
    
  3. 3

    Update tailwind.config.ts

    import type { Config } from 'tailwindcss';export default {  // ...  theme: {    extend: {      keyframes: {        hide: {          from: { opacity: "1" },          to: { opacity: "0" },        },        slideDownAndFade: {          from: { opacity: "0", transform: "translateY(-6px)" },          to: { opacity: "1", transform: "translateY(0)" },        },        slideLeftAndFade: {          from: { opacity: "0", transform: "translateX(6px)" },          to: { opacity: "1", transform: "translateX(0)" },        },        slideUpAndFade: {          from: { opacity: "0", transform: "translateY(6px)" },          to: { opacity: "1", transform: "translateY(0)" },        },        slideRightAndFade: {          from: { opacity: "0", transform: "translateX(-6px)" },          to: { opacity: "1", transform: "translateX(0)" },        },      },      animation: {        hide: "hide 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideDownAndFade:          "slideDownAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideLeftAndFade:          "slideLeftAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideUpAndFade: "slideUpAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",        slideRightAndFade:          "slideRightAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1)",      },    },  },  // ...} satisfies Config;

Example: Simple

Example: With RadioItem

Example: With CheckboxItem

API Reference: DropdownMenu

This component uses the Radix UI API.

API Reference: DropdownMenuTrigger

This component uses the Radix UI API.

API Reference: DropdownMenuSubMenuTrigger

This component uses the Radix UI API.

API Reference: DropdownMenuSubMenu

This component uses the Radix UI API.

API Reference: DropdownMenuSubMenuContent

This component uses the Radix UI API.

API Reference: DropdownMenuGroup

This component uses the Radix UI API.

API Reference: DropdownMenuContent

This component uses the Radix UI API.

API Reference: DropdownMenuItem

This component uses the Radix UI API.

Note that asChild is omitted.

shortcut
string
Add a keyboard shortcut.
hint
string
Add a hint.

API Reference: DropdownMenuRadioGroup

This component uses the Radix UI API.

API Reference: DropdownMenuRadioItem

This component uses the Radix UI API.

Note that asChild is omitted.

shortcut
string
Add a keyboard shortcut.
hint
string
Add a hint.

API Reference: DropdownMenuCheckboxItem

This component uses the Radix UI API.

Note that asChild is omitted.

shortcut
string
Add a keyboard shortcut.
hint
string
Add a hint.

API Reference: DropdownMenuIconWrapper

This component extens an HTML "div".

API Reference: DropdownMenuLabel

This component uses the Radix UI API.

API Reference: DropdownMenuSeparator

This component uses the Radix UI API.