
astryx Selector 组件契约深度解析单选下拉从行为规范、自适应呈现到无障碍实现的完整指南【免费下载链接】astryxAn open source design system thats fully customizable and agent ready项目地址: https://gitcode.com/GitHub_Trending/as/astryx本指南围绕 astryx 设计系统中Selector组件的官方契约文档packages/core/src/Selector/Selector.spec.md展开系统讲解该单选下拉组件的设计意图、公共概念、行为/布局契约FR1–FR6、允许变体、无障碍要求、主题化解剖与验证地图并结合 Selector.tsx 源码与 Selector.test.tsx 测试套件给出实现级证据。读完本文你将掌握Selector的完整公开 API、表单/工具栏两种触发形态、popover/bottom-sheet/adaptive 三种呈现方式的内部协调逻辑以及如何在表单与紧凑工具栏中正确使用它。一、组件定位Selector 解决什么问题Selector让用户从一个规模适中的列表中选择一个值同时保持触发器本身可以作为表单字段或紧凑工具栏控件使用。它拥有并管理以下职责参见 spec 的 Ownership boundary从传入的选项中选择单个值触发器Trigger、列表框Listbox、选项行、搜索、空态、加载态与禁用行为该选择流程的键盘导航与屏幕阅读器播报对共享的Field、Layer、自适应呈现adaptive presentation与指示器indicator行为的 Selector 专属组合。它的非目标边界同样清晰动作/导航菜单由DropdownMenu负责多值选择由MultiSelector负责产品自定义的选项内容、以及选项列表之外的过滤逻辑不在其职责内输入族family级别的状态展示、外观、尺寸、end-control、状态放置与禁用原因策略统一由当前family:input-fields家族契约负责Selector只在自己边界内掌管选择行为。Selector的正确使用场景是表单与设置页中呈现中等数量选项的单选。当只有两个选项时应改用SegmentedControl或单选按钮是/否类二元选择应改用Switch或CheckboxInput超过约 20 个选项且未用 section 分组时应改用Typeahead。二、公共概念与公开类型spec 用一张公共概念表定义评审者所需的语义概念。Prop 的具体语法、完整默认值与示例保留在 Selector.doc.mjs 中概念封闭取值或状态含义按变体/方向/状态可用性默认值归属稳定性非法值行为trigger variantinput、ghost表单字段或工具栏呈现所有触发状态inputSelectorreleasedTypeScript 拒绝其他值sizesm、md、lg触发器与选项行密度所有呈现方式mdSelectorreleasedTypeScript 拒绝其他值selected-mark positionstart、end保留选中标记列的逻辑边缘每一行选项endSelectorreleasedTypeScript 拒绝其他值presentationpopover、bottom-sheet、adaptive锚定指针表面或紧凑触屏模态表面所有触发变体popoverSelectorreleasedTypeScript 拒绝其他值popup semanticslistbox模态对话框内含一个语义跟随活动呈现方式PopoverBottomSheetlistboxSelectorreleased不公开独立的 role propoption-row stateselected、disabled每行选项上稳定的主题状态每个渲染出的选项二者皆无Selectorreleased未知状态不输出read-only statefalse、true保留并提交值但不提供选择操作闭合触发器false调用方additive布尔归一化这些概念在类型层面有直接对应物。types.ts 定义了SelectorOptionDatavalue必填label/description/disabled/icon可选其中label刻意保持为字符串——搜索过滤与 typeahead 都要对它做小写匹配、SelectorDivider{type: divider}、SelectorSection{type: section, title?, options}以及它们的并集SelectorOptionType。公开入口 index.ts 同时导出Selector、SelectorOption、全部类型与useCombobox、useSelectedItemOffset两个 hook。三、行为与布局契约FR1–FR6spec 中的以下不变量描述的是当前main分支上已发布的行为ID已发布不变量证据位置FR1选择启用项会更新唯一选中值、关闭活动呈现并让触发器回到稳定闭合态消费方文档与选择交互测试FR2未显式指定位置时非搜索 popover 将选中行对齐到触发器上方并夹紧到视口搜索 popover 与显式位置使用常规 Layer 定位消费方文档、实现与几何测试FR3每一行选项都在indicatorPosition处保留一个选中标记列即使默认未选中指示器不绘制任何内容该列有最小宽度且可为更大的主题替换物生长itemMarkColumn、indicator-position 测试与主题测试FR4popover使用锚定的 Popoverbottom-sheet使用模态 BottomSheetadaptive在紧凑粗指针屏幕上解析为模态 bottom sheet否则为 Popover呈现控制器与自适应呈现测试FR5isLoading为真时触发器暴露忙碌态列表框抑制空态与无结果输出加载、空态与播报测试FR6isReadOnly为真时选中值保持可聚焦、可随表单提交同时选择表面、清除动作、披露指示器与所有值变更路径均不可用只读交互、表单与无障碍测试FR3 的实现细节itemMarkColumn在 Selector.tsx 中itemMarkColumn样式定义了选中标记列display: inline-flex居中布局、flexShrink: 0防止收缩、minWidth: 1rem保证最小宽度。渲染时每个选项行都会包裹一个spanitemMarkColumn并放入SelectionMark其state根据isSelected在checked/unchecked之间切换尺寸sm并通过themeProps(selector-check)暴露给主题。这正是 FR3 与 AV1 的落点主题可以替换勾选指示器包括在未选中态也绘制但行结构始终为指示器列预留空间保证所有标签的文字对齐。FR2 的实现细节选中项对齐与视口夹紧hooks.ts 中的useSelectedItemOffset实现macOS 风格的选中项对齐通过offsetTop/offsetParent链手动累加getLayoutTop得到未受 CSS transform 影响的文档相对布局坐标因为getBoundingClientRect会包含 popover 入场缩放的误差然后用锚点中心减选中项中心算出期望 top再以window.innerHeight夹紧到[0, viewportHeight - listboxHeight]。代码中的SELECTED_ITEM_OPTICAL_OFFSET 1补偿选中行相对闭合触发器标签约一个光学像素的偏差。最终通过给 Layer 容器施加负的 block-start margin 完成位移。测试 Selector.test.tsx 中clamps the default selected-item overlay to the viewport与aligns the selected item using untransformed layout geometry两条用例直接验证了该逻辑并且does not apply selected-item overlay offset when placement is explicit证明显式位置时不叠加该偏移对应 ORD2。FR4 的实现细节三层呈现控制器useSelectorPresentation.ts 是 Selector 与 MultiSelector 共享的内部呈现控制器。它通过useAdaptivePresentation(presentation)解析出实际呈现然后popover分支委托usePopovershow()返回didShowPopoverRef记录的实际打开结果bottom-sheet分支直接置isSheetOpen并通过isSheetPresented在 BottomSheet 退出动画与焦点交还触发器之后才允许移除隐藏的表面树handleTriggerFocus利用useFocusReturnVisibility判断底部表单的退场焦点事件作为保留的 sheet 可以离树的生命周期信号。SelectorBottomSheet见 SelectorBottomSheet.tsx对BottomSheet做懒加载React.lazySuspenseheighthug内容自适应内部用Heading level{3}渲染标签并有一个SelectorBottomSheetInitialFocus辅助组件在打开后通过requestAnimationFrame把焦点移入搜索框或列表。测试中uses a bottom sheet for adaptive presentation on compact touch与keeps adaptive presentation anchored without compact touch两条用例验证了adaptive的分辨逻辑。四、允许的变体AV1–AV3AV1 — 指示器渲染主题可替换勾选指示器替换物可在选中与未选中两态绘制当前行仍保留指示器列与 FR3 联动。AV2 — 选项内容renderOption可替换可见的选项内容而Selector仍保持行的 role、选中/禁用状态、导航与主题状态。AV3 — 选中值内容renderValue可替换闭合态的值显示而不改变其 combobox 身份无论可编辑还是只读。AV2 的承载者是 SelectorOption.tsx它组合共享的Item布局start content label description end content通过useSelectorRowLayout()读取行布局上下文——在高度被钉死的宿主如 InputGroup 内的触发器中强制inline布局因为该行物理上无法容纳两行。调用方在renderOption中返回SelectorOption即可保留selector-option主题目标。五、代表性状态与必备不变量状态必备不变量允许变化闭合且无值标签与占位符标识该字段消费方占位文本闭合且有值触发器呈现选中选项自定义renderValue内容指针 / popover锚定表面暴露 listbox无模态对话框语义默认或显式位置紧凑粗指针BottomSheet 暴露包含 listbox 的模态对话框显式bottom-sheet或解析后的adaptive搜索中可见选项、键盘导航与播报的结果计数使用同一个过滤器消费方搜索与空态文本加载中触发器忙碌空态与无结果输出被抑制消费方加载时长带原因的禁用触发器保持足够可聚焦以暴露原因同时阻止激活消费方原因文本只读值保持可聚焦可提交菜单、清除与披露操作均不存在值渲染、状态与忙碌呈现选中/未选中行行语义与主题状态正确两态都保留指示器列起始/结束位置与主题化指示器表现带原因的禁用状态对应disabledMessageprop它通过aria-disabled保持触发器可聚焦以显示原因 tooltip同时阻止激活。spec 与 Selector.doc.mjs 都强调不要用 Tooltip 包裹禁用的 Selector因为禁用控件会吞掉外部 Tooltip 所需的 hover 事件应使用disabledMessage。测试套件中disabledMessage分组覆盖了 hover/键盘聚焦显示原因、aria-describedby关联、焦点式禁用与无原因时不可聚焦等全部路径。六、转换与优先级顺序ORD1–ORD2ORD1 — 选项归一化先于过滤与选择字符串与选项对象在搜索、键盘匹配、渲染与值比较之前先归一化为同一种选项形态。实现见 utils.tsnormalizeOption把字符串{value, label}归一化为完整对象label ?? valuegetSelectableOptions负责把 section 扁平化并跳过 divider。isOptionData/isDivider/isSection三个类型守卫共同支撑这一流程。ORD2 — 调用方选中的内容刻意优先startIcon优先于选中选项自带的图标显式位置优先于选中项覆盖对齐。后者在测试does not apply selected-item overlay offset when placement is explicit中得到验证。七、性能与资源契约PR1–PR2PR1 — 搜索不引入由 effect 驱动的结果计数渲染下一次过滤后的计数由输入变化直接派生并对该次查询只播报一次。PR2 — 几何计算仅限打开的 popover 范围内选中项对齐可能在打开时读取浏览器布局但不会在闭合状态下建立文档级或持续的观察。八、无障碍契约AR1–AR4AR1 — 语义跟随呈现锚定呈现通过 Popover 暴露 listbox触发器使用aria-haspopuplistbox触屏呈现暴露包含 listbox 的模态 BottomSheet 对话框触发器使用aria-haspopupdialog。实现见 Selector.tsx 的aria-haspopup三元逻辑只读时省略否则根据activePresentation bottom-sheet选择dialog或listbox。AR2 — 焦点跟随活动交互模型锚定呈现把 combobox 关系保持在触发器/搜索控件模态触屏呈现把焦点移入其搜索控件或 listbox并在关闭时把焦点归还触发器。AR3 — 键盘选择匹配可见集合方向键、Home/End、typeahead、搜索、Enter、Escape 与 Tab 都只作用于用户当前能感知到的选项。AR3 的完整键位矩阵实现在 hooks.ts 的useCombobox中ArrowDown / ArrowUp闭合时打开并把高亮放到第一项/最后一项打开时在启用项索引getEnabledIndices过滤掉 disabled之间移动Home / End跳转到第一个/最后一个启用项非搜索模式PageUp / PageDown镜像 Home/End——在搜索模式下 Home/End 留给输入框光标移动APG 可编辑 combobox 规范因此 PageUp/PageDown 是跳转首尾选项的正式替代键Enter打开时提交高亮项闭合时打开并定位高亮到当前选中值Space无搜索时与 Enter 相同有搜索时让位给 typeahead 查询缓冲new y 可到达 New YorkEscape / Tab打开时关闭Delete / Backspace在闭合、非搜索且存在可清除值时作为清除按钮的键盘等价物清空选中值comboboxes-2 规范保证清除不是鼠标专属操作默认分支hasSearch时把可打印字符e.key.length 1且未按 ctrl/meta作为搜索种子转发给onSearchSeed——这实现了在闭合触发器上直接打字即可打开并填充搜索框的 type-to-open。测试套件中keyboard accessibility、typeahead两个大分组逐条覆盖上述键位包括 IME 组合输入does not select the highlighted option on a composing Enter (IME)对应 IME_GUARD_DESIGN.md 的防护策略、禁用项跳过、循环匹配同首字母项、超时重置前缀缓冲等。AR4 — 只读语义与可用性一致只读值保持可聚焦、保留rolecombobox、暴露aria-readonlytrue与aria-expandedfalse渲染内容仍是 combobox 值不暴露aria-controls、aria-activedescendant或活动选择表面。由于 Chromium 对 button 宿主 combobox 的映射会省略 ARIA readonly 属性因此还用本地化的无障碍描述来播报该状态。搜索与非搜索模式使用相同的只读 combobox 语义因为该状态下两者都不暴露搜索控件。isReadOnly的测试分组覆盖了搜索/非搜索、可清除、打开→只读、禁用优先级isDisabled优先于isReadOnly与本地化播报等路径。九、主题化解剖Theming Anatomyspec 给出了完整的组件解剖映射Selector.spec.md 中的anatomy-theming:v1它记录的是已发布的可达性仅限当前运行时行为{ Field: {delegatesTo: {owner: component:Field, target: field}}, Trigger: {target: selector}, Icon-rendered start icon: { delegatesTo: {owner: component:Icon, target: icon} }, Caller-rendered start content: { none: { reason: intentional: Arbitrary ReactNode content is caller-owned and receives no Selector target. } }, Trigger clear button: { delegatesTo: { owner: component:Field, target: input-clear-button } }, Status icon: { delegatesTo: {owner: component:Icon, target: icon} }, Indicator icon: {target: selector-indicator-icon}, Search row: {target: selector-search}, Search icon: { delegatesTo: {owner: component:Icon, target: icon} }, Search clear button: { delegatesTo: { owner: component:Field, target: input-clear-button } }, Option row: {target: selector-option-row}, SelectorOption-rendered content: {target: selector-option}, Bare caller-rendered option content: { none: { reason: intentional: Bare custom renderOption content is caller-owned and does not receive the SelectorOption target. } }, Option selection indicator: {target: selector-check}, Option divider: { delegatesTo: {owner: component:Divider, target: divider} }, Section heading: {target: selector-section-heading}, Empty state: {target: selector-empty-state}, Pointer popup: {target: selector-popup}, Touch sheet heading: { delegatesTo: {owner: component:Text, target: heading} }, Touch sheet: { delegatesTo: { owner: component:BottomSheet, target: bottom-sheet } } }要点解读Field 是条件性的独立使用的 Selector 会渲染 Field而处于InputGroup内时由组拥有外围壳层Pointer popup 与两个 touch sheet 部件是同一面板内容的备选呈现而非同时存在的解剖结构Icon 渲染的 start 内容委托给 Icon任意ReactNode的 start 内容归调用方所有默认渲染器与返回SelectorOption的自定义renderOption保留selector-option目标只有裸的自定义选项内容留在目标之外而目标化的选项行始终保留selector-clear-icon仍是废弃的兼容别名Selector.doc.mjs 中标记为deprecatedFor: input-clear-icon不拥有当前解剖行。Selector.doc.mjs 的theming.targets还列出了对应类名astryx-selectorvariant/size/statusdisabled/readonly状态、astryx-selector-option、astryx-selector-option-rowsizeselected/disabled、astryx-selector-search、astryx-selector-section-heading、astryx-selector-empty-state、astryx-selector-indicator-iconstate、astryx-selector-check、astryx-selector-popup。测试套件末尾的主题目标分组empty-state、clear-icon、indicator icon 等直接验证这些目标落在正确元素上。十、完整 Props 参考含默认值与行为说明以下内容继承自 Selector.doc.mjs 的公开文档供直接对照使用Prop类型说明默认值labelstring无障碍标签文本必填optionsSelectorOption[]选项数组字符串、带 value/label/description/icon/disabled 的对象、分隔线{type: divider}或分组{type: section, title, items}必填valuestring当前选中值—onChange(value: string) void选择变化回调—hasClearboolean有值时显示清除×按钮开启后onChange还会以null表示清除falsehasSearchboolean是否显示搜索输入输入时通过 polite live region 向屏幕阅读器播报匹配数或 No results found搜索框内置前导放大镜图标与有查询时的尾部清除✕按钮falsesearchPlaceholderstring搜索输入占位文本Search...emptyTextReactNode无选项时面板显示的内容面板打开时以 polite live region 播报字符串覆盖原样播报复杂节点回退到默认文本isLoading时不显示No optionsemptySearchTextReactNode搜索无匹配时显示并播报的内容No results foundplaceholderstring未选中时的占位文本Select...sizesm \| md \| lg尺寸变体mdvariantinput \| ghost触发器视觉风格input 为表单带边框输入形态ghost 为无边框、与幽灵按钮一致的工具栏用法inputisDisabledboolean禁用选择器falseisReadOnlyboolean只读值保持可见、可聚焦、可随表单提交保留 combobox 身份与aria-readonly选择表面、清除动作与披露指示器被移除不像禁用那样变暗两者同时设置时isDisabled优先falsehtmlNamestring表单提交的 HTML name渲染携带选中值的隐藏输入类似原生 select—disabledMessagestring解释禁用原因开启后悬停/键盘聚焦显示 tooltip并通过aria-disabled保持触发器可聚焦激活仍被阻止—isLabelHiddenboolean视觉隐藏标签但保持可访问falsedescriptionstring标签下方的辅助文本—isOptionalboolean标记字段为可选falseisRequiredboolean标记字段为必填falsestatus{type: error \| warning \| success, message?: string}校验状态与可选消息—statusVariantattached \| detached \| tooltip状态消息相对输入的位置attached直接重叠在带边框输入下方且仅对 input 变体有效ghost 默认脱离 attached紧凑工具栏用tooltipinput 为attachedghost 为detachedrenderOption(option: SelectorOptionData) ReactNode每个可选项的自定义渲染函数应使用它而不是 JSX childrendivider 与 section 由选择器自己渲染—renderValue(option: SelectorOptionData) ReactNode闭合触发器内选中值的自定义渲染触发器由 padding 决定尺寸是单行值28/32/36或两行值48/52/56的尺寸令牌始终落在 4px 节奏上并与相邻按钮/输入对齐在 InputGroup 内由组拥有行高选项折叠为单行并省略号截断—indicatorPositionstart \| end选中标记位于选项行的哪一边start在每个标签前预留标记列以保持对齐原生菜单做法end是与 Typeahead、CommandPalette 共享的惯例endpresentationpopover \| bottom-sheet \| adaptive选项列表的呈现方式adaptive在紧凑触屏上用 bottom sheet否则用锚定 popoverpopoverwidthSizeValue字段宽度数字像素字符串原样使用如100%整体缩放字段标签、控件、状态以保持对齐—startIconIconType \| ReactNode触发器起始处的图标—isLoadingboolean触发器内显示加载 spinnerfalsexstyleStyleXStyles布局自定义的 StyleX 样式必须是stylex.create()的值不能用style{{}}内联对象—此外还有隐藏的表单参与逻辑htmlName渲染一个携带选中值的隐藏 input参见测试submits the selected value under htmlName、submits an empty string when nothing is selected与is excluded from form data when disabled。十一、最佳实践速查来自 Selector.doc.mjs 的usage.bestPractices推荐做法提供可见标签让用户清楚自己在选择什么列表超过约 8 项时用 section 与 divider 组织选项自定义选项行使用renderOption不要直接把SelectorOption作为 JSX children 传入设置能暗示预期选择的占位符如 Choose a country而非笼统的 Select...仅在需要短前缀/后缀 addon 组成一个装饰化输入表面时才把 Selector 放进 InputGroup选择器与幽灵按钮并排位于工具栏时用variantghost需要校验状态时优先statusVarianttooltip以保持工具栏高度紧凑需要紧凑触屏上变成 bottom sheet 时用presentationadaptive。明确避免用于动作菜单改用 Dropdown Menu仅有两个选项改用 SegmentedControl 或单选按钮用于导航链接应是链接不是下拉选项用于是/否、开/关二元选择改用 Switch 或 CheckboxInput超过约 20 个选项且未分组考虑 Typeahead用 Tooltip 包裹禁用的 Selector 解释原因改用disabledMessage。十二、键盘与 typeahead 体验原生 select 级匹配按 Selector.doc.mjs 的usage.description键盘 typeahead 匹配原生 select 行为在聚焦的闭合触发器上打字直接选中匹配项重复按相同首字母键在共享首字母的选项中循环空格计入匹配字符new y 可到达 New York菜单打开时打字移动高亮、Enter 提交启用hasSearch时在闭合触发器上打字会打开 popup 并填充搜索输入。测试套件typeahead分组用十余条用例固化了这些行为循环匹配不重复触发changeAction、单字母匹配越过当前选中项前进、匹配label并提交value、跨 section 匹配而忽略 divider 与组标题、超时后重置前缀缓冲、禁用项被跳过、ctrl/meta 修饰的可打印键被忽略、提交后与清除后重新开始新缓冲等。十三、验证地图契约如何被测试锁定spec 的 Verification map 把每条契约映射到具体验证手段与失败预期契约验证方式代表性状态变异/失败预期审计分区FR1, AR2, AR3Selector.test.tsx 的选择、焦点与键盘套件闭合/打开、搜索/非搜索、禁用选项移除选择接线、焦点移动或键盘行为会失败于对应的交互测试audit:Selector/behaviorFR2位置与选中项几何测试默认、显式、RTL、带 transform 的入口使用错误的定位模型会失败于期望的 position-area 或 marginaudit:Selector/behaviorFR3, AV1itemMarkColumn源码检视加 indicator-position 与替换指示器测试start/end、选中/未选中、check/radio移除包裹层会失败于行结构测试改变其保留宽度需要源码/布局评审audit:Selector/design-renderedFR4, AR1, AR2呈现测试加aria-haspopup源码检视指针、紧凑粗指针、搜索/非搜索错误的 Popover/dialog role 或焦点目标会失败于测试aria-haspopup取值需源码/无障碍评审audit:Selector/accessibilityFR5加载、空态与 live-region 测试空选项、无匹配搜索、加载中加载中出现/播报空或无结果输出audit:Selector/behaviorFR6, AR4只读交互、表单、ARIA 与主题状态测试搜索/非搜索、可清除、打开→只读、禁用优先值被改变、popup/编辑操作仍存在、表单值消失或只读语义缺失audit:Selector/accessibilitysource-build 契约Selector.source-build.test.mjs包源码经消费方 Babel 编译把求值后的 StyleX 值移出受支持的源码形态会导致编译失败audit:Selector/code-healthsource-build 测试尤其值得注意它用next/babelpreset 加stylexjs/babel-plugin对 Selector 原始源码做真实编译并断言产出的padding-block:calc(...)声明精确匹配sm/md/lg三个尺寸令牌的期望值——这验证了组件的尺寸系统--size-element-{sm,md,lg}减单行高--spacing-5再减两倍边框宽在消费方构建管线中可复现。十四、兼容性、迁移与未来方向spec 明确声明的兼容性约定本契约记录不改变已发布的默认值与行为indicatorPosition默认为end每一行选项当前都在该逻辑边缘保留指示器列presentation默认为popoverbottom-sheet是显式模态呈现adaptive在紧凑粗指针屏幕上选择它hasClear把值契约扩展为包含null该区别已属于公开类型的一部分isReadOnly是增量additive特性默认false保留选中值、焦点与表单参与同时移除选择表面与编辑操作两态同时设置时isDisabled优先。关于未来方向spec 明确区分已接受但未实现与当前运行时行为spec:AST-004/DEC-1接受了一个未来可能折叠空指示器列的变更。它不是已发布行为且在实现、视觉验证与本契约同步更新之前不会替代 FR3spec:AST-011/DEC-1拥有增量的只读状态调用方策略可保留可聚焦、可提交的值而不暴露选择控件family:input-fields拥有族级的状态显示、行为、外观、尺寸、end-control、禁用原因与状态放置策略Selector 保留其 DEC-1 中独立的 inline-size 例外主题化解剖只记录已发布可达性不把spec:AST-001中已接受的选项来源行为或spec:AST-004中指示器空间变更当作当前运行时行为。结语Selector的组件契约展示了一个成熟设计系统对单选下拉组件的完整约束方式行为不变量FR1–FR6、允许变体AV1–AV3、转换顺序ORD1–ORD2、性能边界PR1–PR2与无障碍语义AR1–AR4被拆成可独立验证的条目并由 Selector.test.tsx选择/搜索/键盘/typeahead/只读/表单/主题目标、Selector.source-build.test.mjs消费方编译兼容与配套文档共同锁定。对使用者而言记住三条主线即可选项先归一化再处理normalizeOption、呈现跟随输入方式adaptive在紧凑粗指针屏幕解析为 bottom sheet、只读 ≠ 禁用isReadOnly保留可聚焦可提交的值isDisabled优先。若需进一步深入可继续阅读 packages/core/src/Selector/Selector.tsx 的触发器尺寸注释、packages/core/src/Selector/hooks.ts 的键盘矩阵以及 spec 引用的spec:AST-004/DEC-1与spec:AST-011/DEC-1决策记录。【免费下载链接】astryxAn open source design system thats fully customizable and agent ready项目地址: https://gitcode.com/GitHub_Trending/as/astryx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考