섹션
컴포넌트
import { Label } from "@/components/ui/label"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
라디오 그룹은 서로 배타적인 옵션 집합을 보여 줍니다. 하나를 선택하면 나머지는 해제됩니다. Base UI Radio Group 프리미티브를 기반으로 하며, 네오브루탈리즘 공식(두꺼운 테두리, 선명한 그림자, 굵은 서체)에 맞춰 스타일을 입혔습니다.
다음과 같은 경우에 사용합니다.
- 플랜 선택기 — free / pro / enterprise를 선택 카드로 두고 하나만 고르게 합니다.
- 결제 옵션 — 배송 속도나 결제 수단처럼 모든 선택이 보여야 하는 경우.
- 옵션 2–5개 설정 — 테마, 밀도, 알림 빈도. select보다 클릭이 적습니다.
설치#
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/radio-group.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/radio-group.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/radio-group.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/radio-group.json
다음 의존성을 설치합니다.
pnpm add @base-ui/reactnpm install @base-ui/reactyarn add @base-ui/reactbun add @base-ui/react
다음 코드를 복사해서 프로젝트에 붙여넣습니다.
"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 }
import 경로를 프로젝트 구성에 맞게 수정합니다.
사용법#
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>구성#
RadioGroup을 만들려면 다음 구성을 사용합니다.
RadioGroup
├── RadioGroupItem
└── RadioGroupItem예제#
설명#
Field 컴포넌트를 사용해서 설명을 붙인 라디오 그룹 항목입니다.
import {
Field,
FieldContent,선택 카드#
FieldLabel로 Field 전체를 감싸면 클릭 가능한 카드 형태의 선택으로 만들 수 있습니다.
import {
Field,
FieldContent,Fieldset#
FieldSet과 FieldLegend를 사용해서 라벨과 설명과 함께 라디오 항목을 그룹화합니다.
import {
Field,
FieldDescription,비활성화#
RadioGroup의 disabled prop을 사용해서 모든 항목을 비활성화합니다.
import { Field, FieldLabel } from "@/components/ui/field"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
오류 상태#
RadioGroupItem에 aria-invalid, Field에 data-invalid를 지정해서 유효성 검증 오류를 표시합니다.
import {
Field,
FieldDescription,RTL#
Neobrutalism에서 RTL 지원을 활성화하는 방법은 RTL 설정 가이드를 참고하세요.
"use client"
import * as React from "react"접근성#
라디오 그룹은 WAI-ARIA Radio Group 패턴을 따릅니다. 컨테이너는 role="radiogroup", 각 항목은 aria-checked가 있는 role="radio" 버튼이며, 로빙 tabindex로 그룹 전체가 탭 스톱 하나입니다.
키보드 상호작용:
| 키 | 동작 |
|---|---|
Tab / Shift + Tab | 그룹으로 포커스 이동(선택된 항목, 없으면 첫 항목)/이탈 |
Space | 아직 아니면 포커스된 항목 선택 |
ArrowDown / ArrowRight | 다음 항목으로 포커스 이동 후 선택 |
ArrowUp / ArrowLeft | 이전 항목으로 포커스 이동 후 선택 |
좌우 화살표는 RTL에서 읽기 방향을 따릅니다.
API 참조#
자세한 내용은 Base UI 문서를 참고하세요.