Listbox 使用手册
v1.4.0 · @snowui-design-system/components
许可阅读:首次阅读组件文档、源码或 npm 使用流程,先读完整 LICENSE;同任务同版本去重。公开 API 配置与内部实现修改分别按许可处理;全部组件使用统一运行包,源码权益以许可为准。
组件介绍
在浮层中展示可选择的选项,支持搜索过滤与键盘操作,可作为 Select 的选择面板。
使用选择
用于有选项、键盘导航和选择语义的列表面板,通常由 Select 承载。通知、联系人、活动流是内容列表,不使用 Listbox。
items 的 value 必须唯一,label 用于显示和搜索;children 存在时替换 items。
显式选项使用 MenuItem as="item";显式搜索使用 Input as="search" 并关闭内置 search,避免重复输入框。
默认内置搜索占位通过 listbox.search 随 LocaleProvider 切换;parts.Input.placeholder(含空字符串)与原生 aria-label 保持优先,显式 Input 子项由调用方配置,查询和选项内容不翻译。
快速开始
以下示例展示推荐的基本组合。更多场景与组合限制见后文。
API
未重新声明的继承能力请查所属基础组件文档;本表只列本组件源码具名公开属性。
使用边界与详细说明
默认内置模式 / 显式组合模式
默认内置模式(推荐):
items自动生成<MenuItem as="item">;设置search可生成固定搜索框。未设置maxHeight时,面板高度按实际可见 MenuItem 的高度计算:默认最多完整显示 10 项,超过后显示浮层滚动条;通过parts.Input/parts.MenuItem配置内置组件。显式组合模式:显式书写 MenuItem,用于复杂内容或逐项 Props 差异;存在 children 时不再生成 items。
Select 默认提供 search=false;默认内置模式可用 search 开启、search={false} 隐藏搜索框、maxHeight 显式修改最大高度、scrollbar={false} 隐藏浮层滚动条。搜索框缺省 placeholder 通过 listbox.search 随 locale 使用“搜索”(zh-CN)/“Search”(en-US),parts.Input.placeholder(含空字符串)保持优先,有搜索框时面板默认最小宽度为 160px。显式组合模式使用 search 时同样自动插入 Input;不设置时也可设置 search={false} 并手动书写 <Input as="search">。maxHeight 与 scrollbar 始终作为 Listbox 面板能力生效。
未设置 maxHeight 时,可用视口空间只改变完整可见的 Item 数量,不产生半项高度:面板在 2~10 项之间选择能够容纳的完整项数;即使触发器下方空间不足,也至少为现有选项中的前 2 项保留完整高度。少于 2 项时按实际项数 Hug。显式 maxHeight 继续按调用方给定的长度与视口可用高度取较小值。
2026-04-24 更新(v1.2.0): 滚动条间距规范化 — .snowui-listbox 使用 overflow-y: scroll + scrollbar-width: none 隐藏原生滚动条,并通过 .snowui-listbox-body 内的自定义浮层滚动条显示滚动位置。MenuItem 背景左右间距保持 8px;滚动条覆盖在右侧,不占布局宽度,右边缘距面板右边框 4px。带搜索 Input 时,滚动条只出现在 Input 下方的 MenuItem 滚动区域。Thumb 支持鼠标拖拽;打开定位用选中项相对 portal 的真实视觉中心计算,兼容有无顶部 Input 的结构。
2026-04-20 更新: 搜索/自定义值支持 — <Input as="search"> 放入 <Listbox> 可自动接入过滤逻辑;allowCustomValue 允许添加自定义项并支持 hover 删除。移除 Combobox 依赖,Combobox.svelte 已废弃。
自动布局协议: Listbox 外层 portal anchor 只负责 position:fixed 定位与尺寸注入;真正的浮层面板由内层 Frame column 承担,使用 .snowui-quick-action-panel 共享视觉基类,并显式引用 DROPDOWN_OVERLAY_APPEAR_MOTION / DROPDOWN_OVERLAY_DISAPPEAR_MOTION。该 preset 只包含 opacity,不包含 scale;具体 duration / easing 以 motion preset catalog 为准,关闭时保留面板到 disappear preset 完成后再卸载。portal 通过 LISTBOX_HEADER_PORTAL_KEY context 暴露 headerEl 引用;Input as="search" 挂载后自动移入 headerEl(.snowui-listbox-header.snowui-quick-action-panel-header),不参与滚动。Listbox 与 QuickAction 共用同一套 header + scroll-body 结构与间距规则;唯一视觉差异只保留在外层面板 padding。为避免 Frame column 的 auto-layout 默认 gap: 8px 干扰浮层布局,Listbox 根层和 QuickAction 一样显式覆盖为 gap: 0。MenuItem 留在 .snowui-listbox-body.snowui-quick-action-panel-scroll-body > .snowui-listbox(flex:1; min-height:0; overflow-y:scroll; scrollbar-width:none)独立滚动。自定义浮层滚动条挂载在 .snowui-listbox-body 内,定位只覆盖实际滚动的 MenuItem 区域,不进入 Input 区域;滚动条覆盖在右侧,不占布局宽度。间距分工明确:面板 padding 定位 Input 与列表外边距,共享 header 规则负责搜索框与列表的内部衔接,MenuItem 自身 padding 定位选项背景和内容间距。无重复,无冲突。浮层滚动条默认可见宽 4px、距面板右边框 4px、thumb hover 时可见宽 8px 并从右向左增粗。
布局模型
主布局模型:复合管理布局。
Listbox 的区域结构为 portal anchor / panel / header / scroll body / option list / overlay scrollbar。
Header 与滚动体复用 QuickAction 的面板区域规范;选项行优先复用
MenuItem的槽位宿主布局。Input as="search"只作为固定 header 内容移入,不参与滚动列表布局。默认 items 与运行时自定义选项的字符串标签由 Text lines={1} 显示;较长内容在视口约束下收缩并提供全文访问,勾选/删除图标保持在可见面板内。面板内部继续受外层宽度约束,短标签的 Hug 宽度不改为强制铺满视口。
Text 仅拥有默认字符串标签的排版与全文展示;选择值、搜索、注册、键盘和焦点仍由原宿主协议拥有。调用方显式 MenuItem/Snippet 不被自动包裹,也不读取父级 parts.Text。
Listbox 不注册为三槽位宿主,也不把 Portal 定位、滚动条和搜索区抽象成通用布局;这些都属于复合组件私有管理逻辑。
与宿主的关系
组件 Props
继承 FrameProps,排除 children / tag。Listbox 必须置于 Select 等提供选择上下文的宿主内;展开、当前值和选择事件由宿主拥有,不支持独立 open、value、options、multiple 或 placement 属性。
等宽模式使用锚点实测宽度加固定 2px,左右各外扩 1px,覆盖下层字段边框;保留小数定位精度。该固定 CSS px 补偿不随根字号缩放,适用于所有 Listbox 宿主;Hug 模式不增加补偿,更大的 minWidth / 内容扩展继续生效。规范例外见 StyleSpec §2.1(源码参考:specs/maintainers/StyleSpec.md) 的 USER-LISTBOX-WIDTH-001。
键盘交互
ARIA
默认内置模式(推荐)
基础用法(在 Select 中)
带搜索过滤
搜索 + 允许自定义输入
Listbox 面板视觉与 QuickAction 对齐,但外层 padding 保持 8px。
搜索框固定在 header;选项滚动区域单独承载 overlay scrollbar。
连续 Hover
continuousHover 默认 true。开启时 Listbox 只使用一个容器级背景层在直接 MenuItem 之间移动,键盘 active 项也复用该层;关闭后恢复 MenuItem 原有的即时 hover / active 背景。disabled、filtered 项不会成为目标。
Listbox 样式覆盖
先阅读 完整 LICENSE;同任务、同版本、同范围去重。
优先用组件公开 Props 匹配合适样式,尽可能保留原有视觉。确需改写时按 样式选择与改写顺序 使用自己的 class(含项目已有 Tailwind)或实例 style。以下名称来自源码实际消费的公开 override;先核对目标作用域,不修改私有 DOM。采用 SnowUI Token 时选择正确类别,外部应用不被要求安装一方 utilities。
Listbox 类型与状态
必填属性:无具名必填属性。
可双向绑定:本组件未声明具名双向绑定属性;状态更新通过公开回调或所属宿主处理。
继承声明:Omit<FrameProps, "children" | "tag">。继承能力以基类公开文档为准;Omit 中的字段已排除,不能按基类原样使用。
以下为公开属性实际引用的类型声明,来自源码;Svelte Snippet 表示内容片段,ComponentProps 表示对应组件的 Props。
ListboxItem
来源:components/src/components/Listbox.svelte
ComponentPartsOf
来源:components/src/logic/component-parts.svelte.ts
ConfigurableComponentPartProps
来源:components/src/logic/component-parts.svelte.ts
ComponentPartControlledKey
来源:components/src/logic/component-parts.svelte.ts