# 单选指示器

## 使用方法

指示器是复选框、单选按钮、选择器和 Markdown 任务列表共用的选择图形。它们只负责把状态画出来。真正的控件保留输入、角色、名称、焦点和键盘。正因为拆开了，图形才可以换：先改它的类，形状不对时再按名字替换组件。

```vue
<script setup lang="ts">
import { RadioIndicator } from '@astryx-vue/core/Indicator'
</script>

<template>
  <RadioIndicator state="checked" />
</template>
```

圆点两种状态都画。未选中是空心圆，所以它能替到勾的位置上。没有半选。放在没有尺寸的单选按钮里时，圆是 18px，点是 8px。单独使用时，小尺寸是 20px，中等尺寸是 24px。

方框是 [复选指示器](/components/checkbox-indicator)。想让各处的勾都变成这个圆点时，替换的是 [勾选指示器](/components/check-indicator)。

## 结构

| 元素 | 说明 |
| --- | --- |
| 外框（方框、圆点） | 必需。每种状态都画出的圆圈。勾选指示器没有自己的外框。 |
| 状态标记 | 选中后才出现的实心内点。 |

## 最佳实践

| 指引 | 实践 |
| --- | --- |
| 推荐 | 先改稳定的类名。形状本身不对时，再替换组件。 |
| 推荐 | 用 isRenderable 判断插槽是否替换标记，不要用空值判断。插槽为空，包括条件不成立时，圆圈和内点都还在。 |
| 推荐 | 替换图形必须隐藏起来。角色和名称由外面的控件提供，再宣布一次就会读两遍。 |
| 推荐 | 替换图形里的颜色、圆角和边框宽度都用主题变量。 |
| 推荐 | 只渲染一个根元素，并保留焦点环要跟着走的圆角。真正的输入聚焦时，单选按钮把焦点环画在圆圈上。不要再自己画一圈。 |
| 避免 | 把悬停或按下当成属性传进去。悬停通过祖先上的 astryx-indicator-scope 到达圆圈。 |
| 避免 | 以为只有选中时才会挂上图形。宿主也会渲染空心圆。勾在未选中时什么都不画，圆点才能替上去。 |

## 示例

### 状态

小尺寸和中等尺寸的空心圆与实心圆，包括禁用。未选中始终是空心圆。

```vue
<script setup lang="ts">
import { RadioIndicator } from '@astryx-vue/core/Indicator'
</script>

<template>
  <div class="indicator-board">
    <div v-for="size in (['sm', 'md'] as const)" :key="size" class="indicator-board-row">
      <span class="checkbox-indicator-preview-size">{{ size }}</span>
      <span class="indicator-board-item">
        <RadioIndicator state="unchecked" :size="size" />
        <span>Unchecked</span>
      </span>
      <span class="indicator-board-item">
        <RadioIndicator state="checked" :size="size" />
        <span>Checked</span>
      </span>
      <span class="indicator-board-item">
        <RadioIndicator state="unchecked" :size="size" is-disabled />
        <span>Disabled</span>
      </span>
      <span class="indicator-board-item">
        <RadioIndicator state="checked" :size="size" is-disabled />
        <span>Disabled checked</span>
      </span>
    </div>
  </div>
</template>
```

## 属性

| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `state` | `'unchecked' \| 'checked'` | — | 必需。单选没有半选。未选中画空心圆。 |
| `size` | `'sm' \| 'md'` | `'md'` | 20px 或 24px。内点是 8px 或 10px。放在没有尺寸的单选按钮里时不要传，圆保持 18px。 |
| `isDisabled` | `boolean` | false | 只改变外观。圆圈变淡，空心圆用柔和背景。禁用的语义留在外面的控件上。 |

## 插槽

- 默认插槽替换内点，画在圆圈里面。
- 插槽为空，包括条件不成立时，圆圈和内点都还在。
- 插槽内容只作装饰。不要放可聚焦控件。

## 无障碍

- 根元素固定为 `aria-hidden="true"`。
- 组件不设置交互角色，也不提供点击或键盘行为。
- 传入的角色、Tab 顺序、可编辑属性，以及以 aria 开头的属性会被丢掉。
- 暴露的元素是圆圈本身。

## 主题

- `.astryx-radio-indicator`：圆圈。
- `.astryx-radio-indicator-dot`：选中后的内点。
- `data-state`：unchecked 或 checked。
- `data-size`：sm 或 md。没传尺寸时不写。
- `data-disabled`：禁用外观。

选中色先看输入状态色，这样字段的错误和警告仍能着色，否则用强调色。悬停通过祖先上的 `.astryx-indicator-scope` 生效，只在可以悬停的指针上变色。减少动态效果时过渡关掉。强制颜色模式下，未选中用画布色，选中用高亮色。

焦点环由单选按钮画在 `.astryx-radio-native:focus-visible + .astryx-radio-indicator` 上。描边跟着圆圈自己的圆角走。
