import { useState } from "react";
import { Radio } from "@lark-ui/core";
/** 展示基础的受控单选按钮组(Radio) */
export function RadioBasicDemo() {
const [value, setValue] = useState("email");
return (
<Radio.Group legend="通知偏好" value={value} onValueChange={setValue}>
<Radio.Item label="邮件" value="email" />
<Radio.Item label="短信" value="sms" />
<Radio.Item label="推送通知" value="push" />
</Radio.Group>
);
}安装
统一导出
import { Radio } from "@lark-ui/core";按需导出
import { Radio } from "@lark-ui/core/components/radio";用法
import { Radio } from "@lark-ui/core";
export default function Example() {
return (
<Radio.Group legend="Choose an option" defaultValue="a">
<Radio.Item label="Option A" value="a" />
<Radio.Item label="Option B" value="b" />
</Radio.Group>
);
}示例
默认(垂直)
单选按钮组(Radio.Group)默认垂直排列。每个单选按钮的标签显示在其右侧。
import { useState } from "react";
import { Radio } from "@lark-ui/core";
/** 展示默认的纵向单选按钮组布局 */
export function RadioDefaultDemo() {
const [value, setValue] = useState("personal");
return (
<Radio.Group legend="账户类型" value={value} onValueChange={setValue}>
<Radio.Item label="个人" value="personal" />
<Radio.Item label="商业" value="business" />
<Radio.Item label="企业版" value="enterprise" />
</Radio.Group>
);
}水平排列
使用 orientation="horizontal" 可获得行内布局。空间不足时选项会自动换行。
import { useState } from "react";
import { Radio } from "@lark-ui/core";
/** 展示横向单选按钮组布局 */
export function RadioHorizontalDemo() {
const [value, setValue] = useState("md");
return (
<Radio.Group
legend="尺寸"
orientation="horizontal"
value={value}
onValueChange={setValue}
>
<Radio.Item label="小" value="sm" />
<Radio.Item label="中" value="md" />
<Radio.Item label="大" value="lg" />
</Radio.Group>
);
}分段样式
使用 appearance="segmented" 可获得行内紧凑的选项。选项不会换行,因此请据此设计布局。
import { useState } from "react";
import { Radio } from "@lark-ui/core";
export function RadioSegmentedDemo() {
const [duration, setDuration] = useState("1");
return (
<Radio.Group
appearance="segmented"
legend="时长预设"
value={duration}
onValueChange={setDuration}
>
<Radio.Item label="1h" value="1" />
<Radio.Item label="12h" value="12" />
<Radio.Item label="24h" value="24" />
</Radio.Group>
);
}是否应该使用分段样式?
仅当分组较小、标签简短且控件能放下一行时,才使用分段样式。标签较长、需要描述性选项、选项数量较多或布局较窄时,请使用默认样式。
当选择结果决定显示哪个内容面板时,请使用 标签页(Tabs) 组件。
默认与分段对比
外观仅影响呈现方式。两个示例表达的是同一组互斥的选项。
import { Radio } from "@lark-ui/core";
export function RadioAppearanceComparisonDemo() {
return (
<div className="flex flex-wrap gap-8">
<Radio.Group legend="默认外观" orientation="horizontal" defaultValue="1">
<Radio.Item label="1h" value="1" />
<Radio.Item label="12h" value="12" />
<Radio.Item label="24h" value="24" />
</Radio.Group>
<Radio.Group appearance="segmented" legend="分段外观" defaultValue="1">
<Radio.Item label="1h" value="1" />
<Radio.Item label="12h" value="12" />
<Radio.Item label="24h" value="24" />
</Radio.Group>
</div>
);
}禁用的分段控件
分段控件组支持禁用整个分组或禁用单个选项。
import { Radio } from "@lark-ui/core";
export function RadioSegmentedDisabledDemo() {
return (
<div className="flex flex-wrap gap-8">
<Radio.Group
appearance="segmented"
legend="禁用的单选组"
defaultValue="12"
disabled
>
<Radio.Item label="1h" value="1" />
<Radio.Item label="12h" value="12" />
<Radio.Item label="24h" value="24" />
</Radio.Group>
<Radio.Group appearance="segmented" legend="禁用的选项" defaultValue="1">
<Radio.Item label="1h" value="1" />
<Radio.Item label="12h" value="12" disabled />
<Radio.Item label="24h" value="24" />
</Radio.Group>
</div>
);
}使用自定义图例的分段控件
Radio.Legend 保持在分段控件表面之外,为分组提供无障碍名称。
import { Radio } from "@lark-ui/core";
export function RadioSegmentedLegendDemo() {
return (
<Radio.Group appearance="segmented" defaultValue="automatic">
<Radio.Legend className="text-sm font-normal text-lark-subtle">
配置模式
</Radio.Legend>
<Radio.Item label="自动" value="automatic" />
<Radio.Item label="手动" value="manual" />
</Radio.Group>
);
}长标签与窄布局
分段控件保持其固有宽度,不会换行、收缩或截断选项。当翻译后的标签或过窄的容器导致分组 无法排在一行内时,请选择默认样式。
import { Radio } from "@lark-ui/core";
export function RadioSegmentedLongLabelsDemo() {
return (
<div className="w-48 max-w-full">
<Radio.Group
appearance="segmented"
legend="处理偏好"
defaultValue="automatic"
>
<Radio.Item label="自动处理" value="automatic" />
<Radio.Item label="手动配置" value="manual" />
</Radio.Group>
</div>
);
}带描述
使用 description 属性可以在单选按钮下方添加辅助说明文字。
import { useState } from "react";
import { Radio } from "@lark-ui/core";
/** 展示带辅助说明文字的单选按钮组 */
export function RadioDescriptionDemo() {
const [value, setValue] = useState("standard");
return (
<Radio.Group
legend="配送方式"
description="选择你希望接收订单的方式"
value={value}
onValueChange={setValue}
>
<Radio.Item label="标准(5-7 天)" value="standard" />
<Radio.Item label="加急(2-3 天)" value="express" />
<Radio.Item label="隔夜送达" value="overnight" />
</Radio.Group>
);
}控件位置
使用 controlPosition="end" 可以把标签放在单选按钮之前。
import { Radio } from "@lark-ui/core";
/** 展示标签位于单选控件之前的单选按钮组 */
export function RadioControlPositionDemo() {
return (
<Radio.Group legend="偏好设置" controlPosition="end" defaultValue="a">
<Radio.Item label="标签在单选按钮之前" value="a" />
<Radio.Item label="另一个选项" value="b" />
</Radio.Group>
);
}单选卡片
在分组上使用 appearance="card",可以把每个选项显示为同一张卡片中的可选行,行之间用
分隔线隔开。结合每个选项上的 description 属性可以呈现更丰富的内容。
import { useState } from "react";
import { Radio } from "@lark-ui/core";
/** 展示带 Lark 套餐选项的单选卡片外观 */
export function RadioCardDemo() {
const [value, setValue] = useState("free");
return (
<Radio.Group
legend="选择套餐"
appearance="card"
value={value}
onValueChange={setValue}
>
<Radio.Item
label="免费版"
description="适合个人或业余项目,不适合关键业务场景。"
value="free"
/>
<Radio.Item
label="专业版"
description="适合专业网站,不适合关键业务场景。"
value="pro"
/>
<Radio.Item
label="商业版"
description="适合线上运营的小型企业。"
value="business"
/>
<Radio.Item
label="合约版"
description="适合作为业务核心的关键应用。"
value="contract"
/>
</Radio.Group>
);
}单选卡片(控件在左侧)
在卡片式单选按钮组上使用 controlPosition="start",可以把单选控件放在标签和描述的左侧。
import { useState } from "react";
import { Radio } from "@lark-ui/core";
/** 展示通过 controlPosition="start" 将控件置于左侧的单选卡片外观 */
export function RadioCardControlStartDemo() {
const [value, setValue] = useState("free");
return (
<Radio.Group
legend="选择套餐"
appearance="card"
controlPosition="start"
value={value}
onValueChange={setValue}
>
<Radio.Item
label="免费版"
description="适合个人或业余项目,不适合关键业务场景。"
value="free"
/>
<Radio.Item
label="专业版"
description="适合专业网站,不适合关键业务场景。"
value="pro"
/>
</Radio.Group>
);
}富标签内容
Radio.Item 上的 label 属性接受 React 节点,因此你可以在文本旁嵌入图标、徽标或其他标记。
import { useState } from "react";
import { Badge, Radio } from "@lark-ui/core";
/** 展示 Radio.Item 标签中使用富文本 ReactNode 内容(图标、徽标或额外标记) */
export function RadioRichLabelDemo() {
const [value, setValue] = useState("pro");
return (
<Radio.Group
legend="选择套餐"
appearance="card"
value={value}
onValueChange={setValue}
>
<Radio.Item
label={
<span className="flex items-center gap-2">
免费版
<Badge variant="neutral">$0</Badge>
</span>
}
description="适合个人或业余项目。"
value="free"
/>
<Radio.Item
label={
<span className="flex items-center gap-2">
专业版
<Badge variant="primary">热门</Badge>
</span>
}
description="适合专业网站。"
value="pro"
/>
</Radio.Group>
);
}单选卡片(水平)
将 appearance="card" 与 orientation="horizontal" 结合使用,可以在同一张卡片内把选项
排成两列。
import { useState } from "react";
import { Radio } from "@lark-ui/core";
/** 展示横向布局的单选卡片外观 */
export function RadioCardHorizontalDemo() {
const [value, setValue] = useState("free");
return (
<Radio.Group
legend="选择套餐"
appearance="card"
orientation="horizontal"
value={value}
onValueChange={setValue}
>
<Radio.Item
label="免费版"
description="适合个人或业余项目,不适合关键业务场景。"
value="free"
/>
<Radio.Item
label="专业版"
description="适合专业网站,不适合关键业务场景。"
value="pro"
/>
<Radio.Item
label="商业版"
description="适合线上运营的小型企业。"
value="business"
/>
<Radio.Item
label="合约版"
description="适合作为业务核心的关键应用。"
value="contract"
/>
</Radio.Group>
);
}带错误
使用 error 属性在分组级别展示校验错误。
import { Radio } from "@lark-ui/core";
/** 展示默认样式和卡片样式单选按钮组的错误状态 */
export function RadioErrorDemo() {
return (
<div className="grid grid-cols-2 gap-6">
<Radio.Group legend="支付方式" error="请选择一种支付方式以继续">
<Radio.Item label="信用卡" value="card" variant="error" />
<Radio.Item label="PayPal" value="paypal" variant="error" />
</Radio.Group>
<Radio.Group
legend="支付方式"
appearance="card"
error="请选择一种支付方式以继续"
>
<Radio.Item
label="信用卡"
description="可使用 Visa、Mastercard、美国运通或 Elo 支付。"
value="card"
variant="error"
/>
<Radio.Item
label="PayPal"
description="使用你的 PayPal 账户支付。"
value="paypal"
variant="error"
/>
</Radio.Group>
</div>
);
}禁用
禁用整个分组或单个选项。
import { Radio } from "@lark-ui/core";
/** 展示默认样式和卡片样式单选按钮组的禁用状态 */
export function RadioDisabledDemo() {
return (
<div className="grid grid-cols-2 gap-6">
<Radio.Group legend="禁用的单选组" disabled defaultValue="a">
<Radio.Item label="选项 A" value="a" />
<Radio.Item label="选项 B" value="b" />
</Radio.Group>
<Radio.Group legend="单独禁用" defaultValue="available">
<Radio.Item label="可用" value="available" />
<Radio.Item label="不可用" value="unavailable" disabled />
</Radio.Group>
<Radio.Group
legend="禁用的卡片单选组"
appearance="card"
disabled
defaultValue="a"
>
<Radio.Item label="选项 A" description="该选项已禁用。" value="a" />
<Radio.Item label="选项 B" description="该选项已禁用。" value="b" />
</Radio.Group>
<Radio.Group
legend="单独禁用的卡片"
appearance="card"
defaultValue="available"
>
<Radio.Item
label="可用"
description="该选项可以选择。"
value="available"
/>
<Radio.Item
label="不可用"
description="该选项不可用。"
value="unavailable"
disabled
/>
</Radio.Group>
</div>
);
}视觉隐藏的图例
在 Radio.Legend 上使用 className="sr-only",可以让图例对屏幕阅读器保持可访问,同时在
视觉上隐藏。当单选按钮组已经由父级 Field 或标题标注,显示图例会造成标签重复时,这会
非常有用。
import { useState } from "react";
import { Radio } from "@lark-ui/core";
/** 展示使用 sr-only 的 Radio.Legend,在保留无障碍语义的同时视觉隐藏图例;当父级 Field 已提供可见标签时非常有用 */
export function RadioLegendSrOnlyDemo() {
const [value, setValue] = useState("all");
return (
<Radio.Group defaultValue="all" value={value} onValueChange={setValue}>
<Radio.Legend className="sr-only">路径</Radio.Legend>
<Radio.Item label="允许所有路径" value="all" />
<Radio.Item label="限制为特定路径" value="specific" />
</Radio.Group>
);
}自定义图例样式
Radio.Legend 接受 className,可完全控制图例的呈现方式。当需要自定义排版、颜色或布局时,
请使用它代替 legend 字符串属性。
import { useState } from "react";
import { Radio } from "@lark-ui/core";
/** 展示使用自定义样式的 Radio.Legend,完全掌控图例的呈现方式 */
export function RadioLegendCustomDemo() {
const [value, setValue] = useState("email");
return (
<Radio.Group value={value} onValueChange={setValue}>
<Radio.Legend className="text-sm font-normal text-lark-subtle">
通知偏好
</Radio.Legend>
<Radio.Item label="邮件" value="email" />
<Radio.Item label="短信" value="sms" />
<Radio.Item label="推送通知" value="push" />
</Radio.Group>
);
}类型化取值
Radio.Group 和 Radio.Item 支持泛型。传入类型参数(例如 <number> 或枚举类型),可以
约束两个子组件上 value 的类型,以及 Radio.Group 上的 defaultValue 和 onValueChange。
省略时默认为 string。
enum ThemeType {
dark = "dark",
light = "light",
system = "system",
}
export function RadioTypedValueDemo() {
const [pageSize, setPageSize] = useState<number>(10);
const [theme, setTheme] = useState<ThemeType>(ThemeType.system);
return (
<div className="grid grid-cols-2 gap-6">
<Radio.Group<number>
legend="Items per page"
value={pageSize}
onValueChange={setPageSize}
>
<Radio.Item<number> label="10" value={10} />
<Radio.Item<number> label="25" value={25} />
<Radio.Item<number> label="50" value={50} />
</Radio.Group>
<Radio.Group<ThemeType>
legend="Theme"
value={theme}
onValueChange={setTheme}
>
<Radio.Item<ThemeType> label="Light" value={ThemeType.light} />
<Radio.Item<ThemeType> label="Dark" value={ThemeType.dark} />
<Radio.Item<ThemeType> label="System" value={ThemeType.system} />
</Radio.Group>
</div>
);
}API 参考
Radio.Group
单选按钮的容器,支持图例(legend)、描述和错误提示。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| legend | string | - | 分组标题文字(无障碍访问必需)。如需更多控制标题样式,请省略此属性,改用 `<Radio.Legend>` 作为子元素。 |
| children* | ReactNode | - | 子级的 Radio.Item 组件(也可以包含 Radio.Legend) |
| orientation | "vertical" | "horizontal" | - | 单选项的排列方向 |
| appearance | LarkRadioAppearance | - | 应用到所有 Radio.Item 子元素的外观样式。- `"default"` — 标准行内单选项 - `"card"` — 带边框、内边距和高亮选中态的选项卡片 - `"segmented"` — 适合少量选项的单行紧凑分组 单个单选项可以覆盖默认和卡片外观;分段式仅用于分组,不能被单个单选项覆盖。 |
| error | string | - | 分组的错误信息 |
| description | ReactNode | - | 分组的辅助说明文字 |
| value | T | - | 选中单选项的受控值。 |
| disabled | boolean | - | 分组内所有单选按钮是否禁用 |
| controlPosition | RadioControlPosition | - | 单选控件相对标签的位置:“start”把单选按钮放在标签之前,“end”把标签放在单选按钮之前。默认外观下为“start”,卡片外观下为“end”。 |
| name | string | - | 单选分组在表单提交时使用的名称 |
| className | string | - | 额外的 CSS 类名 |
| defaultValue | T | - | 选中单选项的初始值(非受控)。 |
| onValueChange | (value: T, eventDetails: RadioGroupChangeEventDetails) => void | - | 选中值变化时触发的回调。第二个参数携带关于本次交互的原生事件信息。 |
Radio.Legend
Radio.Group 的可组合图例子组件。接受 className,可完全控制样式(例如用
className="sr-only" 在视觉上隐藏)。当需要自定义图例样式时,请使用它代替 legend
字符串属性。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| children* | ReactNode | - | 标题内容 |
| className | string | - | 额外的 CSS 类名(例如用 “sr-only” 在视觉上隐藏标题) |
Radio.Item
Radio.Group 中的单个单选按钮。
| 属性 | 类型 | 默认值 |
|---|
该组件没有专有属性,支持标准 HTML 属性。