DropdownMenu
Display a dropdown menu.
#
Documentation
#
#
Usage
#
Use the DropdownMenu
, DropdownMenuTrigger
, and DropdownMenuContent
components to build out menus.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@optiaxiom/react";
import { IconLogout, IconUser } from "@tabler/icons-react";
export function App() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem icon={<IconUser />}>View Profile</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem icon={<IconLogout />}>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Controlled
#
Use the open
and defaultOpen
props to toggle between controlled and uncontrolled usage. And combine it with onOpenChange
to listen for changes to the state.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
Flex,
Switch,
} from "@optiaxiom/react";
import { IconLogout, IconUser } from "@tabler/icons-react";
import { useState } from "react";
export function App() {
const [keepOpen, setKeepOpen] = useState(false);
const [open, setOpen] = useState(false);
return (
<Flex flexDirection="row">
<Switch onCheckedChange={setKeepOpen}>Keep menu open</Switch>
<DropdownMenu
modal={false}
onOpenChange={(flag) => setOpen(flag || keepOpen)}
open={open}
>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem icon={<IconUser />}>View Profile</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem icon={<IconLogout />}>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</Flex>
);
}
#
Non modal usage
#
By default scrolling and interactions with outside elements is disabled when menu is open. Set modal
prop to false
in order to render a non-modal dropdown.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@optiaxiom/react";
import { IconLogout, IconUser } from "@tabler/icons-react";
export function App() {
return (
<DropdownMenu modal={false}>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem icon={<IconUser />}>View Profile</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem icon={<IconLogout />}>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Trigger
#
#
Customize trigger
#
By default we use the Button
component for the menu trigger which accepts all of the existing button props.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@optiaxiom/react";
import { IconDots, IconLogout, IconUser } from "@tabler/icons-react";
export function App() {
return (
<DropdownMenu>
<DropdownMenuTrigger
appearance="subtle"
aria-label="My Account"
icon={<IconDots />}
/>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem icon={<IconUser />}>View Profile</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem icon={<IconLogout />}>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Content
#
#
Menu position
#
Use the align
and side
props on DropdownMenuContent
to change the default position of the dropdown.
import type { ComponentPropsWithRef } from "react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@optiaxiom/react";
import { IconLogout, IconUser } from "@tabler/icons-react";
export function App({
align,
side,
}: Pick<ComponentPropsWithRef<typeof DropdownMenuContent>, "align" | "side">) {
return (
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent align={align} side={side}>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem icon={<IconUser />}>View Profile</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem icon={<IconLogout />}>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Item
#
#
Appearance
#
Use the intent
prop to control the appearance of items.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@optiaxiom/react";
import { IconPencil, IconTrash } from "@tabler/icons-react";
export function App() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem icon={<IconPencil />}>Edit</DropdownMenuItem>
<DropdownMenuItem icon={<IconTrash />} intent="danger">
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Description
#
Use the description
prop to add secondary text to items.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@optiaxiom/react";
export function App() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Actions</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem description="Create a new task">
New task
</DropdownMenuItem>
<DropdownMenuItem description="Copy this task">
Copy task
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem intent="danger">Delete task</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Disabled items
#
Use the disabled
prop on menu items to disable them.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@optiaxiom/react";
import { IconLogout, IconUser, IconUsers } from "@tabler/icons-react";
export function App() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem icon={<IconUser />}>View Profile</DropdownMenuItem>
<DropdownMenuItem disabled icon={<IconUsers />}>
Team Management
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem icon={<IconLogout />}>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Selection
#
Use the onSelect
prop to handle selection of items.
Last selected item:
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
Flex,
Text,
} from "@optiaxiom/react";
import { IconLogout, IconUser } from "@tabler/icons-react";
import { useState } from "react";
export function App() {
const [selected, setSelected] = useState("");
return (
<Flex flexDirection="row">
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem
icon={<IconUser />}
onSelect={() => setSelected("view")}
>
View Profile
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
icon={<IconLogout />}
onSelect={() => setSelected("logout")}
>
Logout
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<Text>Last selected item: {selected}</Text>
</Flex>
);
}
#
Left and right addons
#
Use the icon
, addonBefore
, and addonAfter
props to add icons, text, or any other element to the start or end of the menu items.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
Kbd,
} from "@optiaxiom/react";
import { IconLogout, IconSettings, IconUser } from "@tabler/icons-react";
export function App() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem
addonAfter={
<Kbd keys={["option", "shift"]} variant="subtle">
P
</Kbd>
}
icon={<IconSettings />}
>
Preferences
</DropdownMenuItem>
<DropdownMenuItem icon={<IconUser />}>View Profile</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
addonAfter={
<Kbd keys={["option", "shift"]} variant="subtle">
Q
</Kbd>
}
icon={<IconLogout />}
>
Logout
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Label
#
Use the DropdownMenuLabel
component to render a read-only label.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@optiaxiom/react";
import { IconLogout, IconUser } from "@tabler/icons-react";
export function App() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem icon={<IconUser />}>View Profile</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem icon={<IconLogout />}>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Dialogs inside menus
#
Combine dropdown menus with dialog to show alerts when selecting an item.
Make sure to enable asChild
prop on AlertDialogTrigger
and call event.preventDefault()
in the item onSelect
handler.
import {
AlertDialog,
AlertDialogAction,
AlertDialogBody,
AlertDialogCancel,
AlertDialogContent,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTrigger,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@optiaxiom/react";
import { IconPencil, IconTrash } from "@tabler/icons-react";
export function App() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem icon={<IconPencil />}>Edit</DropdownMenuItem>
<AlertDialog>
<AlertDialogTrigger asChild>
<DropdownMenuItem
icon={<IconTrash />}
intent="danger"
onSelect={(event) => event.preventDefault()}
>
Delete
</DropdownMenuItem>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>Are you sure?</AlertDialogHeader>
<AlertDialogBody>
The task and all content will be deleted.
</AlertDialogBody>
<AlertDialogFooter>
<AlertDialogCancel />
<AlertDialogAction>Yes, delete</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</DropdownMenuContent>
</DropdownMenu>
);
}
#
Related
#
Autocomplete
Text field with inline autocomplete to show suggestions while allowing freeform user input.
Select
Single select combobox widget to allow selection from a fixed set of options.
#
Props
#
#
DropdownMenu
#
Doesn't render its own HTML element.
Prop |
---|
defaultOpen The initial open state in uncontrolled mode. false | true |
modal When enabled interaction with outside elements will be disabled and only dropdown content will be visible to screen readers. false | true |
onOpenChange Handler that is called when the open state changes. (open: boolean) => void |
open The open state in controlled mode. false | true |
#
DropdownMenuTrigger
#
Supports all Button props in addition to its own. Renders a <button>
element.
Prop |
---|
addonAfter Display content inside the button after ReactNode |
addonBefore Display content inside the button before ReactNode |
appearance Control the appearance by selecting between the different button types. "default" | "danger" | "primary" | "subtle" | "danger-outline" | "inverse" |
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details. false | true |
className string |
disabled Whether the button is disabled. false | true |
icon Display an icon before or after the button content or omit ReactNode |
iconOnly Whether button should have square shape. false | true |
iconPosition Control whether to show the icon before or after the button content. "end" | "start" |
loading Whether to show loading spinner inside the button. false | true |
size Control the size of the button. "sm" | "md" | "lg" |
#
DropdownMenuContent
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
align "center" | "end" | "start" Default: start |
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details. false | true |
className string |
loading Whether to show loading spinner inside the menu. false | true |
maxH Whether to restrict the max-height of the content. Content is also restricted by the available height in the screen relative to the trigger. "xs" | "sm" | "md" | "lg" | "full" |
minW Whether to set the min-width to the width of the trigger. "0" | "trigger" |
onCloseAutoFocus Event handler called when auto-focusing on close. Can be prevented. (event: Event) => void |
onEscapeKeyDown (event: KeyboardEvent) => void |
onFocusOutside (event: FocusOutsideEvent) => void |
onInteractOutside (event: FocusOutsideEvent | PointerDownOutsideEvent) => void |
onPointerDownOutside (event: PointerDownOutsideEvent) => void |
side "bottom" | "left" | "right" | "top" |
#
DropdownMenuItem
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
addonAfter Display content inside the item after ReactNode |
addonBefore Display content inside the item before ReactNode |
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details. false | true |
className string |
description Add secondary text after the primary label. ReactNode |
disabled false | true |
icon Display an icon before the item content. ReactNode |
intent Control the appearance by selecting between the different item types. "danger" | "neutral" |
onSelect (event: Event) => void |
textValue string |
#
DropdownMenuLabel
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details. false | true |
className string |
#
DropdownMenuGroup
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details. false | true |
className string |
#
DropdownMenuSeparator
#
Supports all Separator props in addition to its own. Renders a <div>
element.
Prop |
---|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details. false | true |
className string |
#
DropdownMenuSub
#
Doesn't render its own HTML element.
Prop |
---|
defaultOpen The initial open state in uncontrolled mode. false | true |
onOpenChange Handler that is called when the open state changes. (open: boolean) => void |
open The open state in controlled mode. false | true |
#
DropdownMenuSubTrigger
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
addonAfter Display content inside the item after ReactNode |
addonBefore Display content inside the item before ReactNode |
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details. false | true |
className string |
description Add secondary text after the primary label. ReactNode |
disabled false | true |
icon Display an icon before the item content. ReactNode |
intent Control the appearance by selecting between the different item types. "danger" | "neutral" |
textValue string |
#
DropdownMenuSubContent
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details. false | true |
className string |
maxH Whether to restrict the max-height of the content. Content is also restricted by the available height in the screen relative to the trigger. "xs" | "sm" | "md" | "lg" | "full" |
minW Whether to set the min-width to the width of the trigger. "0" | "trigger" |
onEscapeKeyDown (event: KeyboardEvent) => void |
onFocusOutside (event: FocusOutsideEvent) => void |
onInteractOutside (event: FocusOutsideEvent | PointerDownOutsideEvent) => void |
onPointerDownOutside (event: PointerDownOutsideEvent) => void |
#
Changelog
#
#
0.1.0
#
- Added component