# 输入框组

## 使用方法

`InputGroup` 将输入框与前缀、后缀、按钮等元素组合成一个整体，常用于需要添加说明标签、单位、操作按钮的场景。

基本用法通过 `before` 和 `after` 插槽添加前置或后置内容：

```vue
<script setup lang="ts">
import { InputGroup, InputGroupText } from '@astryx-vue/core/InputGroup'
import { TextInput } from '@astryx-vue/core/TextInput'
import { ref } from 'vue'

const domain = ref('')
</script>

<template>
  <InputGroup label="网站">
    <template #before>
      <InputGroupText>https://</InputGroupText>
    </template>
    <TextInput v-model="domain" label="网址" is-label-hidden placeholder="example" />
    <template #after>
      <InputGroupText>.com</InputGroupText>
    </template>
  </InputGroup>
</template>
```

写上标签之后，这一组就是一个字段：标签、说明、可选或必填、状态都由字段壳负责，不要在外面再包一层。组内输入框自己的标签继续说明这一格填什么，通常隐藏起来。前后缀里的固定文字用组内文本组件，它和前后缀共用同一套字号和颜色。没有标签时，组仍然只是一条连在一起的控件，方便嵌进已经有字段的表单。

### 结构

- **标签**: 组上方的文字。
- **前缀**: 输入前面的内容，可以是文字、图标或按钮。
- **输入**: 主要输入元素，可以是 TextInput、NumberInput、TimeInput、DateInput、Typeahead、Selector 或 MultiSelector。
- **后缀**: 输入后面的内容，可以是文字、图标或按钮。
- **状态消息**: 组下面的错误、警告或成功提示。

## 最佳实践

| 指引 | 实践 |
| --- | --- |
| 推荐 | 用前置内容展示单位、协议前缀等固定文本。 |
| 推荐 | 用后置内容放置清除按钮、提交按钮等操作。 |
| 推荐 | 保持前后缀内容简洁，避免占用过多空间。 |
| 避免 | 同时使用过多前后缀元素，会让输入框显得拥挤。 |

## 示例

### 基本

金额输入两侧是固定的前缀和后缀，用来标明单位。

```vue
<script setup lang="ts">
import { InputGroup, InputGroupText } from '@astryx-vue/core/InputGroup'
import { TextInput } from '@astryx-vue/core/TextInput'
import { ref } from 'vue'

const price = ref('')
</script>

<template>
  <div style="width: 320px; max-width: 100%">
    <InputGroup label="Price">
      <template #before>
        <InputGroupText>$</InputGroupText>
      </template>
      <TextInput v-model="price" label="Amount" is-label-hidden placeholder="0.00" />
      <template #after>
        <InputGroupText>USD</InputGroupText>
      </template>
    </InputGroup>
  </div>
</template>
```

### 网站

协议和域名后缀固定在输入框两侧。

```vue
<script setup lang="ts">
import { InputGroup, InputGroupText } from '@astryx-vue/core/InputGroup'
import { TextInput } from '@astryx-vue/core/TextInput'
import { ref } from 'vue'

const domain = ref('')
</script>

<template>
  <div style="width: 320px; max-width: 100%">
    <InputGroup label="Website">
      <template #before>
        <InputGroupText>https://</InputGroupText>
      </template>
      <TextInput v-model="domain" label="URL" is-label-hidden placeholder="example" />
      <template #after>
        <InputGroupText>.com</InputGroupText>
      </template>
    </InputGroup>
  </div>
</template>
```

### 字段状态

带上标签之后，说明、可选和错误都由这一组自己负责。

```vue
<script setup lang="ts">
import { InputGroup, InputGroupText } from '@astryx-vue/core/InputGroup'
import { TextInput } from '@astryx-vue/core/TextInput'
import { ref } from 'vue'

const price = ref('')
</script>

<template>
  <div style="width: 320px; max-width: 100%">
    <InputGroup
      label="Price"
      description="Before tax"
      is-optional
      :status="{ type: 'error', message: 'Enter an amount' }"
    >
      <template #before>
        <InputGroupText>$</InputGroupText>
      </template>
      <TextInput v-model="price" label="Amount" is-label-hidden placeholder="0.00" />
      <template #after>
        <InputGroupText>USD</InputGroupText>
      </template>
    </InputGroup>
  </div>
</template>
```

## InputGroup Props

| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 整组的尺寸，会传给组内控件。 |
| `label` | `string` | — | 整组的无障碍名称。写上之后带上标签、说明、可选或必填，以及状态。 |
| `isLabelHidden` | `boolean` | `false` | 视觉上隐藏标签，读屏仍能读到。 |
| `description` | `string` | — | 标签和控件之间的说明。 |
| `disabled` | `boolean` | `false` | 是否禁用整组，并传给组内选择器。 |
| `isOptional` | `boolean` | `false` | 在标签旁标成可选。 |
| `isRequired` | `boolean` | `false` | 在标签旁标成必填。 |
| `status` | `FieldStatusInput` | — | 整组边框和控件下方的状态。 |
| `labelTooltip` | `string` | — | 标签末尾的提示。 |

## InputGroup 插槽

| 名称 | 说明 |
| --- | --- |
| `default` | 中间的输入控件。 |
| `before` | 输入框前面的文字、图标或按钮。 |
| `after` | 输入框后面的文字、图标或按钮。 |

## InputGroupText

前后缀里的固定文字。没有自己的属性，内容写在默认插槽里。
