# 单选按钮组件

一个用于从一组选项中进行单一选择的单选按钮组件。单选按钮允许用户从一组互斥的预定义选项中精确选择一个。

## 安装

```bash
npm install @ticatec/uniface-element
```

## 导入

```typescript
import RadioButton from "@ticatec/uniface-element/RadioButton";
```

## 基本用法

```svelte
<script>
  import RadioButton from "@ticatec/uniface-element/RadioButton";
  
  let selectedSize = '';
</script>

<RadioButton bind:group={selectedSize} value="small" label="小" />
<RadioButton bind:group={selectedSize} value="medium" label="中" />
<RadioButton bind:group={selectedSize} value="large" label="大" />

<p>已选择：{selectedSize}</p>
```

## 属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `value` | `any` | 必需 | 该单选按钮选项的值 |
| `label` | `string` | 必需 | 单选按钮的显示标签 |
| `group` | `any` | 必需 | 绑定到保存所选值的变量 |
| `disabled` | `boolean` | `false` | 单选按钮是否禁用 |
| `readonly` | `boolean` | `false` | 单选按钮是否只读 |
| `compact` | `boolean` | `false` | 是否使用紧凑间距 |
| `style` | `string` | `""` | 附加 CSS 样式 |
| `onfocus` | `((event: FocusEvent) => void) \| null` | `null` | 单选按钮获得焦点时的回调函数 |
| `onblur` | `((event: FocusEvent) => void) \| null` | `null` | 单选按钮失去焦点时的回调函数 |
| `onchange` | `((event: Event) => void) \| null` | `null` | 选择更改时的回调函数 |

## 事件

| 事件 | 描述 |
|-------|-------------|
| `focus` | 单选按钮获得焦点时触发 |
| `blur` | 单选按钮失去焦点时触发 |
| `change` | 选择更改时触发 |
| `click` | 单选按钮被点击时触发 |

## 方法

| 方法 | 描述 |
|--------|-------------|
| `setFocus()` | 以编程方式使单选按钮获得焦点 |

## 示例

### 基本单选按钮组

```svelte
<script>
  import RadioButton from "@ticatec/uniface-element/RadioButton";
  
  let selectedOption = 'option1';
</script>

<h3>选择一个选项：</h3>
<RadioButton bind:group={selectedOption} value="option1" label="选项 1" />
<RadioButton bind:group={selectedOption} value="option2" label="选项 2" />
<RadioButton bind:group={selectedOption} value="option3" label="选项 3" />

<p>你选择了：{selectedOption}</p>
```

### 带事件处理程序

```svelte
<script>
  import RadioButton from "@ticatec/uniface-element/RadioButton";
  
  let selectedColor = '';
  
  function handleChange(event) {
    console.log('颜色更改为：', event.target.value);
  }
  
  function handleFocus(event) {
    console.log('单选按钮已聚焦');
  }
  
  function handleBlur(event) {
    console.log('单选按钮已失焦');
  }
</script>

<h3>选择一个颜色：</h3>
<RadioButton 
  bind:group={selectedColor} 
  value="red" 
  label="红色" 
  onchange={handleChange}
  onfocus={handleFocus}
  onblur={handleBlur}
/>
<RadioButton 
  bind:group={selectedColor} 
  value="green" 
  label="绿色" 
  onchange={handleChange}
  onfocus={handleFocus}
  onblur={handleBlur}
/>
<RadioButton 
  bind:group={selectedColor} 
  value="blue" 
  label="蓝色" 
  onchange={handleChange}
  onfocus={handleFocus}
  onblur={handleBlur}
/>
```

### 禁用和只读状态

```svelte
<script>
  import RadioButton from "@ticatec/uniface-element/RadioButton";
  
  let selectedPlan = 'basic';
</script>

<h3>订阅计划：</h3>
<RadioButton bind:group={selectedPlan} value="free" label="免费（有限制）" disabled />
<RadioButton bind:group={selectedPlan} value="basic" label="基础" />
<RadioButton bind:group={selectedPlan} value="premium" label="高级" />
<RadioButton bind:group={selectedPlan} value="enterprise" label="企业" readonly />
```

### 紧凑样式

```svelte
<script>
  import RadioButton from "@ticatec/uniface-element/RadioButton";
  
  let selectedTheme = 'light';
</script>

<div style="display: flex; gap: 16px;">
  <RadioButton bind:group={selectedTheme} value="light" label="明亮" compact />
  <RadioButton bind:group={selectedTheme} value="dark" label="暗黑" compact />
  <RadioButton bind:group={selectedTheme} value="auto" label="自动" compact />
</div>
```

### 表单集成

```svelte
<script>
  import RadioButton from "@ticatec/uniface-element/RadioButton";
  import Button from "@ticatec/uniface-element/Button";
  
  let formData = {
    priority: '',
    category: '',
    urgency: ''
  };
  
  function handleSubmit() {
    console.log('表单提交：', formData);
  }
</script>

<form on:submit|preventDefault={handleSubmit}>
  <fieldset>
    <legend>优先级</legend>
    <RadioButton bind:group={formData.priority} value="low" label="低优先级" />
    <RadioButton bind:group={formData.priority} value="medium" label="中优先级" />
    <RadioButton bind:group={formData.priority} value="high" label="高优先级" />
  </fieldset>
  
  <fieldset>
    <legend>类别</legend>
    <RadioButton bind:group={formData.category} value="bug" label="错误报告" />
    <RadioButton bind:group={formData.category} value="feature" label="功能请求" />
    <RadioButton bind:group={formData.category} value="support" label="支持问题" />
  </fieldset>
  
  <fieldset>
    <legend>紧急程度</legend>
    <RadioButton bind:group={formData.urgency} value="immediate" label="立即" />
    <RadioButton bind:group={formData.urgency} value="soon" label="本周" />
    <RadioButton bind:group={formData.urgency} value="later" label="随时" />
  </fieldset>
  
  <Button type="primary" label="提交" onClick={handleSubmit} />
</form>

<style>
  fieldset {
    border: 1px solid #ddd;
    border-radius: 4px;
    padding: 16px;
    margin-bottom: 16px;
  }
  
  legend {
    font-weight: bold;
    padding: 0 8px;
  }
</style>
```

### 动态选项

```svelte
<script>
  import RadioButton from "@ticatec/uniface-element/RadioButton";
  
  let selectedLanguage = '';
  let languages = [
    { value: 'js', label: 'JavaScript' },
    { value: 'ts', label: 'TypeScript' },
    { value: 'py', label: 'Python' },
    { value: 'java', label: 'Java' },
    { value: 'go', label: 'Go' }
  ];
</script>

<h3>首选编程语言：</h3>
{#each languages as lang}
  <RadioButton 
    bind:group={selectedLanguage} 
    value={lang.value} 
    label={lang.label} 
  />
{/each}

{#if selectedLanguage}
  <p>你选择了：{languages.find(l => l.value === selectedLanguage)?.label}</p>
{/if}
```

### 带自定义样式

```svelte
<script>
  import RadioButton from "@ticatec/uniface-element/RadioButton";
  
  let selectedSize = 'medium';
</script>

<div class="size-selector">
  <RadioButton 
    bind:group={selectedSize} 
    value="small" 
    label="小 (S)" 
    style="margin-right: 24px;"
  />
  <RadioButton 
    bind:group={selectedSize} 
    value="medium" 
    label="中 (M)" 
    style="margin-right: 24px;"
  />
  <RadioButton 
    bind:group={selectedSize} 
    value="large" 
    label="大 (L)" 
  />
</div>

<style>
  .size-selector {
    padding: 16px;
    background: #f8f9fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
  }
</style>
```

### 编程式焦点

```svelte
<script>
  import RadioButton from "@ticatec/uniface-element/RadioButton";
  import Button from "@ticatec/uniface-element/Button";
  
  let selectedAnswer = '';
  let firstRadio, secondRadio, thirdRadio;
  
  function focusFirst() {
    firstRadio.setFocus();
  }
  
  function focusSecond() {
    secondRadio.setFocus();
  }
  
  function focusThird() {
    thirdRadio.setFocus();
  }
</script>

<h3>调查问题：</h3>
<RadioButton bind:this={firstRadio} bind:group={selectedAnswer} value="yes" label="是" />
<RadioButton bind:this={secondRadio} bind:group={selectedAnswer} value="no" label="否" />
<RadioButton bind:this={thirdRadio} bind:group={selectedAnswer} value="maybe" label="也许" />

<div style="margin-top: 16px;">
  <Button label="聚焦 是" onClick={focusFirst} />
  <Button label="聚焦 否" onClick={focusSecond} />
  <Button label="聚焦 也许" onClick={focusThird} />
</div>
```

## 功能

- **单一选择**：确保组内只能选择一个选项
- **键盘导航**：支持 Tab 键和箭头键的完整键盘可访问性
- **焦点管理**：支持编程式焦点控制和事件处理
- **状态管理**：支持禁用和只读状态
- **自定义样式**：灵活的样式选项和紧凑模式
- **事件处理**：支持用户交互的全面事件处理

## 行为

1. **选择**：点击一个单选按钮会选择它并取消组内其他按钮的选择
2. **键盘**：箭头键在选项间导航，空格键选择焦点所在的选项
3. **焦点**：Tab 键在单选按钮组间移动焦点
4. **标签**：点击标签会选择关联的单选按钮
5. **禁用**：禁用状态的单选按钮无法被选择或聚焦
6. **只读**：只读状态的单选按钮无法更改但可以聚焦

## 可访问性

- 适当的 ARIA 属性和角色
- 键盘导航支持
- 屏幕阅读器兼容的标签
- 焦点指示器和管理
- 带适当标签的语义化 HTML 结构

## 最佳实践

1. **分组相关选项**：对互斥选择使用单选按钮
2. **清晰标签**：为每个选项提供描述性、简洁的标签
3. **默认选择**：考虑提供一个合理的默认选择
4. **选项数量**：限制为 2-7 个选项以获得最佳可用性
5. **逻辑顺序**：按逻辑顺序排列选项
6. **视觉分组**：使用 `<fieldset>` 和 `<legend>` 分组相关单选按钮

## 浏览器支持

- 支持完整表单控件的现代浏览器
- 兼容 Svelte 5+
- 响应式设计原则
- 触控友好界面

## 相关组件

- `CheckBox` - 用于多选
- `Switch` - 用于二元开/关状态
- `OptionsSelect` - 用于下拉单选
- `Button` - 用于基于操作的选择