列表框显示选项列表并允许用户选择其中一个或多个。

演示

import { Listbox, ListboxContent, ListboxList } from "@resolid/react-ui";

export default function App() {
  const collection = [
    {
      label: "Fruits",
      children: [
        { value: "apple", label: "Apple" },
        { value: "banana", label: "Banana" },
        { value: "blueberry", label: "Blueberry" },
        { value: "grapes", label: "Grapes" },
        { value: "pineapple", label: "Pineapple" },
      ],
    },
    {
      label: "Vegetables",
      children: [
        { value: "aubergine", label: "Aubergine" },
        { value: "broccoli", label: "Broccoli" },
        { value: "carrot", label: "Carrot" },
        { value: "courgette", label: "Courgette", disabled: true },
        { value: "leek", label: "Leek" },
      ],
    },
  ];

  return (
    <Listbox name="listbox" className="min-w-60" collection={collection}>
      <ListboxContent className="max-h-60 p-1">
        <ListboxList />
      </ListboxContent>
    </Listbox>
  );
}

用法

import {
  Listbox,
  ListboxFilter,
  ListboxContent,
  ListboxVirtualizer,
  ListboxList,
} from "@resolid/react-ui";
  • Listbox: 列表框的根容器。
  • ListboxFilter: 列表框的筛选框
  • ListboxContent: 列表框要渲染的内容。
  • ListboxVirtualizer: 实现列表虚拟化。
  • ListboxList: 列表框的项目列表。
<Listbox>
  <ListboxFilter />
  <ListboxContent>
    <ListboxVirtualizer>
      <ListboxList />
    </ListboxVirtualizer>
  </ListboxContent>
</Listbox>

特点

  • 可以是受控的,也可以是不受控的。
  • 支持项目、标签、项目组。
  • 焦点得到全面管理。
  • 完整的键盘导航。
  • 支持虚拟化

举例

多选

使用 multiple 属性实现多选

import { Listbox, ListboxContent, ListboxList } from "@resolid/react-ui";

export default function App() {
  const collection = [
    {
      label: "Fruits",
      children: [
        { value: "apple", label: "Apple" },
        { value: "banana", label: "Banana" },
        { value: "blueberry", label: "Blueberry" },
        { value: "grapes", label: "Grapes" },
        { value: "pineapple", label: "Pineapple" },
      ],
    },
    {
      label: "Vegetables",
      children: [
        { value: "aubergine", label: "Aubergine" },
        { value: "broccoli", label: "Broccoli" },
        { value: "carrot", label: "Carrot" },
        { value: "courgette", label: "Courgette", disabled: true },
        { value: "leek", label: "Leek" },
      ],
    },
  ];

  return (
    <Listbox
      multiple
      defaultValue={["broccoli", "carrot"]}
      name="listbox"
      className="min-w-60"
      collection={collection}
    >
      <ListboxContent className="max-h-60 p-1">
        <ListboxList />
      </ListboxContent>
    </Listbox>
  );
}

筛选

使用 ListboxFilter 组件可以实现项目筛选

import {
  Listbox,
  ListboxFilter,
  ListboxContent,
  ListboxVirtualizer,
  ListboxList,
} from "@resolid/react-ui";

export default function App() {
  const collection = [
    {
      label: "Fruits",
      children: [
        { value: "apple", label: "Apple" },
        { value: "banana", label: "Banana" },
        { value: "blueberry", label: "Blueberry" },
        { value: "grapes", label: "Grapes" },
        { value: "pineapple", label: "Pineapple" },
      ],
    },
    {
      label: "Vegetables",
      children: [
        { value: "aubergine", label: "Aubergine" },
        { value: "broccoli", label: "Broccoli" },
        { value: "carrot", label: "Carrot" },
        { value: "courgette", label: "Courgette", disabled: true },
        { value: "leek", label: "Leek" },
      ],
    },
  ];

  const virtualCollection = Array.from({ length: 1000 }, (_, i) => ({
    value: i + 1,
    label: `Item ${i + 1}`,
  }));

  return (
    <div className="flex flex-row gap-5">
      <Listbox name="testSingleNormal" className="min-w-60" collection={collection}>
        <div className="border-b border-bd-subtle p-2">
          <ListboxFilter size="sm" />
        </div>
        <ListboxContent className="max-h-60 p-1">
          <ListboxList />
        </ListboxContent>
      </Listbox>
      <Listbox
        name="testMultipleVirtual"
        multiple
        required
        className="min-w-60"
        collection={virtualCollection}
      >
        <div className="border-b border-bd-subtle p-2">
          <ListboxFilter size="sm" />
        </div>
        <ListboxContent className="max-h-60 px-1">
          <ListboxVirtualizer>
            <ListboxList />
          </ListboxVirtualizer>
        </ListboxContent>
      </Listbox>
    </div>
  );
}

虚拟化

使用 ListboxVirtualizer 组件可以实现虚拟化

import { Listbox, ListboxContent, ListboxVirtualizer, ListboxList } from "@resolid/react-ui";

export default function App() {
  const collection = Array.from({ length: 1000 }, (_, i) => ({
    value: i + 1,
    label: `Item ${i + 1}`,
  }));

  const groupCollection = Array.from({ length: Math.ceil(collection.length / 20) }, (_, i) => ({
    label: `Group ${i + 1}`,
    children: collection.slice(i * 20, (i + 1) * 20),
  }));

  return (
    <div className="flex flex-row gap-5">
      <Listbox defaultValue={201} className="min-w-60" collection={collection}>
        <ListboxContent className="max-h-60 px-1">
          <ListboxVirtualizer>
            <ListboxList />
          </ListboxVirtualizer>
        </ListboxContent>
      </Listbox>
      <Listbox multiple defaultValue={[201, 203]} className="min-w-60" collection={groupCollection}>
        <ListboxContent className="max-h-60 px-1">
          <ListboxVirtualizer>
            <ListboxList />
          </ListboxVirtualizer>
        </ListboxContent>
      </Listbox>
    </div>
  );
}

自定义渲染

使用 renderItem 属性实现自定义渲染

import { Listbox, ListboxContent, ListboxList } from "@resolid/react-ui";
import { BrowserIcon } from "~/components/browser-icon";

export default function App() {
  const collection = [
    {
      value: "chrome",
      label: "Chrome",
      description: "Google Chrome 是一款快速、易于使用且安全的网络浏览器。",
    },
    {
      value: "firefox",
      label: "Firefox",
      description: "Firefox 是一款快速、轻量、注重隐私的浏览器,全平台可用。",
    },
    {
      value: "microsoft-edge",
      label: "Microsoft Edge",
      description: "Microsoft Edge 是 AI 驱动的浏览器。更智能的浏览方式。",
    },
    {
      value: "safari",
      label: "Safari",
      description: "Safari 是在所有 Apple 设备上体验互联网的最佳方式。",
    },
    {
      value: "opera",
      label: "Opera",
      description: "比默认浏览器更快、更安全、更智能。 功能齐全,可保护隐私、安全等。",
    },
  ];

  return (
    <Listbox
      name="listbox"
      className="max-w-96"
      collection={collection}
      renderItem={(item, { selected }) => {
        return (
          <div className="flex items-center gap-2">
            <div className="w-12 flex-1">
              <BrowserIcon size="2em" name={item.value} />
            </div>
            <div className="flex flex-col gap-1">
              <div>{item.label}</div>
              <div className={`text-sm ${!selected ? "text-fg-subtle" : ""}`}>
                {item.description}
              </div>
            </div>
          </div>
        );
      }}
    >
      <ListboxContent className="p-1">
        <ListboxList />
      </ListboxContent>
    </Listbox>
  );
}

属性

Listbox

属性
name

字段的名称, 提交表单时使用

类型string默认值必须false
属性
multiple

是否多个值

类型boolean默认值false必须false
属性
value

受控值

类型string | number | (string | number)[] | null默认值必须false
属性
defaultValue

默认值

类型string | number | (string | number)[] | null默认值null | []必须false
属性
onChange

onChange 回调

类型(value: string | number | (string | number)[] | null) => void默认值必须false
属性
valueKey

自定义 `value` 字段名

类型string默认值"value"必须false
属性
labelKey

自定义 `label` 字段名

类型string默认值"label"必须false
属性
childrenKey

自定义 `children` 字段名

类型string默认值"children"必须false
属性
disabledKey

自定义 `disabled` 字段名

类型string默认值"disabled"必须false
属性
size

大小

类型"xs" | "sm" | "md" | "lg" | "xl"默认值"md"必须false
属性
disabled

是否禁用

类型boolean默认值false必须false
属性
required

是否必需

类型boolean默认值false必须false
属性
readOnly

是否只读

类型boolean默认值false必须false
属性
invalid

是否无效

类型boolean默认值false必须false
属性
collection

项目的集合

类型T[]默认值必须true
属性
renderGroupLabel

自定义组标签渲染

类型(group: T) => ReactNode默认值必须false
属性
renderItem

自定义项目渲染

类型(item: T, status: { active: boolean; selected: boolean; }) => ReactNode默认值必须false
属性
searchFilter

自定义过滤函数

类型(keyword: string, item: T) => boolean默认值必须false

ListboxFilter

属性
value

受控值

类型string | number默认值必须false
属性
defaultValue

默认值

类型string | number默认值必须false
属性
onChange

onChange 回调

类型(value: string | number) => void默认值必须false
属性
size

大小

类型"xs" | "sm" | "md" | "lg" | "xl"默认值"md"必须false
属性
disabled

是否禁用

类型boolean默认值false必须false
属性
placeholder

占位符文本

类型string默认值必须false
属性
prefix

前置元素

类型ReactNode默认值必须false
属性
prefixWidth

前置元素宽度

类型number默认值必须false

ListboxVirtualizer

属性
gap

虚拟化列表中项目之间的间距

类型number默认值必须false
属性
groupLabelHeight

分组标签的高度(以像素为单位)

类型number默认值必须false
属性
itemHeight

项目的高度(以像素为单位)

类型number默认值必须false
属性
overscan

在可见区域上方和下方渲染的项目数

类型number默认值3必须false
属性
paddingEnd

应用于虚拟器末尾的填充(以像素为单位)

类型number默认值4必须false
属性
paddingStart

应用于虚拟器开始处的填充(以像素为单位)

类型number默认值4必须false
属性
scrollPaddingEnd

滚动到元素时应用于虚拟器末尾的填充(以像素为单位)

类型number默认值4必须false
属性
scrollPaddingStart

滚动到元素时应用于虚拟器开始处的填充(以像素为单位)

类型number默认值4必须false
属性
useAnimationFrameWithResizeObserver

将 ResizeObserver 封装在 requestAnimationFrame 中,实现更顺畅的更新并减少布局抖动

类型boolean默认值必须false

建议更改此页面