Dropdown
基础导航基于 Bootstrap 5 的下拉菜单组件,Dropdown 系列(Dropdown、DropdownToggle、DropdownMenu、DropdownItem 等)用于在按钮旁弹出上下文菜单,支持分割按钮、尺寸调整、深色菜单、六个展开方向、菜单项激活/禁用状态、标题/分割线/纯文本、表单菜单、菜单对齐、自动关闭策略、受控模式与键盘导航
Component Demo
Basic usage and examples of the Dropdown component
基础用法
Dropdown 渲染 `div.dropdown`,DropdownToggle 渲染 `button.btn.dropdown-toggle`, DropdownMenu 渲染 `div.dropdown-menu`,展开时自动添加 `show` 类并设置 `aria-expanded`
分割按钮
SplitButton 渲染 `div.btn-group`,左侧主按钮触发 action,右侧箭头按钮( `dropdown-toggle-split`)展开菜单
尺寸
size 分别渲染 `btn-lg`/`btn-sm` 类,与 Bootstrap 的按钮尺寸规则一致
深色菜单
为 DropdownMenu 设置 variant="dark"(或使用 DropdownButton 的 menuVariant)渲染 `dropdown-menu-dark` 深色菜单
展开方向
drop 分别渲染 `dropup`、`dropup dropup-center`、`dropdown dropdown-center`、 `dropend`、`dropstart` 类,箭头方向与菜单定位自动匹配
菜单项
active 渲染 `active` 类与 `aria-current`;disabled 渲染 `disabled` 类、 `aria-disabled` 并移除 tabIndex;设置了 href 的菜单项渲染为 `a` 标签
选择回调
当前选择:未选择。点击菜单项后 eventKey 通过 onSelect 回调传出,默认自动关闭菜单
菜单内容
DropdownHeader 渲染 `h6.dropdown-header`,DropdownDivider 渲染 `hr.dropdown-divider`,DropdownItemText 渲染 `span.dropdown-item-text`
表单菜单
通过 as="form" 将菜单渲染为表单,表单控件不是菜单项,交互不会触发自动关闭
菜单对齐
align="end" 渲染 `dropdown-menu-end` 类;对象形式按断点生成 `dropdown-menu-lg-end` 等响应式类
自动关闭策略
autoClose 控制菜单的关闭时机:true 为默认行为,inside/outside 分别只在菜单内/外触发, false 只能通过触发按钮或 Esc 键关闭
受控模式
当前展开状态:false。传入 show 后 Dropdown 变为受控组件,展开状态完全由 onToggle 驱动的外部 state 决定
API Documentation
Complete API reference for the Dropdown component
Props
Dropdown
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
as | ElementType | 'div' | 根元素标签 |
align | DropdownAlignOption | - | 菜单对齐,`"start"`/`"end"` 渲染 `dropdown-menu-start`/`dropdown-menu-end` 类;对象形式按断点生成响应式的 `dropdown-menu-{断点}-{对齐}` 类,`xs` 同时作为定位计算的基准对齐 |
autoClose | DropdownAutoClose | true | 自动关闭策略:`true` 选择菜单项或点击外部都关闭;`"inside"` 仅选择菜单项时关闭;`"outside"` 仅点击外部时关闭;`false` 永不自动关闭 |
defaultShow | boolean | false | 非受控模式下的初始展开状态 |
drop | DropdownDirection | 'down' | 展开方向,`"up"`/`"up-centered"`/`"down"`/`"down-centered"`/`"start"`/`"end"` 分别渲染 `dropup`、`dropup dropup-center`、`dropdown`、`dropdown dropdown-center`、`dropstart`、`dropend` 类 |
flip | boolean | true | 是否允许菜单靠近视口边缘时翻转到相反方向 |
focusFirstItemOnShow | 'keyboard' | boolean | false | 展开时是否聚焦第一个菜单项,`"keyboard"` 表示仅通过键盘(如回车激活触发按钮)展开时聚焦 |
onSelect | SelectCallback | - | 选择回调,点击 DropdownItem 且事件未被阻止时触发 |
onToggle | ToggleCallback | - | 展开状态变化回调,配合 `show` 实现受控模式 |
popperConfig | DropdownPositionConfig | - | 自定义定位配置,可分别覆盖 `flip`(是否允许翻转)、`offset`([水平偏移, 间距] 元组,默认 `[0, 2]`)与 `padding`(与视口边缘的最小距离,默认 2) |
renderMenuOnMount | boolean | false | 是否在首次渲染时就挂载菜单,默认首次展开时才挂载 |
show | boolean | - | 受控的展开状态,需配合 onToggle 更新 |
DropdownToggle
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
as | ElementType | - | 触发按钮标签,默认渲染 `button.btn.dropdown-toggle` |
children | ReactNode | - | 按钮内容;split 模式下未设置时渲染无障碍隐藏标签 |
disabled | boolean | false | 禁用触发按钮 |
id | string | - | 触发按钮 id,同时作为菜单的 `aria-labelledby` 关联 |
size | ButtonSize | - | 按钮尺寸,`lg`/`sm` 渲染 `btn-lg`/`btn-sm` |
split | boolean | false | 分割按钮模式,追加 `dropdown-toggle-split` 类并隐藏按钮文字 |
toggleLabel | string | 'Toggle dropdown' | split 模式下屏幕阅读器可读的触发按钮标签 |
type | 'button' | 'reset' | 'submit' | 'button' | 渲染为按钮时的 type 属性 |
variant | ButtonVariant | - | 按钮颜色变体 |
DropdownMenu
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
align | DropdownAlignOption | - | 菜单对齐,覆盖 Dropdown 的 align 设置 |
as | ElementType | 'div' | 菜单容器标签,默认渲染 `div.dropdown-menu`,内置表单时可用 `as="form"` |
flip | boolean | - | 是否允许翻转,覆盖 Dropdown 的 flip 设置 |
popperConfig | DropdownPositionConfig | - | 自定义定位配置,覆盖 Dropdown 的 popperConfig 设置 |
renderOnMount | boolean | false | 是否在首次渲染时挂载菜单,与 Dropdown 的 renderMenuOnMount 合并(任一为 true 即挂载) |
show | boolean | - | 独立使用(不在 Dropdown 内)时手动控制展开状态 |
variant | DropdownMenuVariant | - | 菜单变体,`"dark"` 渲染 `dropdown-menu-dark` 深色菜单类 |
DropdownItem
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
active | boolean | false | 激活状态,渲染 `active` 类与 `aria-current="true"` |
as | ElementType | - | 渲染的元素标签,设置了 `href` 默认渲染 `a`,否则渲染 `button` |
disabled | boolean | false | 禁用状态,渲染 `disabled` 类与 `aria-disabled`;按钮同时设置原生 disabled 并移除 tabIndex |
eventKey | EventKey | - | 关联 Dropdown onSelect 回调的 key,未设置时回调收到 null |
href | string | - | 链接地址,设置后渲染为 `a` 标签 |
onSelect | SelectCallback | - | 选择回调,触发后事件继续冒泡到 Dropdown |
DropdownItemText
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
as | ElementType | 'span' | 渲染的元素标签,默认渲染 `span.dropdown-item-text` 纯文本条目 |
DropdownHeader
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
as | ElementType | 'h6' | 渲染的元素标签,默认渲染 `h6.dropdown-header` 分组标题 |
DropdownDivider
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
as | ElementType | 'hr' | 渲染的元素标签,默认渲染 `hr.dropdown-divider` 分割线 |
DropdownButton
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
title | ReactNode | - | 触发按钮文案 |
disabled | boolean | false | 禁用触发按钮 |
id | string | - | 触发按钮 id,同时作为菜单的 `aria-labelledby` 关联 |
menuVariant | DropdownMenuVariant | - | 菜单变体,透传给 DropdownMenu 的 variant |
size | ButtonSize | - | 按钮尺寸,`lg`/`sm` 渲染 `btn-lg`/`btn-sm` |
toggleClassName | string | - | 触发按钮的自定义类名 |
type | 'button' | 'reset' | 'submit' | - | 渲染为按钮时的 type 属性 |
variant | ButtonVariant | - | 按钮颜色变体 |
children | ReactNode | - | 菜单内容,通常由 DropdownItem 等组成;其余 Dropdown 属性(align、autoClose、drop、flip、onSelect、onToggle、popperConfig、renderMenuOnMount、show、defaultShow 等)直接继承 |
SplitButton
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
href | string | - | 主按钮链接,设置后主按钮渲染为 `a` 标签 |
toggleLabel | string | - | 分割箭头按钮的屏幕阅读器标签,透传给 DropdownToggle 的 toggleLabel |
Common Props
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | ReactNode | - | 组件内容 |
className | string | - | 自定义类名 |
...rest | HTMLAttributes | - | 透传原生元素属性(如 `onClick`、`style`、`role` 等) |
Type Definitions
EventKey
菜单项事件 key 类型
export type EventKey = number | string;SelectCallback
选择回调函数类型
export type SelectCallback = (eventKey: EventKey | null, event: SyntheticEvent) => void;ToggleCallback
展开状态变化回调函数类型
export type ToggleCallback = (
nextShow: boolean,
event?: Event | SyntheticEvent,
source?: DropdownToggleSource,
) => void;DropdownAlign
菜单对齐类型
export type DropdownAlign = 'end' | 'start';DropdownAlignOption
菜单对齐选项,支持按断点配置响应式对齐
export interface DropdownAlignMap {
lg?: DropdownAlign;
md?: DropdownAlign;
sm?: DropdownAlign;
xl?: DropdownAlign;
xs?: DropdownAlign;
xxl?: DropdownAlign;
}
export type DropdownAlignOption = DropdownAlign | DropdownAlignMap;DropdownAutoClose
自动关闭策略类型
export type DropdownAutoClose = 'inside' | 'outside' | boolean;DropdownDirection
展开方向类型
export type DropdownDirection = 'down-centered' | 'down' | 'end' | 'start' | 'up-centered' | 'up';DropdownPositionConfig
自定义定位配置接口,用于覆盖翻转、偏移与视口边距
export interface DropdownPositionConfig {
flip?: boolean;
offset?: readonly [number, number];
padding?: number;
}DropdownToggleSource
展开状态切换来源类型
export type DropdownToggleSource = 'click' | 'keydown' | 'rootClose' | 'select';DropdownProps
下拉菜单容器组件属性接口
export interface DropdownProps extends Omit<HTMLAttributes<HTMLElement>, 'onSelect' | 'onToggle'> {
align?: DropdownAlignOption;
as?: ElementType;
autoClose?: DropdownAutoClose;
children?: ReactNode;
className?: string;
defaultShow?: boolean;
drop?: DropdownDirection;
flip?: boolean;
focusFirstItemOnShow?: 'keyboard' | boolean;
onSelect?: SelectCallback;
onToggle?: ToggleCallback;
popperConfig?: DropdownPositionConfig;
renderMenuOnMount?: boolean;
show?: boolean;
}DropdownToggleProps
下拉触发按钮组件属性接口
export interface DropdownToggleProps extends Omit<HTMLAttributes<HTMLElement>, 'onSelect'> {
as?: ElementType;
children?: ReactNode;
className?: string;
disabled?: boolean;
id?: string;
size?: ButtonSize;
split?: boolean;
toggleLabel?: string;
type?: 'button' | 'reset' | 'submit';
variant?: ButtonVariant;
}DropdownItemProps
下拉菜单项组件属性接口
export interface DropdownItemProps extends Omit<HTMLAttributes<HTMLElement>, 'onSelect'> {
active?: boolean;
as?: ElementType;
children?: ReactNode;
className?: string;
disabled?: boolean;
eventKey?: EventKey;
href?: string;
onSelect?: SelectCallback;
}DropdownItemTextProps
下拉纯文本条目组件属性接口
export interface DropdownItemTextProps extends HTMLAttributes<HTMLElement> {
as?: ElementType;
children?: ReactNode;
className?: string;
}DropdownHeaderProps
下拉分组标题组件属性接口
export interface DropdownHeaderProps extends HTMLAttributes<HTMLElement> {
as?: ElementType;
children?: ReactNode;
className?: string;
}DropdownDividerProps
下拉分割线组件属性接口
export interface DropdownDividerProps extends HTMLAttributes<HTMLElement> {
as?: ElementType;
children?: ReactNode;
className?: string;
}DropdownButtonProps
下拉按钮快捷组件属性接口
export interface DropdownButtonProps extends Omit<DropdownProps, 'as' | 'children' | 'title'> {
children?: ReactNode;
disabled?: boolean;
id?: string;
menuVariant?: DropdownMenuVariant;
size?: ButtonSize;
title: ReactNode;
toggleClassName?: string;
type?: 'button' | 'reset' | 'submit';
variant?: ButtonVariant;
}SplitButtonProps
分割按钮快捷组件属性接口
export interface SplitButtonProps extends DropdownButtonProps {
href?: string;
toggleLabel?: string;
}DropdownContextValue
下拉菜单上下文,供 DropdownToggle 与 DropdownMenu 等消费
export interface DropdownContextValue {
align?: DropdownAlignOption;
autoClose: DropdownAutoClose;
drop: DropdownDirection;
flip: boolean;
focusFirstItemOnShow: 'keyboard' | boolean;
menuElement: HTMLElement | null;
onSelect: SelectCallback;
popperConfig?: DropdownPositionConfig;
renderMenuOnMount: boolean;
setMenu: (element: HTMLElement | null) => void;
setToggle: (element: HTMLElement | null, id?: string) => void;
show: boolean;
source?: DropdownToggleSource;
toggle: ToggleCallback;
toggleElement: HTMLElement | null;
toggleId?: string;
}