Bỏ qua đến nội dung

Nhóm radio

Một bộ nút radio chọn một tùy chọn duy nhất dành cho các biểu mẫu về gói cước, tùy chọn vận chuyển và cài đặt — với phong cách thiết kế theo trường phái tân thô mộc, kết hợp viền và bóng đổ.

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

Radio group hiển thị một tập các lựa chọn loại trừ lẫn nhau — chọn một mục sẽ bỏ chọn các mục còn lại. Được xây dựng trên thành phần Base UI Radio Group và tạo kiểu theo công thức neobrutalist: viền dày, bóng đổ đậm và kiểu chữ đậm.

Nên dùng khi:

  • Chọn gói dịch vụ — free / pro / enterprise dưới dạng thẻ lựa chọn, luôn chỉ một mục được chọn.
  • Tùy chọn thanh toán — tốc độ giao hàng hoặc phương thức thanh toán, nơi mọi lựa chọn phải luôn hiển thị.
  • Cài đặt có 2–5 lựa chọn — giao diện, mật độ hiển thị, tần suất thông báo; ít lần bấm hơn so với select.

Cài đặt

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/radio-group.json
npx shadcn@latest add https://neobrutalism.com/r/base/radio-group.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/radio-group.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/radio-group.json

Cài đặt các phụ thuộc sau:

pnpm add @base-ui/react
npm install @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react

Sao chép và dán đoạn mã sau vào dự án của bạn.

components/ui/radio-group.tsx
"use client"

import * as React from "react"
import { RadioGroup as RadioGroupPrimitive } from "radix-ui"

import { cn } from "@/lib/utils"

function RadioGroup({
  className,
  ...props
}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
  return (
    <RadioGroupPrimitive.Root
      data-slot="radio-group"
      className={cn("grid w-full gap-2", className)}
      {...props}
    />
  )
}

function RadioGroupItem({
  className,
  ...props
}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
  return (
    <RadioGroupPrimitive.Item
      data-slot="radio-group-item"
      className={cn(
        "group/radio-group-item peer relative flex aspect-square size-5 shrink-0 rounded-full border-2 bg-input shadow-sm outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive",
        className
      )}
      {...props}
    >
      <RadioGroupPrimitive.Indicator
        data-slot="radio-group-indicator"
        className="flex size-4 items-center justify-center"
      >
        <span className="absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary" />
      </RadioGroupPrimitive.Indicator>
    </RadioGroupPrimitive.Item>
  )
}

export { RadioGroup, RadioGroupItem }

Cập nhật các đường dẫn import cho phù hợp với thiết lập dự án của bạn.

Cách dùng

import { Label } from "@/components/ui/label"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
<RadioGroup defaultValue="option-one">
  <div className="flex items-center gap-3">
    <RadioGroupItem value="option-one" id="option-one" />
    <Label htmlFor="option-one">Option One</Label>
  </div>
  <div className="flex items-center gap-3">
    <RadioGroupItem value="option-two" id="option-two" />
    <Label htmlFor="option-two">Option Two</Label>
  </div>
</RadioGroup>

Kết hợp

Dùng cách kết hợp sau để xây dựng một RadioGroup:

RadioGroup
├── RadioGroupItem
└── RadioGroupItem

Ví dụ

Mô tả

Các mục radio group có mô tả bằng cách dùng component Field.

import {
  Field,
  FieldContent,

Choice Card

Dùng FieldLabel để bao bọc toàn bộ Field nhằm tạo một lựa chọn kiểu thẻ có thể nhấp.

import {
  Field,
  FieldContent,

Fieldset

Dùng FieldSetFieldLegend để nhóm các mục radio với một nhãn và một mô tả.

import {
  Field,
  FieldDescription,

Vô hiệu hóa

Dùng prop disabled trên RadioGroup để vô hiệu hóa tất cả các mục.

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

Không hợp lệ

Dùng aria-invalid trên RadioGroupItemdata-invalid trên Field để hiển thị lỗi xác thực.

import {
  Field,
  FieldDescription,

RTL

Để bật hỗ trợ RTL trong Neobrutalism, hãy xem hướng dẫn cấu hình RTL.

"use client"

import * as React from "react"

Khả năng truy cập

Radio group tuân theo mẫu Radio Group của WAI-ARIA: phần tử chứa render role="radiogroup", mỗi mục là một nút role="radio" kèm aria-checked, và cơ chế roving tabindex giữ cho cả nhóm chỉ là một điểm dừng Tab duy nhất.

Tương tác bàn phím:

PhímHành động
Tab / Shift + TabDi chuyển focus vào nhóm (mục đang chọn, hoặc mục đầu tiên) / ra ngoài
SpaceChọn mục đang focus nếu nó chưa được chọn
ArrowDown / ArrowRightDi chuyển focus đến mục kế tiếp và chọn mục đó
ArrowUp / ArrowLeftDi chuyển focus đến mục trước đó và chọn mục đó

Mũi tên trái và phải đi theo hướng đọc trong chế độ RTL.

Tham chiếu API

Xem tài liệu Base UI Radio Group.