ProComponents, templates & AI tooling
HeroUI
27.7k

ListBox 列表框

列表框展示一组选项,并允许用户选择一个或多个。

引入

import { ListBox } from '@heroui/react';

用法

B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com
import {Avatar, Description, Label, ListBox} from "@heroui/react";

export function Default() {
  return (
    <ListBox aria-label="用户" className="w-[220px]" selectionMode="single">

组件结构

引入 ListBox 组件并通过点语法访问所有子部分。

import { ListBox, Label, Description, Header } from '@heroui/react';

export default () => (
  <ListBox>
    <ListBox.Item>
      <Label />
      <Description />
      <ListBox.ItemIndicator />
    </ListBox.Item>
    <ListBox.Section>
      <Header />
      <ListBox.Item>
        <Label />
      </ListBox.Item>
    </ListBox.Section>
  </ListBox>
)

带分组

创建新文件
N
进行修改
E
移至废纸篓
D
"use client";

import {Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Description, Header, Kbd, Label, ListBox, Separator, Surface} from "@heroui/react";

多选

B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com
import {Avatar, Description, Label, ListBox, Surface} from "@heroui/react";

export function MultiSelect() {
  return (
    <Surface className="w-[256px] rounded-3xl shadow-surface">

带禁用项

创建新文件
N
进行修改
E
移至废纸篓
D
"use client";

import {Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Description, Header, Kbd, Label, ListBox, Separator, Surface} from "@heroui/react";

自定义勾选图标

B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com
"use client";

import {Check} from "@gravity-ui/icons";
import {Avatar, Description, Label, ListBox, Surface} from "@heroui/react";

受控

B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com

已选:1

"use client";

import type {Selection} from "@heroui/react";

import {Check} from "@gravity-ui/icons";

自定义渲染函数

B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com
"use client";

import {Avatar, Description, Label, ListBox} from "@heroui/react";

export function CustomRenderFunction() {

虚拟化

ListBox 通过 Virtualizer 支持虚拟化,仅渲染视口内可见的行,从而高效展示大数据集。

"use client";

import {Description, Label, ListBox, ListLayout, Virtualizer} from "@heroui/react";

interface User {

样式

传入 Tailwind CSS 类

import { ListBox } from '@heroui/react';

function CustomListBox() {
  return (
    <ListBox className="border rounded-lg p-2 bg-surface">
      <ListBox.Item id="1" textValue="Item 1" className="hover:bg-surface-secondary">
        Item 1
      </ListBox.Item>
    </ListBox>
  );
}

自定义组件类

若要自定义 ListBox 组件类,可使用 @layer components 指令。
了解更多

@layer components {
  .list-box {
    @apply rounded-lg border border-border bg-surface p-2;
  }

  .list-box-item {
    @apply rounded px-2 py-1 cursor-pointer;
  }

  .list-box-item--danger {
    @apply text-danger;
  }

  .list-box-item__indicator {
    @apply text-accent;
  }
}

HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。

CSS 类

ListBox 组件使用以下 CSS 类(查看源码样式):

基础类

  • .list-box - ListBox 根容器
  • .list-box-item - 单个列表项
  • .list-box-item__indicator - 选中指示图标
  • .list-box-section - 用于分组的区块容器

变体类

  • .list-box--default - 默认变体样式
  • .list-box--danger - 危险变体样式
  • .list-box-item--default - 列表项默认变体
  • .list-box-item--danger - 列表项危险变体

状态类

  • .list-box-item[data-selected="true"] - 选中状态
  • .list-box-item[data-focus-visible="true"] - 聚焦状态
  • .list-box-item[data-disabled="true"] - 禁用状态
  • .list-box-item__indicator[data-visible="true"] - 指示器可见状态

交互状态

该组件同时支持 CSS 伪类与 data 属性:

  • 悬停:列表项上 :hover[data-hovered="true"]
  • 聚焦:列表项上 :focus-visible[data-focus-visible="true"]
  • 已选中:列表项上 [data-selected="true"]
  • 禁用:列表项上 :disabled[data-disabled="true"]

API 参考

ListBox Props

Prop类型默认值描述
aria-labelstring-ListBox 的无障碍标签。
aria-labelledbystring-标注 ListBox 的元素 id。
selectionMode"none" | "single" | "multiple""single"选择行为。
selectedKeysSelection-受控的选中 key。
defaultSelectedKeysSelection-初始选中 key。
onSelectionChange(keys: Selection) => void-选中变化时调用的事件处理函数。
disabledKeysIterable<Key>-禁用项的 key。
onAction(key: Key) => void-激活某项时调用的事件处理函数。
variant"default" | "danger""default"视觉变体。
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode-ListBox 项与分组。
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, ListBoxRenderProps>-使用自定义渲染函数覆盖默认 DOM 元素。

ListBox.Item Props

Prop类型默认值描述
idKey-列表项唯一标识。
textValuestring-用于无障碍与首字母导航的文本值。
isDisabledbooleanfalse是否禁用该项。
variant"default" | "danger""default"视觉变体。
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode | RenderFunction-列表项内容或渲染函数。
render(props: DetailedHTMLProps<LinkWithRequiredHref, HTMLAnchorElement> | React.JSX.IntrinsicElements[keyof React.JSX.IntrinsicElements], renderProps: ListBoxItemRenderProps) => ReactElement-使用自定义渲染函数覆盖默认 DOM 元素。

ListBox.ItemIndicator Props

Prop类型默认值描述
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode | RenderFunction-自定义指示器内容或渲染函数。

ListBox.Section Props

Prop类型默认值描述
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode-分组内容,包含 Header 与列表项。

RenderProps

在 ListBox.Item 或 ListBox.ItemIndicator 中使用渲染函数时,会传入以下值:

Prop类型描述
isSelectedboolean该项是否选中。
isFocusedboolean该项是否聚焦。
isDisabledboolean该项是否禁用。
isPressedboolean该项是否处于按下状态。

ListLayout

Name类型默认值描述
rowHeightnumber | undefined48行固定高度(px)。
estimatedRowHeightnumber | undefined行高可变时的估算高度。
headingHeightnumber | undefined48分组标题固定高度(px)。
estimatedHeadingHeightnumber | undefined标题高度可变时的估算高度。
loaderHeightnumber | undefined48加载器元素固定高度(px)。该加载器用于在根级或嵌套行/分组中渲染「加载更多」等内容。
dropIndicatorThicknessnumber | undefined2放置指示线厚度。
gapnumber | undefined0项之间的间距。
paddingnumber | undefined0列表内边距。

示例

基础用法

import { ListBox, Label, Description } from '@heroui/react';

<ListBox aria-label="Users" selectionMode="single">
  <ListBox.Item id="1" textValue="Bob">
    <Label>Bob</Label>
    <Description>bob@heroui.com</Description>
  </ListBox.Item>
  <ListBox.Item id="2" textValue="Alice">
    <Label>Alice</Label>
    <Description>alice@heroui.com</Description>
  </ListBox.Item>
</ListBox>

带分组

import { ListBox, Header, Separator } from '@heroui/react';

<ListBox aria-label="Actions" selectionMode="none" onAction={(key) => console.log(key)}>
  <ListBox.Section>
    <Header>Actions</Header>
    <ListBox.Item id="new" textValue="New file">New file</ListBox.Item>
    <ListBox.Item id="edit" textValue="Edit file">Edit file</ListBox.Item>
  </ListBox.Section>
  <Separator />
  <ListBox.Section>
    <Header>Danger zone</Header>
    <ListBox.Item id="delete" textValue="Delete" variant="danger">Delete</ListBox.Item>
  </ListBox.Section>
</ListBox>

受控选择

import { ListBox, Selection } from '@heroui/react';
import { useState } from 'react';

function ControlledListBox() {
  const [selected, setSelected] = useState<Selection>(new Set(["1"]));

  return (
    <ListBox
      aria-label="Options"
      selectedKeys={selected}
      selectionMode="multiple"
      onSelectionChange={setSelected}
    >
      <ListBox.Item id="1" textValue="Option 1">Option 1</ListBox.Item>
      <ListBox.Item id="2" textValue="Option 2">Option 2</ListBox.Item>
      <ListBox.Item id="3" textValue="Option 3">Option 3</ListBox.Item>
    </ListBox>
  );
}

自定义指示器

import { ListBox, ListBoxItemIndicator } from '@heroui/react';
import { Icon } from '@iconify/react';

<ListBox aria-label="Options" selectionMode="multiple">
  <ListBox.Item id="1" textValue="Option 1">
    Option 1
    <ListBox.ItemIndicator>
      {({isSelected}) =>
        isSelected ? <Icon icon="gravity-ui:check" /> : null
      }
    </ListBox.ItemIndicator>
  </ListBox.Item>
</ListBox>

无障碍

ListBox 组件实现 ARIA listbox 模式,并提供:

  • 完整键盘导航支持
  • 屏幕阅读器对选中变化的播报
  • 合理的焦点管理
  • 禁用状态支持
  • 首字母导航(typeahead)搜索能力

更多信息见 React Aria ListBox 文档

本页目录