多选器 · MultiSelector
从选项中选择多个值,展示选中项并允许移除。
安装与前置条件
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0
需要 React 19+,按顺序导入基础 CSS 和主题,并设置 Theme Provider。参见开始使用。
示例与使用方式
- 多选器 · 综合展示 1:首先体验这个示例,再查看代码理解组件的组合方式。
- 多选器 · 交互示例 2:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 多选器 · 交互示例 3:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 多选器 · 交互示例 4:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 多选器 · 交互示例 5:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 多选器 · 搜索 6:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 多选器 · 交互示例 7:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
API 与上游详细参考
优先使用 0.7.1 官方中文说明;上游尚未提供中文的条目保留英文。属性名、类型及默认值保持原生 API,不把示例状态名称当成组件属性。
Multi Selector
A checkbox dropdown for selecting multiple values from a list. Selected items can display as a count, labels, or badges. Use it for filtering or when presenting a finite set of options where multiple choices are needed.
使用建议
- Use for a moderate, finite set of options where multiple choices are needed.
- Enable search filtering when the list exceeds ~15 options.
- Use renderOption for custom option rows; the checkbox affordance remains owned by MultiSelector.
- Enable select-all when most users will want all or nearly all options selected.
- 避免:Use for single-value selection; use Selector instead.
- 避免:Show more than ~20 options without enabling search.
- 避免:Wrap a disabled MultiSelector in Tooltip to explain why it is disabled; disabled triggers swallow the hover events the wrapper needs. Use the disabledMessage prop instead.
主题 API
{
"targets": [
{
"className": "astryx-multi-selector",
"visualProps": [
"variant",
"size",
"status"
],
"states": [
"disabled",
"readonly"
]
},
{
"className": "astryx-multi-selector-empty-state"
},
{
"className": "astryx-multi-selector-search"
},
{
"className": "astryx-multi-selector-section-heading"
},
{
"className": "astryx-multi-selector-indicator-icon",
"states": [
"state"
]
},
{
"className": "astryx-multi-selector-option",
"visualProps": [
"size"
],
"states": [
"select-all",
"selected",
"disabled"
]
},
{
"className": "astryx-multi-selector-popup"
}
]
}
Multi Selector
带复选框的多选下拉框,用于从列表中选择多项。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| label * | string | 无障碍标签文本。 | |
| options * | MultiSelectorOptionType[] | 项目数组——字符串、带 value/label/icon/disabled 的对象、分隔线或分组。 | |
| value * | string[] | 当前选中的值。 | |
| onChange * | (value: string[], change?: MultiSelectorChange) => void | 选择变化时触发的回调。 | |
| changeAction | (value: string[]) => void | Promise<void> | 变化时的异步操作,在 onChange 之后触发。 | |
| placeholder | string | 'Select...' | 未选择值时显示的占位文本。 |
| size | 'sm' | 'md' | 'lg' | 'md' | 选择器的尺寸变体。 |
| variant | 'input' | 'secondary' | 'ghost' | 'input' | Visual trigger style. input is the bordered input treatment for forms; secondary matches the secondary buttons of the active theme (borderless and neutral-filled by default) for navs and toolbars; ghost is borderless and transparent, matching ghost buttons for toolbar usage. |
| triggerDisplay | 'count' | 'labels' | 'badges' | 'count' | 在触发器中显示选中项的方式。 |
| formatValue | (items: {value: string; label: string}[]) => string | 格式化 triggerDisplay="count" 或 "labels" 时的触发器文本。接收选中项(value 及解析后的 label),数量为 items.length。triggerDisplay="badges" 不使用此属性。 | |
| maxBadges | number | 3 | 显示"+N"之前的最大徽章数。仅适用于 triggerDisplay="badges"。 |
| hasSelectAll | boolean | 是否显示全选复选框。 | |
| selectAllLabel | string | 'Select all' | 全选复选框的标签。 |
| hasSearch | boolean | 是否显示用于过滤选项的搜索输入。 | |
| searchPlaceholder | string | 'Search...' | 搜索输入的占位文本。 |
| emptyText | ReactNode | 'No options' | 没有可显示的选项时,下拉面板中显示的内容。 |
| emptySearchText | ReactNode | 'No results found' | 搜索查询未匹配到任何选项时,下拉面板中显示的内容。 |
| hasCreate | boolean | false | 配合 hasSearch:当输入的文本与任何选项标签都不匹配时,在列表首行提供“创建 "<query>"”行;选中后通过 onChange 以 {type: "create", query} 描述符报告,调用方需在同一次更新中添加该选项。 |
| isDisabled | boolean | 禁用选择器。 | |
| isReadOnly | boolean | false | 将选择器设为只读:保留当前值、焦点顺序和表单提交,但移除选择面板、清除操作和展开指示器。与 isDisabled 不同,只读控件不会变暗;两者同时设置时 isDisabled 优先。 |
| htmlName | string | 用于表单提交的 HTML name 属性。为每个已选值渲染一个隐藏输入,类似原生多选。 | |
| disabledMessage | string | 解释选择器被禁用的原因。与 isDisabled 一起使用时,悬停/键盘聚焦时显示工具提示,并通过 aria-disabled 保持触发器可聚焦(仍无法激活)。请使用此属性,而不是用 Tooltip 包裹被禁用的选择器。 | |
| isLabelHidden | boolean | 视觉上隐藏标签同时保持其可访问性。 | |
| description | string | 标签下方显示的辅助文本。 | |
| isOptional | boolean | 将字段标记为可选。 | |
| isRequired | boolean | 将字段标记为必填。 | |
| isLoading | boolean | 在触发器中显示加载旋转器。 | |
| status | {type: 'error' | 'warning' | 'success', message?: string} | 带可选消息的验证状态。 | |
| statusVariant | 'attached' | 'detached' | 'tooltip' | 'attached' for input selectors; 'detached' for secondary and ghost selectors | 状态消息的放置方式:attached 直接叠加在输入框下方;detached 作为独立元素浮于下方并留有间距。 |
| renderOption | (option: MultiSelectorOptionData) => ReactNode | 每个可选选项的自定义渲染函数。不会用于分隔线、分组或全选行。 | |
| indicatorPosition | 'start' | 'end' | 'start' | Which edge of the option row carries the checkbox. end pushes it to the far edge of the row, including on the select-all row. |
| presentation | 'popover' | 'bottom-sheet' | 'adaptive' | 'popover' | 选项列表的呈现方式:锚定弹出框、底部抽屉,或根据紧凑触控屏自适应。 |
| width | SizeValue | Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned. | |
| startIcon | IconType | ReactNode | Icon displayed at the start of the selector trigger. | |
| hasClear | boolean | false | Shows a clear button when values are selected. |
| isDefaultOpen | boolean | false | Whether the dropdown starts open on mount. |
| renderTrigger | (props: MultiSelectorRenderTriggerProps) => ReactNode | 由调用方渲染面板的触发控件(替代选择器自带的字段和按钮);将传入的属性展开到该控件上,列表框将锚定于它并由 label 命名。 | |
| handleRef | React.Ref<MultiSelectorHandle> | 命令式句柄:open()、close()、toggle()、isOpen()。 | |
| onOpenChange | (isOpen: boolean) => void | 面板每次打开或关闭时触发,无论由何种方式引起。 | |
| onClick | (event: MouseEvent) => void | 触发器的点击处理函数,在内置开关之后运行,无法取消它。 | |
| onFocus | (event: FocusEvent) => void | 触发器的焦点处理函数,在选择器自身的焦点处理之前运行。 | |
| onKeyDown | (event: KeyboardEvent) => void | 触发器的按键处理函数,在内置键盘模型之后运行;该模型处理并取消的按键不会传给它。 | |
| containerXstyle | StyleXStyles | 字段容器(标签、控件和状态整体)的 StyleX 样式。在 InputGroup 内或 horizontal-labels FormLayout 中无效。不接受根级 xstyle、className 和 style。 | |
| containerClassName | string | 字段容器的类名,作用目标同 containerXstyle。 | |
| containerStyle | CSSProperties | 字段容器的内联样式,作用目标同 containerXstyle。 | |
| controlXstyle | StyleXStyles | 可视控件框的 StyleX 样式:绘制边框和背景并包含值、图标与尾部控件的元素,而非触发按钮本身。 | |
| controlClassName | string | 可视控件框的类名。 | |
| controlStyle | CSSProperties | 可视控件框的内联样式。 |
组件结构
- Field: Standalone Field shell that provides the label and optional supporting content; omitted inside InputGroup.
- Trigger: Painted control that displays the current selection or placeholder and opens the selection surface when editable.
- Icon-rendered start icon: Optional leading semantic icon or icon component rendered through Icon.
- Caller-rendered start content: Optional arbitrary React content rendered directly at the start of the trigger.
- Trigger clear button: Shared clear action that removes every selected value when hasClear is enabled.
- Status icon: Status glyph shown in place of the disclosure indicator for attached or tooltip status.
- Indicator icon: Trailing chevron shown when status presentation does not replace it; reflects collapsed or expanded state.
- Search row: Panel header with a borderless search input and optional clear action.
- Search icon: Leading magnifier rendered through Icon inside the search row.
- Search clear button: Shared clear action shown in the search row while a query is present.
- Option row: Selectable row for an option or the optional select-all choice.
- Option checkbox indicator: CheckboxInput indicator that presents each row’s selected, unselected, or indeterminate state.
- Option divider: Divider supplied in the public options data to separate adjacent option groups.
- Section heading: Visible heading for a labeled group of option rows.
- Empty state: Message shown when the shared panel content has no options or no search matches.
- Pointer popup: Anchored painted surface that hosts the shared panel content for popover presentation.
- Touch sheet heading: Heading above the shared panel content in bottom-sheet presentation.
- Touch sheet: BottomSheet surface that hosts the same panel content for bottom-sheet presentation.