自 1.0.0BETA
Radio 单选框
用于单选场景(`TxRadioGroup` + `TxRadio`)。支持三种形式:**标准单选**(圆点+文案)、**卡片单选**(强调信息层级)和**按钮组**(紧凑排列)。
该页面由 AI 迁移生成,请谨慎使用
内容已迁移完成,但仍建议结合源码和人工评审结果使用。
Radio 单选框
用于单选场景(TxRadioGroup + TxRadio)。支持三种形式:标准单选(圆点+文案)、卡片单选(强调信息层级)和按钮组(紧凑排列)。
标准单选形式
前圆点+后文案的标准单选形式,适合选项较多的场景。
Radio (standard)
示例即将加载...
<script setup lang="ts">
import { ref } from 'vue'
const value = ref<'a' | 'b' | 'c'>('a')
</script>
<template>
<div class="tx-demo tx-demo__col tx-demo--max-400">
<TxRadioGroup v-model="value" type="standard" direction="row">
<TxRadio value="a" label="Option A" />
<TxRadio value="b" label="Option B" />
<TxRadio value="c" label="Option C" />
</TxRadioGroup>
<TxCard variant="plain" background="mask" :padding="10" :radius="14">
<div class="tx-demo__meta">
selected: {{ value }}
</div>
</TxCard>
</div>
</template>
卡片单选形式
更强调信息层级的单选形式,适合需要解释文本的场景。
Radio (card)
示例即将加载...
<script setup lang="ts">
import { ref } from 'vue'
const value = ref<'a' | 'b' | 'c'>('a')
</script>
<template>
<div class="tx-demo tx-demo__col tx-demo--max-520">
<TxRadioGroup v-model="value" type="card">
<TxRadio value="a">
<div class="tx-demo__title">
Option A
</div>
<div class="tx-demo__desc">
Description text for option A
</div>
</TxRadio>
<TxRadio value="b">
<div class="tx-demo__title">
Option B
</div>
<div class="tx-demo__desc">
A longer description line to test wrapping and spacing
</div>
</TxRadio>
<TxRadio value="c" disabled>
<div class="tx-demo__title">
Option C (disabled)
</div>
<div class="tx-demo__desc">
Disabled option
</div>
</TxRadio>
</TxRadioGroup>
<TxCard variant="plain" background="mask" :padding="10" :radius="14">
<div class="tx-demo__meta">
selected: {{ value }}
</div>
</TxCard>
</div>
</template>
按钮组形式
紧凑排列的按钮组,适合选项较少的场景。
Radio (simple)
示例即将加载...
<script setup lang="ts">
import { ref } from 'vue'
const value = ref<'a' | 'b' | 'c'>('a')
</script>
<template>
<div class="tx-demo tx-demo__col">
<TxRadioGroup v-model="value">
<TxRadio value="a">
Option A
</TxRadio>
<TxRadio value="b">
Option B
</TxRadio>
<TxRadio value="c">
Option C
</TxRadio>
</TxRadioGroup>
<TxCard variant="plain" background="mask" :padding="10" :radius="14">
<div class="tx-demo__meta">
selected: {{ value }}
</div>
</TxCard>
</div>
</template>
Indicator 动效
带指示器的按钮组动效示例:默认 → 普通 → 模糊 → 玻璃。
Radio (indicator)
示例即将加载...
<script setup lang="ts">
import { ref } from 'vue'
const valueDefault = ref<'a' | 'b' | 'c'>('a')
const valuePlain = ref<'a' | 'b' | 'c'>('a')
const valueBlur = ref<'a' | 'b' | 'c'>('a')
const valueGlass = ref<'a' | 'b' | 'c'>('a')
</script>
<template>
<div class="tx-demo tx-demo__col tx-demo__col--18">
<div class="tx-demo__col tx-demo__col--10">
<div class="tx-demo__label">
Default
</div>
<TxRadioGroup v-model="valueDefault">
<TxRadio value="a">
Option A
</TxRadio>
<TxRadio value="b">
Option B
</TxRadio>
<TxRadio value="c">
Option C
</TxRadio>
</TxRadioGroup>
</div>
<div class="tx-demo__col tx-demo__col--10">
<div class="tx-demo__label">
Plain
</div>
<TxRadioGroup v-model="valuePlain" :elastic="false">
<TxRadio value="a">
Option A
</TxRadio>
<TxRadio value="b">
Option B
</TxRadio>
<TxRadio value="c">
Option C
</TxRadio>
</TxRadioGroup>
</div>
<div class="tx-demo__col tx-demo__col--10">
<div class="tx-demo__label">
Blur
</div>
<TxRadioGroup v-model="valueBlur" blur>
<TxRadio value="a">
Option A
</TxRadio>
<TxRadio value="b">
Option B
</TxRadio>
<TxRadio value="c">
Option C
</TxRadio>
</TxRadioGroup>
</div>
<div class="tx-demo__col tx-demo__col--10">
<div class="tx-demo__label">
Glass
</div>
<TxRadioGroup v-model="valueGlass" glass>
<TxRadio value="a">
Option A
</TxRadio>
<TxRadio value="b">
Option B
</TxRadio>
<TxRadio value="c">
Option C
</TxRadio>
</TxRadioGroup>
</div>
</div>
</template>
禁用状态
Radio (disabled)
示例即将加载...
<script setup lang="ts">
import { ref } from 'vue'
const value = ref<'a' | 'b'>('a')
</script>
<template>
<div class="tx-demo tx-demo__row">
<TxRadioGroup v-model="value" disabled>
<TxRadio value="a">
Disabled A
</TxRadio>
<TxRadio value="b">
Disabled B
</TxRadio>
</TxRadioGroup>
<TxRadioGroup v-model="value">
<TxRadio value="a" disabled>
Option A
</TxRadio>
<TxRadio value="b">
Option B
</TxRadio>
</TxRadioGroup>
</div>
</template>
Playground
把 TxRadioGroup 的主要属性做成可调节的控制面板,用于快速验证不同形态/参数组合。
RadioGroup (playground)
示例即将加载...
<script setup lang="ts">
import { computed, ref } from 'vue'
type GroupType = 'button' | 'standard' | 'card'
type OptionValue = 'a' | 'b' | 'c'
const type = ref<GroupType>('button')
const direction = ref<'row' | 'column'>('row')
const disabled = ref(false)
type IndicatorVariant = 'solid' | 'outline' | 'glass' | 'blur'
const indicatorVariant = ref<IndicatorVariant>('solid')
const glass = ref(false)
const blur = ref(false)
const elastic = ref(true)
const stiffness = ref(110)
const damping = ref(12)
const blurAmount = ref(1)
const value = ref<OptionValue>('a')
const shouldShowDirection = computed(() => type.value !== 'button')
const shouldShowIndicatorProps = computed(() => type.value === 'button')
const resolvedGlass = computed(() => {
if (!shouldShowIndicatorProps.value)
return false
if (indicatorVariant.value === 'glass')
return true
return glass.value
})
const resolvedBlur = computed(() => {
if (!shouldShowIndicatorProps.value)
return false
if (indicatorVariant.value === 'blur')
return true
return blur.value
})
const typeOptions = [
{ value: 'button', label: 'button' },
{ value: 'standard', label: 'standard' },
{ value: 'card', label: 'card' },
]
const directionOptions = [
{ value: 'row', label: 'row' },
{ value: 'column', label: 'column' },
]
</script>
<template>
<div class="tx-demo tx-demo__col" style="max-width: 720px;">
<TxCard variant="plain" background="mask" :padding="14" :radius="14">
<div class="tx-demo__col" style="gap: 12px;">
<div class="tx-demo__row">
<label class="tx-demo__row" style="gap: 8px;">
<span class="tx-demo__label">type</span>
<TuffSelect v-model="type" style="min-width: 180px;">
<TuffSelectItem v-for="opt in typeOptions" :key="opt.value" :value="opt.value" :label="opt.label" />
</TuffSelect>
</label>
<label v-if="shouldShowDirection" class="tx-demo__row" style="gap: 8px;">
<span class="tx-demo__label">direction</span>
<TuffSelect v-model="direction" style="min-width: 180px;">
<TuffSelectItem v-for="opt in directionOptions" :key="opt.value" :value="opt.value" :label="opt.label" />
</TuffSelect>
</label>
</div>
<div class="tx-demo__row">
<label class="tx-demo__row" style="gap: 8px;">
<span class="tx-demo__label">disabled</span>
<TxSwitch v-model="disabled" />
</label>
<label class="tx-demo__row" style="gap: 8px;">
<span class="tx-demo__label">elastic</span>
<TxSwitch v-model="elastic" />
</label>
<label v-if="shouldShowIndicatorProps" class="tx-demo__row" style="gap: 8px;">
<span class="tx-demo__label">indicator</span>
<TuffSelect v-model="indicatorVariant" style="min-width: 180px;">
<TuffSelectItem value="solid" label="solid" />
<TuffSelectItem value="outline" label="outline" />
<TuffSelectItem value="glass" label="glass" />
<TuffSelectItem value="blur" label="blur" />
</TuffSelect>
</label>
<label v-if="shouldShowIndicatorProps" class="tx-demo__row" style="gap: 8px;">
<span class="tx-demo__label">blur</span>
<TxSwitch v-model="blur" />
</label>
<label v-if="shouldShowIndicatorProps" class="tx-demo__row" style="gap: 8px;">
<span class="tx-demo__label">glass</span>
<TxSwitch v-model="glass" />
</label>
</div>
<div class="tx-demo__col" style="gap: 10px;">
<div class="tx-demo__label">
stiffness
</div>
<TxSlider v-model="stiffness" :min="60" :max="220" :step="1" show-value />
</div>
<div class="tx-demo__col" style="gap: 10px;">
<div class="tx-demo__label">
damping
</div>
<TxSlider v-model="damping" :min="4" :max="30" :step="1" show-value />
</div>
<div v-if="shouldShowIndicatorProps && blur" class="tx-demo__col" style="gap: 10px;">
<div class="tx-demo__label">
blurAmount
</div>
<TxSlider v-model="blurAmount" :min="0" :max="24" :step="1" show-value />
</div>
</div>
</TxCard>
<TxCard variant="plain" background="mask" :padding="18" :radius="14" style="width: 100%;">
<TxRadioGroup
v-model="value"
:type="type"
:direction="shouldShowDirection ? direction : undefined"
:disabled="disabled"
:indicator-variant="shouldShowIndicatorProps ? indicatorVariant : undefined"
:glass="resolvedGlass"
:blur="resolvedBlur"
:elastic="elastic"
:stiffness="stiffness"
:damping="damping"
:blur-amount="blurAmount"
>
<TxRadio value="a" :disabled="disabled && type !== 'button'">
<template v-if="type === 'card'">
<div class="tx-demo__title">
Option A
</div>
<div class="tx-demo__desc">
Card description A
</div>
</template>
<template v-else>
Option A
</template>
</TxRadio>
<TxRadio value="b">
<template v-if="type === 'card'">
<div class="tx-demo__title">
Option B
</div>
<div class="tx-demo__desc">
Card description B
</div>
</template>
<template v-else>
Option B
</template>
</TxRadio>
<TxRadio value="c" :disabled="type === 'button' ? false : true">
<template v-if="type === 'card'">
<div class="tx-demo__title">
Option C (disabled)
</div>
<div class="tx-demo__desc">
Disabled in non-button types
</div>
</template>
<template v-else>
Option C
</template>
</TxRadio>
</TxRadioGroup>
<div class="tx-demo__meta" style="margin-top: 12px;">
selected: {{ value }}
</div>
</TxCard>
</div>
</template>
API
TxRadioGroup
Props
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| modelValue / v-model | 绑定值 | string | number | - |
| disabled | 是否禁用(整组) | boolean | false |
| type | 形态:按钮组 / 标准单选 / 卡片 | 'button' | 'standard' | 'card' | 'button' |
| direction | 排列方向(button 无效;standard 默认 row;card 默认 column) | 'row' | 'column' | - |
| indicatorVariant | 指示器样式(button 有效) | 'solid' | 'outline' | 'glass' | 'blur' | - |
| glass | 玻璃指示器(button 有效) | boolean | false |
| blur | 模糊指示器(button 有效) | boolean | false |
| stiffness | 动效刚度(越大越快) | number | 110 |
| damping | 动效阻尼(越大越稳) | number | 12 |
| blurAmount | 模糊强度(blur 有效) | number | 1 |
| elastic | 是否启用弹性形变 | boolean | true |
Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| update:modelValue | 值更新时触发 | (value: string | number) => void |
| change | 值变化时触发 | (value: string | number) => void |
Keyboard
| 按键 | 行为 |
|---|---|
| ArrowRight / ArrowDown | 选择下一个可用单选项。 |
| ArrowLeft / ArrowUp | 选择上一个可用单选项。 |
| Home / End | 选择第一个 / 最后一个可用单选项。 |
TxRadio
Props
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| value | 当前项的值 | string | number | - |
| label | 文案(无插槽时) | string | '' |
| disabled | 是否禁用(单项) | boolean | false |
| type | 形态(一般由 group 决定) | 'button' | 'standard' | 'card' | 'button' |
Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| click | 点击(仅在组内变更时触发) | (value: string | number) => void |