Chuyển tới nội dung

Pro đang mở bán trước. Cài đặt mở từ tháng 1/2027. Xem Pro

Component

RadioGroup

Một lựa chọn trong số vài phương án mà người dùng so sánh cạnh nhau. Mỗi phương án là vòng tròn 16px, label đứng sau và description tùy chọn nằm dưới label; phương án đã chọn tô bằng accent và hiện một chấm on-accent.

  • npm: 2 trực tiếp, 5 tổng
  • registry: 3 trực tiếp, 4 tổng

Xem trước

Gói

Tối đa 3 dự án.

Không giới hạn dự án và lịch sử phiên bản.

Pro, thêm thư viện dùng chung và vai trò.

Props

  • orientation
  • variant
  • defaultValue
  • value
  • disabled
  • descriptions
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

<div className="flex flex-col gap-sm">
  <span id="preview-plan-heading" className="text-sm font-medium text-text-primary">Gói</span>
  <RadioGroup aria-labelledby="preview-plan-heading" defaultValue="pro">
    <RadioGroupItem value="free" label="Miễn phí" description="Tối đa 3 dự án." />
    <RadioGroupItem value="pro" label="Pro" description="Không giới hạn dự án và lịch sử phiên bản." />
    <RadioGroupItem value="team" label="Nhóm" description="Pro, thêm thư viện dùng chung và vai trò." />
  </RadioGroup>
</div>

Cách dùng

Khi nào dùng

  • Chọn đúng một trong hai đến năm phương án mà người dùng cần thấy và so sánh cùng lúc, như một gói.
  • Phương án cần một dòng thứ hai để nói chúng nghĩa là gì.

Khi nào không dùng

  • Hơn năm phương án, hoặc phương án người dùng đã biết, như một quốc gia. Dùng Select.
  • Bật hoặc tắt một cài đặt. Dùng Switch.
  • Chọn nhiều phương án. Dùng Checkbox.

Biến thể

orientation

Đặt trên RadioGroup. vertical cho phương án có description hoặc label dài; horizontal cho hai hoặc ba phương án ngắn. Phím mũi tên đi theo hướng này.

  • Gói

    Tối đa 3 dự án.

    Không giới hạn dự án và lịch sử phiên bản.

    Pro, thêm thư viện dùng chung và vai trò.

    verticalmặc định

  • Gói

    Tối đa 3 dự án.

    Không giới hạn dự án và lịch sử phiên bản.

    Pro, thêm thư viện dùng chung và vai trò.

    horizontal

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

<div className="flex flex-col gap-sm">
  <span id="preview-plan-heading-orientation-vertical" className="text-sm font-medium text-text-primary">Gói</span>
  <RadioGroup aria-labelledby="preview-plan-heading-orientation-vertical" defaultValue="pro">
    <RadioGroupItem value="free" label="Miễn phí" description="Tối đa 3 dự án." />
    <RadioGroupItem value="pro" label="Pro" description="Không giới hạn dự án và lịch sử phiên bản." />
    <RadioGroupItem value="team" label="Nhóm" description="Pro, thêm thư viện dùng chung và vai trò." />
  </RadioGroup>
</div>
<div className="flex flex-col gap-sm">
  <span id="preview-plan-heading-orientation-horizontal" className="text-sm font-medium text-text-primary">Gói</span>
  <RadioGroup aria-labelledby="preview-plan-heading-orientation-horizontal" defaultValue="pro" orientation="horizontal">
    <RadioGroupItem value="free" label="Miễn phí" description="Tối đa 3 dự án." />
    <RadioGroupItem value="pro" label="Pro" description="Không giới hạn dự án và lịch sử phiên bản." />
    <RadioGroupItem value="team" label="Nhóm" description="Pro, thêm thư viện dùng chung và vai trò." />
  </RadioGroup>
</div>

variant

Đặt trên RadioGroup. default là vòng tròn thường kèm label. card vẽ mỗi lựa chọn thành một thẻ bao label và mô tả, cho vài lựa chọn cần một câu giải thích, chẳng hạn các gói. Thẻ được chọn nổi lên và viền dày hơn.

  • Gói

    Tối đa 3 dự án.

    Không giới hạn dự án và lịch sử phiên bản.

    Pro, thêm thư viện dùng chung và vai trò.

    defaultmặc định

  • Gói

    Tối đa 3 dự án.

    Không giới hạn dự án và lịch sử phiên bản.

    Pro, thêm thư viện dùng chung và vai trò.

    card

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

<div className="flex flex-col gap-sm">
  <span id="preview-plan-heading-variant-default" className="text-sm font-medium text-text-primary">Gói</span>
  <RadioGroup aria-labelledby="preview-plan-heading-variant-default" defaultValue="pro">
    <RadioGroupItem value="free" label="Miễn phí" description="Tối đa 3 dự án." />
    <RadioGroupItem value="pro" label="Pro" description="Không giới hạn dự án và lịch sử phiên bản." />
    <RadioGroupItem value="team" label="Nhóm" description="Pro, thêm thư viện dùng chung và vai trò." />
  </RadioGroup>
</div>
<div className="flex flex-col gap-sm">
  <span id="preview-plan-heading-variant-card" className="text-sm font-medium text-text-primary">Gói</span>
  <RadioGroup aria-labelledby="preview-plan-heading-variant-card" defaultValue="pro">
    <RadioGroupItem value="free" label="Miễn phí" description="Tối đa 3 dự án." />
    <RadioGroupItem value="pro" label="Pro" description="Không giới hạn dự án và lịch sử phiên bản." />
    <RadioGroupItem value="team" label="Nhóm" description="Pro, thêm thư viện dùng chung và vai trò." />
  </RadioGroup>
</div>

Ví dụ

Mặc định

Một tiêu đề nhìn thấy đặt tên nhóm qua aria-labelledby.

Gói

Tối đa 3 dự án.

Không giới hạn dự án và lịch sử phiên bản.

Pro, thêm thư viện dùng chung và vai trò.

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

<div className="flex flex-col gap-sm">
  <span id="plan-heading" className="text-sm font-medium text-text-primary">Gói</span>
  <RadioGroup aria-labelledby="plan-heading" defaultValue="pro">
    <RadioGroupItem value="free" label="Miễn phí" description="Tối đa 3 dự án." />
    <RadioGroupItem value="pro" label="Pro" description="Không giới hạn dự án và lịch sử phiên bản." />
    <RadioGroupItem value="team" label="Nhóm" description="Pro, thêm thư viện dùng chung và vai trò." />
  </RadioGroup>
</div>

Phương án ngắn trên một hàng

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

<RadioGroup aria-label="Chủ đề" orientation="horizontal" defaultValue="system">
  <RadioGroupItem value="system" label="Hệ thống" />
  <RadioGroupItem value="light" label="Sáng" />
  <RadioGroupItem value="dark" label="Tối" />
</RadioGroup>

Một phương án disabled

Phím mũi tên bỏ qua phương án đó.

Sẽ có vào cuối năm nay.

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

<RadioGroup aria-label="Khu vực" defaultValue="eu">
  <RadioGroupItem value="eu" label="Châu Âu" />
  <RadioGroupItem value="us" label="Hoa Kỳ" />
  <RadioGroupItem value="ap" label="Châu Á Thái Bình Dương" description="Sẽ có vào cuối năm nay." disabled />
</RadioGroup>

Dạng thẻ

Mỗi gói cần một câu giải thích, nên mỗi lựa chọn là một thẻ.

Three projects, community support.

Unlimited projects and priority support.

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"

<RadioGroup aria-label="Gói" defaultValue="pro" variant="card" className="w-full max-w-sm">
  <RadioGroupItem value="free" label="Miễn phí" description="Three projects, community support." />
  <RadioGroupItem value="pro" label="Pro" description="Unlimited projects and priority support." />
</RadioGroup>

Nên và không nên

Nên

  • Dùng cho hai đến năm phương án mà người dùng cần thấy và so sánh cùng lúc.
  • Đặt một tiêu đề nhìn thấy phía trên nhóm và trỏ aria-labelledby vào tiêu đề đó.
  • Chọn một mặc định khi có một phương án là lựa chọn thường dùng.
  • Thêm description khi riêng label không nói phương án nghĩa là gì.

Không nên

  • Đừng dùng cho hơn năm phương án; dùng Select.
  • Đừng dùng để bật hoặc tắt một cài đặt; dùng Switch.
  • Đừng dùng để chọn nhiều phương án; dùng Checkbox.

Props

TênKiểuGiá trịMặc địnhMô tả
orientationenumvertical | horizontalverticalĐặt trên RadioGroup. vertical cho phương án có description hoặc label dài; horizontal cho hai hoặc ba phương án ngắn. Phím mũi tên đi theo hướng này.
variantenumdefault | carddefaultĐặt trên RadioGroup. default là vòng tròn thường kèm label. card vẽ mỗi lựa chọn thành một thẻ bao label và mô tả, cho vài lựa chọn cần một câu giải thích, chẳng hạn các gói. Thẻ được chọn nổi lên và viền dày hơn.
defaultValuestring--Đặt trên RadioGroup. Giá trị được chọn ở lần render đầu, khi bạn không kiểm soát nó. Chọn một mặc định hợp lý khi đã có.
valuestring--Đặt trên RadioGroup. Giá trị đã chọn, khi bạn kiểm soát nó. Đi cùng onValueChange.
onValueChangefunction--Đặt trên RadioGroup. Được gọi với value của phương án vừa chọn.
disabledboolean-falseTrên RadioGroup thì tắt mọi phương án và làm mờ label; trên một RadioGroupItem thì chỉ phương án đó.
requiredboolean-falseĐặt trên RadioGroup. Phải chọn một phương án thì mới gửi được form.
namestring--Đặt trên RadioGroup. Tên trong form; form gửi giá trị đã chọn dưới tên này.
labelnode--Đặt trên RadioGroupItem. Tên nhìn thấy, sau vòng tròn. Nhấn vào tên thì chọn phương án.
descriptionnode--Đặt trên RadioGroupItem. Dòng thứ hai dưới label: phương án này nghĩa là gì. Cần label.

Slot

TênBắt buộcMô tả
itemscóHai đến năm RadioGroupItem, mỗi item có value và label.

Cấu tạo

PhầnMô tả
rootRadioGroup: các phương án trong một cột (gap-md), hoặc trong một hàng xuống dòng (gap-x-lg, gap-y-md).
itemRadioGroupItem: vòng tròn 16px, viền nhạt trên nền nổi với bóng nhẹ. Khi được chọn, accent tô kín tới mép.
indicatorChấm trong vòng tròn đã chọn: 6px, màu icon on-accent (::after của indicator ở currentColor).
hitArea::before trong suốt, căn giữa vòng tròn, không nhỏ hơn size-target-min (24px với chuột, 44px với cảm ứng).
rowKhi có label: hàng giữ vòng tròn, rồi Label và description, gap-sm. Dùng chung với Checkbox và Switch.
labelKhi có label: một Label sau vòng tròn, thẳng hàng với vòng tròn ở dòng đầu.
descriptionKhi có description: chữ secondary 14px dưới label, gap-xs.
tileVới variant card: thẻ bao quanh hàng, radius-element, padding spacing-md và viền ring-border. Nhấn vào bất kỳ đâu trên thẻ để chọn. Khi được chọn: nền nổi, shadow-low và vòng 2px accent.

Khả năng truy cập

Role: radiogroup

PhímHành động
TabĐưa focus vào nhóm, tới phương án đã chọn (hoặc phương án đầu), rồi đưa focus ra khỏi nhóm. Cả nhóm là một tab stop.
Arrow keysChuyển tới phương án kế hoặc phương án trước và chọn nó, quay từ phương án cuối về phương án đầu.
SpaceChọn phương án đang focus khi chưa chọn phương án nào.
  • Đặt tên nhóm: aria-labelledby với id của tiêu đề nhìn thấy phía trên, hoặc aria-label. Type bắt buộc một trong hai.
  • Đặt tên mỗi phương án bằng prop label; nhấn vào label thì chọn phương án. description liên kết bằng aria-describedby và được đọc sau tên.
  • Nhóm disabled làm mờ mọi label; phím mũi tên bỏ qua phương án disabled.
  • Trong form, một input ẩn mang name và giá trị đã chọn.
  • Phương án đã chọn khác các phương án còn lại ở cả chấm lẫn phần tô, nên lựa chọn không bao giờ chỉ dựa vào màu.

Cài đặt

npx werewolf-ui add radio-group

Chạy npx werewolf-ui init một lần trong app trước khi thêm component. Init cài token, thêm CSS import và luật cho agent. Add cài component này cùng các dependency và giữ nguyên theme của bạn. Xem Cài đặt để biết yêu cầu và cách cài qua registry.