# 复杂选择器 · ComplexSelector

- 页面: https://jiguang132.com/zh/resources/astryx/docs/complex-selector
- 资源: Astryx (https://jiguang132.com/zh/resources/astryx.md)
- 全部指南: https://jiguang132.com/zh/resources/astryx/docs.md

用更丰富的选项结构表达复杂选择。

## 安装与前置条件

```bash
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0
```

需要 React 19+，按顺序导入基础 CSS 和主题，并设置 Theme Provider。参见[开始使用](/resources/astryx/docs/getting-started)。

## 示例与使用方式

- **复杂选择器 · 综合展示 1**：首先体验这个示例，再查看代码理解组件的组合方式。
- **复杂选择器 · 交互示例 2**：可交互查看这一用法的行为，复制代码时保留它实际使用的属性与导入。
- **复杂选择器 · 搜索 3**：可交互查看这一用法的行为，复制代码时保留它实际使用的属性与导入。

## API 与上游详细参考

优先使用 0.7.1 官方中文说明；上游尚未提供中文的条目保留英文。属性名、类型及默认值保持原生 API，不把示例状态名称当成组件属性。

## Complex Selector

Use ComplexSelector when a selection needs richer custom content than a Selector option row. It is intentionally one component: ComplexSelector owns the field, trigger, popover, focus restore, and changeAction flow, while the content render prop owns the selector-specific accessible structure.

### 使用建议

- Use variant="secondary" beside secondary buttons, or variant="ghost" beside ghost buttons; add a startIcon when it helps identify the trigger. Use alignment="end" when a wide surface should align its end edge to the trigger.
- For staged editors, keep draft state in the composed content and call the provided onChange helper only from Apply. Cancel or dismiss without committing.
- Compose the dialog content from the appropriate accessible structure for the job: RadioList for a simple choice, Calendar/date inputs for date picking, TreeList or a searchable list for hierarchy, or a custom grid when two-dimensional arrow navigation is useful.
- Use the provided onChange helper from children; it already calls both onChange and changeAction and updates optimistic busy state.
- Call close() from custom content when a selection should dismiss the popup. Keep it open for multi-step content or freeform entry flows.
- Use Astryx focus hooks for custom content: useGridFocus for two-dimensional grids, useTreeFocus through TreeList for hierarchies, and useListFocus for custom linear collections.
- Evaluate custom content against WCAG 2.2: keyboard operation, focus visible/not obscured, names and roles, labels/instructions, target size, and contrast/non-text contrast are especially relevant for selector popovers.
- 避免：Do not rebuild trigger ARIA, popover focus management, or changeAction handling in product code.
- 避免：Do not use ComplexSelector for a plain single-column text list; use Selector instead.

### 主题 API

```json
{
  "targets": [
    {
      "className": "astryx-complex-selector",
      "visualProps": [
        "variant",
        "size",
        "status"
      ]
    },
    {
      "className": "astryx-complex-selector-indicator-icon",
      "states": [
        "state"
      ]
    },
    {
      "className": "astryx-complex-selector-popup"
    }
  ]
}
```

## Complex Selector

An input or toolbar trigger and dialog-popover shell for custom selector content.

| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| label * | string |  | Label text for accessibility and the field label. |
| value * | Value |  | Current controlled value. |
| onChange | (value: Value) => void |  | Called when custom content commits a new value. |
| changeAction | (value: Value) => void \| Promise<void> |  | Async action after onChange. ComplexSelector exposes optimistic value and busy state while pending. |
| children * | (value: Value, onChange: (value: Value) => void, close: () => void, state: ComplexSelectorRenderState) => ReactNode |  | Custom dialog content. Receives positional value, onChange, close, and state helpers. |
| triggerLabel | ReactNode |  | Label/content shown in the closed trigger. |
| placeholder | ReactNode | 'Select...' | Placeholder shown when triggerLabel is omitted. |
| isDisabled | boolean |  | Disables the selector. |
| isLoading | boolean |  | Shows loading state on the trigger. |
| status | {type: 'warning' \| 'error' \| 'success', message?: string} |  | Validation status. |
| statusVariant | 'attached' \| 'detached' \| 'tooltip' | 'attached' for input selectors; 'detached' for secondary and ghost selectors | How the status message is placed relative to the input. attached overlaps directly below the input (bordered treatment; detached when variant is secondary or ghost); detached floats below as a separate element with spacing; tooltip reveals the message in an info-tip button. |
| size | 'sm' \| 'md' \| 'lg' | 'md' | Exact trigger height: sm 28px, md 32px, or lg 36px. |
| variant | 'input' \| 'secondary' \| 'ghost' | 'input' | Visual trigger style. Input is the bordered form treatment; secondary matches the secondary buttons of the active theme (borderless and neutral-filled by default); ghost is borderless and transparent to match ghost buttons. |
| startIcon | ReactNode \| IconType |  | Icon displayed at the start of the trigger. |
| width | SizeValue |  | Width of the field. |
| placement | 'above' \| 'below' \| 'start' \| 'end' | 'below' | Popup placement. |
| alignment | 'start' \| 'center' \| 'end' | 'start' | Popup alignment along the placement axis. |
| renderTrigger | (props: ComplexSelectorRenderTriggerProps) => ReactNode |  | Render the control the popup hangs off — a glyph in a list row, a chip, an icon button — instead of the selector's own field and button. Spread the given props ({ref, id, onClick, onKeyDown, aria-haspopup, aria-expanded, aria-controls, aria-busy}) onto it; the popup is anchored to that control and still labelled by `label`. The field chrome is not rendered. Pair with handleRef to open from a keystroke elsewhere. |
| handleRef | React.Ref<ComplexSelectorHandle> |  | Imperative handle for programmatic control. Exposes open(), close(), toggle(), and isOpen(). |
| onOpenChange | (isOpen: boolean) => void |  | Called whenever the surface opens or closes, however it happened — trigger, keyboard, light dismiss, Escape, close(), or the imperative handle. |
| contentXstyle | StyleXStyles |  | StyleX styles for the popup content container. |
| onClick | (event: MouseEvent) => void |  | Click handler on the trigger. Runs before the popup opens; call preventDefault() to keep it closed. A press elsewhere in the control box goes through the trigger too. With renderTrigger it runs after the built-in toggle and cannot cancel it. |
| onKeyDown | (event: KeyboardEvent) => void |  | Key handler on the trigger. Runs after the built-in handling and receives every key, including the ArrowDown that opens the popup. With renderTrigger it is skipped for keys the built-in handling cancels. |
| containerXstyle | StyleXStyles |  | StyleX styles for the field container (label, control, and status together). No effect inside InputGroup (style the InputGroup instead) or in a `horizontal-labels` FormLayout. Root `xstyle`, `className`, and `style` are not accepted. |
| containerClassName | string |  | Class name for the field container. Same targeting as `containerXstyle`. |
| containerStyle | CSSProperties |  | Inline styles for the field container. Same targeting as `containerXstyle`. |
| controlXstyle | StyleXStyles |  | StyleX styles for the visual control box: the element that paints the border and background and holds the value, icons, and end controls. Never the trigger button itself. |
| controlClassName | string |  | Class name for the visual control box. |
| controlStyle | CSSProperties |  | Inline styles for the visual control box. |

### 组件结构

- **Field**: Field shell that provides the label and optional supporting field content.
- **Trigger**: Control that displays the current value or placeholder and opens the popup.
- **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.
- **Indicator icon**: Trailing chevron that rotates to reflect whether the popup is open.
- **Popup**: Mounted dialog surface that is painted and shown while open and hidden while closed.


## 示例的 StyleX 编译要求

ComplexSelectorShowcase 包含 stylex.create，需要配置 StyleX 源码编译流程。仅引入 Core 预编译 CSS 不足以运行这些示例样式，复制前请阅读[样式与 Tailwind](/resources/astryx/docs/styling)。

---

JGuang 全部资源索引: https://jiguang132.com/llms.txt
