Input · Radio

Radio

Radio component allows the user to select one option from a relative small set.

When to use

  • Used to select a single state among multiple options.
  • The difference from Select is that all available options in Radio are visible by default, making it easier for users to choose in comparison, so there should not be too many options.

Demos

How to import

<script lang="ts">
    import { Radio, RadioGroup } from '@fibrae/semi-ui-svelte';
</script>

Basic Usage

Code
<script lang="ts">
    import { Radio } from '@fibrae/semi-ui-svelte';
</script>

<Radio aria-label="单选示例" name="demo-radio">Radio</Radio>

Extra Info

You can use the extra snippet to add extra information: define it inside the Radio tag with {#snippet extra()}...{/snippet}, and the rest of the content is the label. It can hold any content.

Code
<script lang="ts">
    import { Radio } from '@fibrae/semi-ui-svelte';
</script>

<Radio aria-label="单选示例" name="demo-radio-extra">
    Semi Design
    {#snippet extra()}Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统{/snippet}
</Radio>

Disabled


Code
<script lang="ts">
    import { Button, Radio } from '@fibrae/semi-ui-svelte';

    let disabled = $state(true);
</script>

<div>
    <Radio aria-label="单选示例" checked={false} {disabled} name="demo-radio-disabled">Disabled</Radio>
    <br />
    <Radio aria-label="单选示例" checked {disabled} name="demo-radio-defaultChecked-disabled">Disabled</Radio>
    <div style="margin-top: 20px">
        <Button type="primary" onclick={() => (disabled = !disabled)}>Toggle disabled</Button>
    </div>
</div>

Advanced Mode

You can set mode='advanced' to allow options be able to unchecked when clicked again.

Code
<script lang="ts">
    import { Radio, type RadioChangeEvent } from '@fibrae/semi-ui-svelte';

    let checked = $state(true);
    const onChange = (e: RadioChangeEvent) => console.log('radio checked', e.target.checked);
</script>

<Radio aria-label="单选示例" bind:checked mode="advanced" name="demo-radio-advanced" {onChange}>允许取消选择</Radio>

Mutually Exclusive Set

You can use RadioGroup to create a set of mutually exclusive options.

Code
<script lang="ts">
    import { Radio, RadioGroup, type RadioChangeEvent, type RadioValue } from '@fibrae/semi-ui-svelte';

    let value = $state<RadioValue | undefined>(1);
    const onChange = (e: RadioChangeEvent) => console.log('radio checked', e.target.value);
</script>

<RadioGroup aria-label="单选组合示例" bind:value name="demo-radio-group" {onChange}>
    <Radio value={1}>A</Radio>
    <Radio value={2}>B</Radio>
    <Radio value={3}>C</Radio>
    <Radio value={4}>D</Radio>
</RadioGroup>

vertical arrangement

The radio elements in the group can be arranged horizontally or vertically by setting the direction property to the RadioGroup

Code
<script lang="ts">
    import { Radio, RadioGroup } from '@fibrae/semi-ui-svelte';
</script>

<RadioGroup aria-label="单选组合示例" direction="vertical" name="demo-radio-group-vertical">
    <Radio value={1}>A</Radio>
    <Radio value={2}>B</Radio>
    <Radio value={3}>C</Radio>
    <Radio value={4}>D</Radio>
</RadioGroup>

Button Style

You can use type='button' to set the button style type radio, and the button type radio supports three sizes.

It should be noted that the button type radio selector does not support auxiliary text (extra) and vertical arrangement (direction='vertical').

Code
<script lang="ts">
    import { Radio, RadioGroup, Space } from '@fibrae/semi-ui-svelte';

    const sizes = ['small', 'middle', 'large'] as const;
</script>

<Space align="start" spacing="loose" vertical>
    {#each sizes as size (size)}
        <RadioGroup aria-label="单选组合示例" buttonSize={size} name={`demo-radio-${size}`} type="button" value={1}>
            <Radio value={1}>即时推送</Radio>
            <Radio value={2}>定时推送</Radio>
            <Radio value={3}>动态推送</Radio>
        </RadioGroup>
    {/each}
</Space>

Card Style

You can set type='card' to RadioGroup to achieve card style with background.

Code
<script lang="ts">
    import { Radio, RadioGroup } from '@fibrae/semi-ui-svelte';

    const extraText = 'Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统';
    const items = [
        { value: 1, disabled: true },
        { value: 2, disabled: false },
        { value: 3, disabled: false },
    ];
</script>

<RadioGroup aria-label="单选组合示例" direction="vertical" name="demo-radio-group-card" type="card" value={2}>
    {#each items as item (item.value)}
        <Radio disabled={item.disabled} style="width: 280px" value={item.value}>
            单选框标题
            {#snippet extra()}{extraText}{/snippet}
        </Radio>
    {/each}
</RadioGroup>

Pure Card Style

You can set type='pureCard' to RadioGroup to achieve a pure card style with background and no radio.

Code
<script lang="ts">
    import { Radio, RadioGroup } from '@fibrae/semi-ui-svelte';

    const extraText = 'Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统';
    const items = [
        { value: 1, disabled: true },
        { value: 2, disabled: false },
        { value: 3, disabled: false },
    ];
</script>

<RadioGroup aria-label="单选组合示例" direction="vertical" name="demo-radio-group-pureCard" type="pureCard" value={2}>
    {#each items as item (item.value)}
        <Radio disabled={item.disabled} style="width: 280px" value={item.value}>
            单选框标题
            {#snippet extra()}{extraText}{/snippet}
        </Radio>
    {/each}
</RadioGroup>

Options Configuration

You can pass an array of options to RadioGroup using options property to create a set.

Code
<script lang="ts">
    import { RadioGroup, Space, type RadioChangeEvent, type RadioValue } from '@fibrae/semi-ui-svelte';

    let value1 = $state<RadioValue | undefined>('Guest');
    let value2 = $state<RadioValue | undefined>('Developer');
    let value3 = $state<RadioValue | undefined>('Maintainer');
    const plainOptions = ['Guest', 'Developer', 'Maintainer'];
    const options = [
        { label: 'Guest', value: 'Guest', extra: 'Semi Design', style: 'width: 120px' },
        { label: 'Developer', value: 'Developer', extra: 'Semi Design', style: 'width: 120px' },
        { label: 'Maintainer', value: 'Maintainer', extra: 'Semi Design', style: 'width: 120px' },
    ];
    const optionsWithDisabled = [
        { label: 'Guest', value: 'Guest' },
        { label: 'Developer', value: 'Developer' },
        { label: 'Maintainer', value: 'Maintainer', disabled: true },
    ];

    const log = (name: string, e: RadioChangeEvent) => console.log(`${name} checked`, e.target.value);
</script>

<Space align="start" spacing="loose" vertical>
    <RadioGroup aria-label="单选组合示例" bind:value={value1} name="demo-radio-group-1" onChange={(e) => log('radio1', e)} options={plainOptions} />
    <RadioGroup aria-label="单选组合示例" bind:value={value2} name="demo-radio-group-2" onChange={(e) => log('radio2', e)} options={optionsWithDisabled} />
    <RadioGroup aria-label="单选组合示例" bind:value={value3} name="demo-radio-group-3" onChange={(e) => log('radio3', e)} {options} />
</Space>

API Reference

Radio

Props

PropertyDescriptionTypeDefault
addonClassNameClass name of the container wrapping the content.string-
addonIdId of the addon node, which aria-labelledby points to. Generated when omitted.string-
addonStyleInline style of the container wrapping the content. Accepts a string only.string-
checkedWhether the radio is checked; bind it with bind:checked. Ignored inside a RadioGroup. bind:checked={get, set} makes it fully controlled; a plain checked is the initial value, a click overrides it inside the component, and a new value from the parent wins again.boolean-
childrenLabel content snippet of the radio. The rest of the tag's content is this snippet.Snippet-
disabledWhether the radio is disabled.boolean-
displayModeWhen set to vertical, the radio is displayed as a block and takes a line of its own.RadioDisplayMode-
extraSnippet of the supplementary text, which aria-describedby points to. Not rendered when type is button.Snippet-
extraIdId of the extra node, which aria-describedby points to. Generated when omitted.string-
modeWhen set to advanced, a checked radio can be unchecked by clicking it or pressing Space. Inside a RadioGroup the group's mode applies.RadioMode""
onChangeCalled when the checked state changes. The event's target is { checked, value, name, disabled }.Type(event: RadioChangeEvent) => void-
prefixClsCSS class name prefix. When omitted it falls back to the enclosing RadioGroup's value, then the global default.string-
preventScrollWhether focusing prevents the browser from scrolling the element into view; applies to the focus method.boolean-
typeStyle type: default, button, card or pureCard. Inside a RadioGroup the group's type applies.RadioType"default"
valueThe radio's value, which a RadioGroup compares to decide whether it is checked. It is also the native input's value in form submission.RadioValue-

Methods

MethodDescriptionType
blurRemoves focus from the native input.Type() => void
focusFocuses the native input.Type() => void

class and style (a string) land on the root label element. id, name, tabindex, autofocus, aria-*, onfocus and onblur land on the inner native input; other native attributes and events (such as onmouseenter and onmouseleave) land on the root element, and onclick is also on the root element but is called once, and only when the click lands on the input. checked supports bind:, a function binding, a one-way value, or nothing, and there is no defaultChecked. extra is not rendered for the button type.

RadioGroup

Props

PropertyDescriptionTypeDefault
buttonSizeButton size when type is button: small, middle or large.RadioGroupButtonSize"middle"
childrenRadio components in the group. Ignored when options is set.Snippet-
directionLayout direction of the radios: horizontal or vertical. Not supported when type is button.RadioDirection"horizontal"
disabledWhether the whole group is disabled.booleanfalse
extraSnippet for the extra text of each item in options, with the parameter { option, index }.TypeSnippet<[RadioGroupOptionSnippetParams]>-
labelSnippet for the label of each item in options, with the parameter { option, index }.TypeSnippet<[RadioGroupOptionSnippetParams]>-
modeWhen set to advanced, a checked radio can be unchecked by clicking it or pressing Space, and the selected value becomes undefined.RadioMode""
nameThe name of every native input in the group. A unique value is generated per group when omitted.string-
onBlurCalled when focus leaves the whole group; moving focus between its radios does not call it.Type(event: FocusEvent) => void-
onChangeCalled when the selected value changes. The event's target.value is the new value, or undefined when mode is advanced and the selected radio is unchecked.Type(event: RadioChangeEvent) => void-
optionsDeclares the options as data. Each item is a string or { label, value, disabled, extra, class, style, addonId, addonStyle, addonClass, extraId }, where style and addonStyle are strings.TypeArray<string | RadioOptionItem>-
prefixClsCSS class name prefix.string-
typeStyle type of every Radio in the group: default, button, card or pureCard.RadioType"default"
valueThe selected value, matched against each Radio's value; bind it with bind:value. bind:value={get, set} makes it fully controlled; a plain value is the initial value.RadioValue-

Each item in options has the fields label, value, disabled, extra (string | number), class, style (a string), addonId, addonStyle (a string), addonClass and extraId, and no onChange. Use the label and extra snippets, with the parameter { option, index }, for custom content; a button radio does not render extra. class, style (a string), onBlur and native attributes land on the root element with role="radiogroup", and so do aria-required, aria-invalid and aria-errormessage; onBlur fires only when focus leaves the whole group. The aria-expanded, aria-haspopup, aria-controls and tabindex injected by Tooltip are not rendered. value supports bind:, a function binding, a one-way value, or nothing, and there is no defaultValue.

Methods

Radio

Call focus() and blur() on the Radio instance obtained with bind:this; they act on the inner native input, and preventScroll applies to focus(). See Methods above.

Accessibility

ARIA

  • aria-label: used to explain the role of Radio or RadioGroup
  • aria-labelledby points to the addon node, used to explain the content of Radio
  • aria-describedby points to the extra node, which is used to explain the content of Radio
  • aria-required, aria-invalid and aria-errormessage apply to RadioGroup only and are set on the role="radiogroup" element. ARIA does not support them on a single Radio; when both aria-invalid and aria-errormessage are passed to it, the error message is linked to the input through aria-describedby

Keyboard and focus

WAI-ARIA: https://www.w3.org/WAI/ARIA/apg/patterns/radiobutton/

  • RadioGroup can be focused, the initial focus acquisition rules are as follows:
    • When there is no selected item in the RadioGroup, the initial focus is on the first Radio item;
    • When there are selected items in the RadioGroup, the initial focus is on the selected Radio item.
  • For radios belonging to the same radiogroup:
    • You can use Right arrow or Down arrow to move the focus to the next Radio item, uncheck the previously focused Radio item, and select the currently focused Radio item;
    • You can Use Left Arrow or Up Arrow to move the focus to the previous Radio item, at the same time uncheck the previously focused Radio item, and select the currently focused Radio item.
  • If there is no item selected in the RadioGroup, you can use the Space key to select the initial focus.
  • mode="advanced" is still a radio: arrow keys move the selection as usual, and clicking the selected item or pressing Space on it unchecks it.

Content Guidelines

  • Capitalize the first letter
  • No punctuation

Design Tokens

These are the component's internal Sass variables and cannot be overridden. To customize styles, override the --semi-* CSS variables (see the Design Token page) or write unlayered CSS rules.
Sass variableValueUsage
$transition_duration-radio-bgvar(--semi-transition_duration-none)单选框-背景色-动画持续时间
$transition_function-radio-bgvar(--semi-transition_function-easeIn)单选框-背景色-过渡曲线
$transition_delay-radio-bgvar(--semi-transition_delay-none)单选框-背景色-延迟时间
$transition_duration-radio-bordervar(--semi-transition_duration-none)单选框-边框-动画持续时间
$transition_function-radio-bordervar(--semi-transition_function-easeIn)单选框-边框-过渡曲线
$transition_delay-radio-bordervar(--semi-transition_delay-none)单选框-边框-延迟时间
$color-radio_default-border-defaultvar(--semi-color-text-3)单选圆圈描边颜色 - 默认态
$color-radio_default-bg-defaulttransparent单选圆圈背景颜色 - 默认态
$color-radio_default-bg-hovervar(--semi-color-fill-0)单选圆圈背景颜色 - 悬浮态
$color-radio_default-bg-activevar(--semi-color-fill-1)单选圆圈背景颜色 - 按下态
$color-radio_default-border-hovervar(--semi-color-focus-border)单选圆圈描边颜色 - 悬浮态
$color-radio_checked-border-hovervar(--semi-color-primary-hover)选中状态单选圆圈描边颜色 - 悬浮态
$color-radio_checked-border-activevar(--semi-color-primary-active)选中状态单选圆圈描边颜色 - 按下态
$color-radio_default-text-defaultvar(--semi-color-text-0)选项文本颜色
$color-radio_extra-text-defaultvar(--semi-color-text-2)辅助文本颜色
$color-radio_primary-bg-hovervar(--semi-color-primary-hover)选中状态单选圆圈背景颜色 - 悬浮态
$color-radio_primary-bg-activevar(--semi-color-primary-active)选中状态单选圆圈背景颜色 - 按下态
$color-radio_primary-border-defaultvar(--semi-color-primary)选中状态单选圆圈描边颜色 - 默认态
$color-radio_primary-bg-defaultvar(--semi-color-primary)选中状态单选圆圈背景颜色 - 默认态
$color-radio_primary-text-defaultvar(--semi-white)选中状态单选圆圈中心圆点颜色
$color-radio_checked-bg-disabledvar(--semi-color-primary-disabled)选中状态单选圆圈背景颜色 - 禁用态
$color-radio_default-border-disabledvar(--semi-color-border)单选圆圈描边颜色 - 禁用态
$color-radio_checked-border-disabledvar(--semi-color-primary-disabled)选中状态单选圆圈描边颜色 - 禁用态
$color-radio_disabled-bg-defaultvar(--semi-color-disabled-fill)单选圆圈背景颜色 - 禁用态
$color-radio_disabled-bg-hovertransparent
$color-radio_disabled-text-defaultvar(--semi-color-disabled-text)禁用态文本颜色
$color-radio_disabled-border-defaultvar(--semi-color-border)单选圆圈描边颜色 - 禁用态
$color-radio_checked-icon-disabledvar(--semi-white)选中且禁用状态下中心圆点颜色
$color-radio_buttonRadio-text-defaultvar(--semi-color-text-1)按钮样式单选文本颜色
$color-radio_buttonRadio-bg-defaultvar(--semi-color-fill-0)按钮样式单选背景颜色
$color-radio_buttonRadio-text-disabledvar(--semi-color-disabled-text)按钮样式单选禁用态文本颜色
$color-radio_addon_buttonRadio-bg-hovervar(--semi-color-fill-1)按钮样式单选悬浮态背景色
$color-radio_addon_buttonRadio-text-checkedvar(--semi-color-primary)按钮样式单选选中项文字颜色
$color-radio_addon_buttonRadio-bg-checkedvar(--semi-color-bg-3)按钮样式单选选中项背景颜色
$color-radio_cardRadioGroup-bg-defaulttransparent卡片样式单选默认背景色
$color-radio_cardRadioGroup-bg-checkedvar(--semi-color-primary-light-default)卡片样式单选选中态背景色
$color-radio_cardRadioGroup_disabled-bg-checkedvar(--semi-color-primary-light-default)卡片样式单选选中且禁用时的背景色
$color-radio_cardRadioGroup_disabled-bg-activetransparent卡片样式单选禁用时的背景色 - 按下态
$color-radio_cardRadioGroup-bg-hovervar(--semi-color-fill-0)卡片样式单选悬浮态背景色
$color-radio_cardRadioGroup-bg-activevar(--semi-color-fill-1)卡片样式单选按下态背景色
$color-radio_cardRadioGroup_border-defaulttransparent卡片样式单选默认描边颜色
$color-radio_cardRadioGroup_border-activevar(--semi-color-primary)卡片样式单选选中态描边颜色
$color-radio_cardRadioGroup_checked_border-activevar(--semi-color-primary-active)卡片样式单选选中态描边颜色 - 按下态
$color-radio_cardRadioGroup_checked_border-hovervar(--semi-color-primary-hover)卡片样式单选选中态描边颜色 - 悬浮态
$color-radio_cardRadioGroup_border_disabled-activevar(--semi-color-primary-disabled)卡片样式单选选中且禁用时的描边颜色
$color-radio_cardRadioGroup_addon-text-defaultvar(--semi-color-text-0)卡片样式单选标题文字颜色
$color-radio_cardRadioGroup_extra-text-defaultvar(--semi-color-text-2)卡片样式单选辅助文字颜色
$color-radio_cardRadioGroup_checked_disabled-border-defaultvar(--semi-color-primary-disabled)卡片样式选中项禁用态描边颜色 - 默认态
$color-radio_cardRadioGroup_checked_disabled-border-hovervar(--semi-color-primary-disabled)卡片样式选中项禁用态描边颜色 - 悬浮态
$color-radio_card-bg-hovervar(--semi-color-white)卡片模式下单选圆圈背景颜色 - 悬浮态
$color-radio_card-bg-activevar(--semi-color-white)卡片模式下单选圆圈背景颜色 - 按下态
$color-radio_card-bg-defaultvar(--semi-color-white)卡片模式下单选圆圈背景颜色 - 默认态
$color-radio_primary-outline-focus$color-focus-ring轮廓颜色 - 按键聚焦
$radius-radio_cardRadioGroupvar(--semi-border-radius-small)卡片式单选圆角大小
$radius-radio_addon_buttonRadiovar(--semi-border-radius-small)按钮式单选圆点圆角大小
$radius-radio_buttonRadiovar(--semi-border-radius-small)按钮式单选圆角大小
$width-radio_cardRadioGroup_checked-border1px卡片式单选描边宽度
$width-radio_cardRadioGroup_checked_disabled-border1px卡片式单选选中且禁用时的描边宽度
$width-radio_hover-border$border-thickness-control描边宽度 - 悬浮态
$width-radio_disabled-border$border-thickness-control描边宽度 - 禁用态
$width-radio_innder-border$border-thickness-control描边宽度 - 禁用态
$width-radio-outline$width-focus-ring单选框轮廓宽度
$height-radio_inner_min20px单选按钮高度
$width-radio_inner$width-icon-medium单选按钮宽度
$spacing-radio_addon-paddingLeft$spacing-tight单选标题到单选按钮左侧边距
$spacing-radio_addon_buttonRadio_large-paddingX$spacing-loose大尺寸按钮式单选按钮水平内边距
$spacing-radio_addon_buttonRadio_large-paddingY$spacing-base-tight * 0.5大尺寸按钮式单选按钮垂直内边距
$spacing-radio_addon_buttonRadio_small-paddingX$spacing-base小尺寸按钮式单选按钮水平内边距
$spacing-radio_addon_buttonRadio_small-paddingY$spacing-super-tight中尺寸按钮式单选按钮垂直内边距
$spacing-radio_addon_buttonRadio_middle-paddingX$spacing-base中尺寸按钮式单选按钮水平内边距
$spacing-radio_addon_buttonRadio_middle-paddingY$spacing-extra-tight中尺寸按钮式单选按钮垂直内边距
$spacing-radio_content-rowGap4px内容行间距
$spacing-radio_group_vertical-marginBottom$spacing-base-tight垂直布局单选框组底部外边距
$spacing-radio_group_horizontal-marginRight$spacing-base水平单选框组右侧外边距
$spacing-radio_buttonRadio-padding$spacing-extra-tight按钮式单选内边距
$spacing-radio_buttonRadioGroup_small-paddingX$spacing-super-tight小尺寸按钮式单选组水平内边距
$spacing-radio_buttonRadioGroup_small-paddingY$spacing-extra-tight小尺寸按钮式单选组垂直内边距
$spacing-radio_buttonRadioGroup_middle-padding$spacing-extra-tight中尺寸按钮式单选组内边距
$spacing-radio_buttonRadioGroup_large-padding$spacing-extra-tight大尺寸按钮式单选组内边距
$spacing-radio_buttonRadioGroup-paddingRight$spacing-none中尺寸按钮式单选组右侧内边距
$spacing-radio_cardRadioGroup-paddingX$spacing-base卡片式单选组水平内边距
$spacing-radio_cardRadioGroup-paddingY$spacing-base-tight卡片式单选组垂直内边距
$font-radio_buttonRadio_large-default-size$font-size-regular大尺寸按钮式单选标题字体大小
$font-radio_buttonRadio_small-default-size$font-size-small中尺寸按钮式单选标题字体大小
$font-radio_buttonRadio_middle-default-size$font-size-small小尺寸按钮式单选标题字体大小
$font-radio_buttonRadio-default-fontWeight$font-weight-bold按钮式单选标题字重 - 默认态
$font-radio_buttonRadio-hover-fontWeight$font-weight-bold按钮式单选标题字重 - 悬浮态
$font-radio_buttonRadio-checked-fontWeight$font-weight-bold按钮式单选标题字重 - 选中态
$font-radio_buttonRadioGroup_small-lineHeight16px小尺寸按钮式单选标题行高
$font-radio_buttonRadioGroup_middle-lineHeight16px中尺寸按钮式单选标题行高
$font-radio_buttonRadioGroup_large-lineHeight20px大尺寸按钮式单选标题行高
$font-radio_cardRadioGroup_addon-size$font-size-regular卡片式单选组标题字体大小
$font-radio_cardRadioGroup_addon-fontWeight$font-weight-bold卡片式单选组标题字体大小
$font-radio_cardRadioGroup_addon-lineHeight20px卡片式单选组标题行高
$font-radio_cardRadioGroup_extra-size$font-size-regular卡片式单选组副标题字体大小
$font-radio_cardRadioGroup_extra-fontWeightnormal卡片式单选组副标题字重
$font-radio_cardRadioGroup_extra-lineHeight20px卡片式单选组副标题行高