列表框
查看源代码列表框显示选项列表并允许用户选择其中一个或多个。
演示
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 className={"min-w-60"} collection={collection}>
<div className={"border-bd-subtle border-b p-2"}>
<ListboxFilter size={"sm"} />
</div>
<ListboxContent className={"max-h-60 p-1"}>
<ListboxList />
</ListboxContent>
</Listbox>
<Listbox className={"min-w-60"} collection={virtualCollection}>
<div className={"border-bd-subtle border-b 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 defaultValue={201} 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
属性 | 类型 | 默认值 | 必须 | |
---|---|---|---|---|
属性multiple | 简介 是否多选 | 类型boolean | 默认值false | 必须false |
属性collection | 简介 项目的集合 | 类型T[] | 默认值- | 必须true |
属性valueKey | 简介 自定义 `value` 字段名 | 类型string | 默认值"value" | 必须false |
属性labelKey | 简介 自定义 `label` 字段名 | 类型string | 默认值"label" | 必须false |
属性disabledKey | 简介 自定义 `disabled` 字段名 | 类型string | 默认值"disabled" | 必须false |
属性childrenKey | 简介 自定义 `children` 字段名 | 类型string | 默认值"children" | 必须false |
属性searchFilter | 简介 自定义过滤函数 | 类型(keyword: string, item: T) => boolean | 默认值- | 必须false |
属性renderItem | 简介 自定义项目渲染 | 类型(item: T, status: { active: boolean; selected: boolean; }) => ReactNode | 默认值- | 必须false |
属性renderGroupLabel | 简介 自定义组标签渲染 | 类型(group: T) => ReactNode | 默认值- | 必须false |
属性size | 简介 大小 | 类型"xs" | "sm" | "md" | "lg" | "xl" | 默认值"md" | 必须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 |
属性name | 简介 字段的名称, 提交表单时使用 | 类型string | 默认值- | 必须false |
属性disabled | 简介 是否禁用 | 类型boolean | 默认值false | 必须false |
属性required | 简介 是否必需 | 类型boolean | 默认值false | 必须false |
属性readOnly | 简介 是否只读 | 类型boolean | 默认值false | 必须false |
属性invalid | 简介 是否无效 | 类型boolean | 默认值false | 必须false |
ListboxFilter
属性 | 类型 | 默认值 | 必须 | |
---|---|---|---|---|
属性size | 简介 大小 | 类型"xs" | "sm" | "md" | "lg" | "xl" | 默认值"md" | 必须false |
属性placeholder | 简介 占位符文本 | 类型string | 默认值- | 必须false |
属性prefix | 简介 前置元素 | 类型ReactNode | 默认值- | 必须false |
属性prefixWidth | 简介 前置元素宽度 | 类型number | 默认值- | 必须false |
属性value | 简介 可控值 | 类型string | number | 默认值- | 必须false |
属性defaultValue | 简介 默认值 | 类型string | number | 默认值"" | 必须false |
属性onChange | 简介 onChange 回调 | 类型((value: string | number) => void) | 默认值- | 必须false |
属性disabled | 简介 是否禁用 | 类型boolean | 默认值false | 必须false |
ListboxVirtualizer
属性 | 类型 | 默认值 | 必须 | |
---|---|---|---|---|
属性itemHeight | 简介 项目的高度(以像素为单位) | 类型number | 默认值- | 必须false |
属性groupLabelHeight | 简介 分组标签的高度(以像素为单位) | 类型number | 默认值- | 必须false |
属性overscan | 简介 在可见区域上方和下方渲染的项目数 | 类型number | 默认值3 | 必须false |
属性paddingStart | 简介 应用于虚拟器开始处的填充(以像素为单位) | 类型number | 默认值4 | 必须false |
属性paddingEnd | 简介 应用于虚拟器末尾的填充(以像素为单位) | 类型number | 默认值4 | 必须false |
属性scrollPaddingStart | 简介 滚动到元素时应用于虚拟器开始处的填充(以像素为单位) | 类型number | 默认值4 | 必须false |
属性scrollPaddingEnd | 简介 滚动到元素时应用于虚拟器末尾的填充(以像素为单位) | 类型number | 默认值4 | 必须false |
属性gap | 简介 虚拟化列表中项目之间的间距 | 类型number | 默认值- | 必须false |
属性useAnimationFrameWithResizeObserver | 简介 将 ResizeObserver 封装在 requestAnimationFrame 中,实现更顺畅的更新并减少布局抖动 | 类型boolean | 默认值- | 必须false |