@ data- slot/ 选择
用于从下拉列表中选择单一值的无头可访问的选定组件.
安装
npm install @data-slot/select
使用量
HTML 结构
<div data-slot="select" data-placeholder="Choose a fruit...">
<button data-slot="select-trigger">
<span data-slot="select-value"></span>
<!-- Add your own chevron icon -->
</button>
<div data-slot="select-content" hidden>
<div data-slot="select-viewport">
<div data-slot="select-group">
<div data-slot="select-label">Fruits</div>
<div data-slot="select-item" data-value="apple">
<span data-slot="select-item-text">Apple</span>
</div>
<div data-slot="select-item" data-value="banana">
<span data-slot="select-item-text">Banana</span>
</div>
<div data-slot="select-item" data-value="orange">
<span data-slot="select-item-text">Orange</span>
</div>
</div>
<div data-slot="select-separator"></div>
<div data-slot="select-item" data-value="other">
<span data-slot="select-item-text">Other</span>
</div>
</div>
</div>
</div>
Java 脚本
import { create, createSelect } from '@data-slot/select';
// Auto-discover and bind all selects
const controllers = create();
// Or bind a specific element
const root = document.querySelector('[data-slot="select"]');
const controller = createSelect(root, {
defaultValue: 'apple',
onValueChange: (value) => console.log('Selected:', value),
});
// Programmatic control
controller.open();
controller.close();
controller.select('banana');
console.log(controller.value); // 'banana'
// Cleanup
controller.destroy();
createSelect(root) 每个根具有一能性。 再次为同一元素调用它返回现有的控制器; 如果您需要用不同的选项重新组合, 则首先将其销毁 .
API 密码
初始化
create(scope?)
寻找和约束未初始化 [data-slot="select"] 后裔 scope (违约) document) (中文(简体) ). 回返 SelectController[] 新绑起的根。 初始化范围元素本身,使用 createSelect。 。 。 .
import { create } from "@data-slot/select";
const controllers = create();
createSelect(root, options?)
创建一个 SelectController 用于一个根元素。 JavaScript 选项优先于相应的数据属性. 再次调用此选项为绑定根返回其已存在的控制器; 在重新绑定新选项前将其销毁 .
import { createSelect } from "@data-slot/select";
const controller = createSelect(element, {});
槽数
运行时间槽
select- 根装箱.select-trigger- 需要打开弹出并锁定位置的按钮.select-value- 触发器内的可选文本目标;显示选定的标签或占位符.select-content- 选项需要弹出容器.select-viewport- 内部可选滚动容器select-content;用于当前项目对齐滚动.select-item- 个人选择的选项.select-item-text- 内部可选文本锁定select-item; 倾向于与 Base/shadcn 样式精确的对等项目.select-group- 与团体有关的项目.select-label- 组标签(内置a)select-group) (中文(简体) ).select-positioner- 可选作者定位包装(重新使用而不是生成包装).select-portal- 可选作者的门户包装器,可以包含select-positioner。 。 。 .
只有样式的槽
select-separator- 物品/组之间的视觉分隔器.
来自作者的项目标签解析 data-label,则 select-item-text,然后是项目的文本内容. data-label 是输入属性,而不是生成状态.
由门户网站标记( 可选)
<div data-slot="select">
<button data-slot="select-trigger">
<span data-slot="select-value"></span>
</button>
<div data-slot="select-portal">
<div data-slot="select-positioner">
<div data-slot="select-content" hidden>...</div>
</div>
</div>
</div>
本地标签支持
使用标准的 HTML <label for="..."> 用于标签选择的元素。 这个 for 属性应匹配 id 在触发按钮。 单击标签打开选择区 aria-labelledby 自动设置.
<label for="fruit-select">Choose a fruit</label>
<div data-slot="select">
<button data-slot="select-trigger" id="fruit-select">
<span data-slot="select-value"></span>
</button>
<div data-slot="select-content" hidden>
<div data-slot="select-group">
<div data-slot="select-label">Fruits</div> <!-- group label -->
<div data-slot="select-item" data-value="apple">Apple</div>
</div>
</div>
</div>
数据属性
该组件设置这些属性以反映状态:
| 属性 | 元素 | 数值 | 说明 |
|---|---|---|---|
data-state | 根、 触发、 内容 | "open" | "closed" | 打开状态 |
data-position | 内容, 视图 | "item-aligned" | "popper" | 由控制器创建的已解析定位模式 |
data-align-trigger | 内容 | "true" | "false" | 当前模式是否将所选项目对齐到触发器 |
data-value | 根号 | string | 当前选定值 |
data-selected | 项目 | (在场) | 选中项目 |
data-highlighted | 项目 | (在场) | 重点/重点项目 |
data-placeholder | 触发 | (在场) | 显示占位符时 |
选项
选项可以通过JavaScript或数据属性(JS优先)传递.
放置属性( A)position, (中文(简体) ), side, (中文(简体) ), align, (中文(简体) ), sideOffset, (中文(简体) ), alignOffset, (中文(简体) ), avoidCollisions, (中文(简体) ), collisionPadding(a) 决定按此顺序:
- JavaScript 选项
select-contentselect-positionerselect根 (倒计时)
| 选项 | 数据属性 | 类型 | 默认 | 说明 |
|---|---|---|---|---|
defaultValue | data-default-value | string | null | 初始选定值 |
defaultOpen | data-default-open | boolean | false | 初始弹出打开状态 |
mountStrategy | 根号 data-mount-strategy | "lazy" | "eager" | "lazy" | 解密内容, 或者保持连接和隐藏 |
placeholder | data-placeholder | string | "" | 未选择值时的文本 |
disabled | data-disabled | boolean | false | 禁用交互 |
required | data-required | boolean | false | 需要确认的格式 |
name | data-name | string | - 说吧 | 窗体字段名称( 创建内部窗体控制) |
position | data-position | "item-aligned" | "popper" | "item-aligned" | 定位模式(见下文) |
avoidCollisions | data-avoid-collisions | boolean | true | 调整以停留在取景点 |
collisionPadding | data-collision-padding | number | 8 | 查看端口边缘粘贴 (px) |
lockScroll | data-lock-scroll | boolean | true | 弹出时锁定页面滚动 |
highlightItemOnHover | data-highlight-item-on-hover | boolean | true | 在指针上突出突出和突出焦点 |
定位模式
item-aligned (默认):弹出位置本身使所选项目与触发器一致,类似于本地 <select> 要素。 弹出宽度与触发宽度相匹配.
对于最接近的 Base/shadcn 视觉平面,将每个项目内的可见标签用 data-slot="select-item-text"。缺席时,控制器会回归整体 select-item 框,用于对齐、触发显示和打字头.
popper:弹出在扳机下方或上方,如下放菜单. 应用其他选项:
| 选项 | 数据属性 | 类型 | 默认 | 说明 |
|---|---|---|---|---|
side | data-side | "top" | "bottom" | "bottom" | 弹出位置 |
align | data-align | "start" | "center" | "end" | "start" | 弹出对齐 |
sideOffset | data-side-offset | number | 4 | 距离触发器( px) |
alignOffset | data-align-offset | number | 0 | 从对齐边缘抵消 (px) |
两种定位模式都设定 --transform-origin 定位要素select-positioner,或 select-content 当没有使用定位器时),所以内容动画可以使用 transform-origin: var(--transform-origin, center)。 。 。 .
控制器还将解析的定位模式映射到DOM上,用于样式:
data-position="item-aligned" | "popper"打开select-contentdata-position="item-aligned" | "popper"打开select-viewport当存在时data-align-trigger="true" | "false"打开select-content
消费者可以直接对照这些属性来作风格,不需要手动编写.
回电
| 回电 | 类型 | 说明 |
|---|---|---|
onValueChange | (value: string | null) => void | 选择更改时调用 |
onOpenChange | (open: boolean) => void | 弹出打开/ 关闭时调用 |
内容安装和服务器渲染
默认情况下, 选择从页面的 DOM 中删除其关闭的下拉 。 一直这样 页面中有许多选择在初始化后较小。 选择按钮和 选定的数值仍然可见,形式继续正常工作.
打开下拉将相同的选项放回页面中. 他们的状况和 事件听众被保存。 关闭等待任何退出动画完成, 除非选择一个选项,否则会立即关闭下拉.
大多数应用程序可以不作任何修改地使用此默认值.
如果您的代码需要在关闭时找到或更新选项 - for
实例,使用 querySelector——使用 eager 模式将其保存在 DOM 中:
createSelect(root, { mountStrategy: "eager" });
您还可以添加 data-mount-strategy="eager" 到选择根。 一个 Java 脚本
选项优先于 HTML 属性.
默认 lazy 模式, DOM 查询不会找到关闭的选项。 你还可以
关闭时使用选择控制器更改所选值; 显示
标签和窗体值将一如既往地更新.
没有 JavaScript 的服务器渲染和页面
懒散的升起 没有 减少发送给浏览器的 HTML 。 选项还在 包含在您的 HTML; 选择在 JavaScript 之后从 DOM 中删除它们 初始化 .
将降水的初始标记隐藏起来, 防止在之前短暂出现
初始化。 如果窗体必须在没有JavaScript的情况下工作,则提供本地
<select> 倒计时。 也没有 lazy 也没有 eager 模式提供后退
自动.
主计长
interface SelectController {
readonly value: string | null; // Current selected value
readonly isOpen: boolean; // Current open state
select(value: string): void; // Select a value
open(): void; // Open the popup
close(): void; // Close the popup
destroy(): void; // Cleanup
}
主计长销毁
destroy() 永久处理控制器并隐藏任何打开的表面,而不包含
产生额外的变化事件。 重复销毁是安全的
旧控制器变成无操作器。 在同一根上创建新控制器以重新组合 .
重心修复已经排入了近距离的队列 能够幸存的破坏. 关闭 Tab 仍然跳过焦点恢复以保存正常 Tab 导航 .
活动
境外事件
root.addEventListener('select:change', (e) => {
console.log('Value changed:', e.detail.value);
});
root.addEventListener('select:open-change', (e) => {
console.log('Open state:', e.detail.open);
});
入境事件
select:set 接受 { value?: string | null, open?: boolean }启用 value: null 清除选择。 在提供这两个字段时,在打开状态之前应用该值. 程序选择在禁用时有效, 但打开被屏蔽 .
// Set value
root.dispatchEvent(new CustomEvent('select:set', {
detail: { value: 'apple' }
}));
// Set open state
root.dispatchEvent(new CustomEvent('select:set', {
detail: { open: true }
}));
键盘导航
| 密钥 | 行动 |
|---|---|
Enter, (中文(简体) ), Space, (中文(简体) ), ArrowDown, (中文(简体) ), ArrowUp | 打开弹出( 当触发聚焦时) |
ArrowDown | 移动到下一个项目 |
ArrowUp | 移动到上一个项目 |
Home | 移动到第一个项目 |
End | 移动到上一个项目 |
Enter, (中文(简体) ), Space | 选择突出显示的项目 |
Escape | 关闭弹出 |
Tab | 关闭弹出并移动焦点 |
| 类型字符 | 跳转到匹配项目 |
无障碍
- 触发 :
role="combobox", (中文(简体) ),aria-haspopup="listbox", (中文(简体) ),aria-expanded,以及aria-controls打开时 - 内容 :
role="listbox", (中文(简体) ),aria-labelledby - 项目:
role="option", (中文(简体) ),aria-selected, (中文(简体) ),aria-disabled - 组 :
role="group", (中文(简体) ),aria-labelledby - 键盘导航时跳过已禁用的项目
形式整合
何时 name 将自动为格式提交建立内部控制,并避免视觉和键盘流动:
<form>
<div data-slot="select" data-name="fruit">
<!-- ... -->
</div>
<button type="submit">Submit</button>
</form>
与 required 编号 : data-required,该控制参与本地验证。 需要的空选定块构成提交并突出可见触发点。 被禁用的选手被排除在验证和提交之外。 准确保留了选定的值,包括换行符.
重设置窗体还原 defaultValue 及其未显示的选中区域
显示一个值变化事件,包括选择没有 name。 。 。 .
在浏览器重置后, 在下一个事件启动任务上同步
本地控制系统。 通话 preventDefault() 在重置事件上保留当前状态.
许可证
麻省理工学院