Action Menu - Admin Components

Archived: Medusa exports an ActionMenu component from the @medusajs/dashboard package since v2.21.0. Use the exported component instead of building your own. This guide is kept for reference only.

In this guide, you'll learn how to add an action menu to your Medusa Admin customizations.

The Medusa Admin often provides additional actions in a dropdown shown when users click a three-dot icon.

Example of an action menu in the Medusa Admin

To create a component that shows this menu in your customizations, create the file src/admin/components/action-menu.tsx with the following content:

src/admin/components/action-menu.tsx
import { 
  DropdownMenu,
  IconButton,
  clx,
} from "@medusajs/ui"
import { EllipsisHorizontal } from "@medusajs/icons"
import { Link } from "react-router-dom"

export type Action = {
  icon: React.ReactNode
  label: string
  disabled?: boolean
} & (
  | {
      to: string
      onClick?: never
    }
  | {
      onClick: () => void
      to?: never
    }
)

export type ActionGroup = {
  actions: Action[]
}

export type ActionMenuProps = {
  groups: ActionGroup[]
}

export const ActionMenu = ({ groups }: ActionMenuProps) => {
  return (
    <DropdownMenu>
      <DropdownMenu.Trigger asChild>
        <IconButton size="small" variant="transparent">
          <EllipsisHorizontal />
        </IconButton>
      </DropdownMenu.Trigger>
      <DropdownMenu.Content>
        {groups.map((group, index) => {
          if (!group.actions.length) {
            return null
          }

          const isLast = index === groups.length - 1

          return (
            <DropdownMenu.Group key={index}>
              {group.actions.map((action, index) => {
                if (action.onClick) {
                  return (
                    <DropdownMenu.Item
                      disabled={action.disabled}
                      key={index}
                      onClick={(e) => {
                        e.stopPropagation()
                        action.onClick()
                      }}
                      className={clx(
                        "[&_svg]:text-ui-fg-subtle flex items-center gap-x-2",
                        {
                          "[&_svg]:text-ui-fg-disabled": action.disabled,
                        }
                      )}
                    >
                      {action.icon}
                      <span>{action.label}</span>
                    </DropdownMenu.Item>
                  )
                }

                return (
                  <div key={index}>
                    <DropdownMenu.Item
                      className={clx(
                        "[&_svg]:text-ui-fg-subtle flex items-center gap-x-2",
                        {
                          "[&_svg]:text-ui-fg-disabled": action.disabled,
                        }
                      )}
                      asChild
                      disabled={action.disabled}
                    >
                      <Link to={action.to} onClick={(e) => e.stopPropagation()}>
                        {action.icon}
                        <span>{action.label}</span>
                      </Link>
                    </DropdownMenu.Item>
                  </div>
                )
              })}
              {!isLast && <DropdownMenu.Separator />}
            </DropdownMenu.Group>
          )
        })}
      </DropdownMenu.Content>
    </DropdownMenu>
  )
}

The ActionMenu component shows a three-dots icon (or EllipsisHorizontal) from the Medusa Icons package in a button.

When the button is clicked, a dropdown menu is shown with the actions passed in the props.

The component accepts the following props:

Loading...

Example#

Use the ActionMenu component in any widget or UI route.

For example, create the widget src/admin/widgets/product-widget.tsx with the following content:

src/admin/widgets/product-widget.tsx
import { defineWidgetConfig } from "@medusajs/admin-sdk"
import { Pencil } from "@medusajs/icons"
import { Container } from "../components/container"
import { ActionMenu } from "../components/action-menu"

const ProductWidget = () => {
  return (
    <Container>
      <ActionMenu groups={[
        {
          actions: [
            {
              icon: <Pencil />,
              label: "Edit",
              onClick: () => {
                alert("You clicked the edit action!")
              },
            },
          ],
        },
      ]} />
    </Container>
  )
}

export const config = defineWidgetConfig({
  zone: "product.details",
})

export default ProductWidget

This widget also uses a Container custom component.

Use in Header#

You can also use the action menu in the Header component as part of its actions.

For example:

src/admin/widgets/product-widget.tsx
import { defineWidgetConfig } from "@medusajs/admin-sdk"
import { Pencil } from "@medusajs/icons"
import { Container } from "../components/container"
import { Header } from "../components/header"

const ProductWidget = () => {
  return (
    <Container>
      <Header 
        title="Product Widget"
        subtitle="This is my custom product widget"
        actions={[
          {
            type: "action-menu",
            props: {
              groups: [
                {
                  actions: [
                    {
                      icon: <Pencil />,
                      label: "Edit",
                      onClick: () => {
                        alert("You clicked the edit action!")
                      },
                    },
                  ],
                },
              ],
            },
          },
        ]}
      />
    </Container>
  )
}

export const config = defineWidgetConfig({
  zone: "product.details",
})

export default ProductWidget
Was this page helpful?
Ask Bloom
For assistance in your development, use Claude Code Plugins or Docs MCP server in Cursor, VSCode, etc...FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break
⇧↵