RadioGroup
여러 선택지 중 정확히 하나를 고르는 세트입니다. 선택지마다 설명이 필요하거나 모든 선택지를 펼쳐 보여야 할 때 씁니다.
import { Radio, RadioGroup } from 'neba';
<RadioGroup label="플랜" defaultValue="team">
<Radio value="starter" label="Starter" />
<Radio value="team" label="Team" />
</RadioGroup>;Props
RadioGroup
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| size공통 | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | 높이와 타입 스케일 |
| color공통 | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'primary' | 의미론적 색 역할. 그룹이 정하고 모든 Radio가 물려받습니다 |
| orientation공통 | 'horizontal' | 'vertical' | 'vertical' | 옵션이 쌓이는 방향. 세로가 기본입니다. 가로는 라벨이 길어지는 순간 읽을 수 없어집니다 |
| label | ReactNode | — | 컨트롤과 연결되는 라벨. Base UI Field가 묶어 줍니다 |
| description | ReactNode | — | 보조 설명 |
| error | ReactNode | — | 오류 메시지. 값이 있으면 invalid 상태도 함께 켜지고 색 계열이 danger로 넘어갑니다 |
| invalid | boolean | !!error | 메시지 없이 invalid만 켭니다. 외부 폼 라이브러리가 유효성을 가질 때 |
| value | Value | — | 선택된 값. onValueChange와 함께 제어 컴포넌트로 씁니다 |
| defaultValue | Value | — | 초기 선택 값 |
| onValueChange | (value: Value, details) => void | — | 선택이 바뀔 때 |
| name | string | — | 폼 제출 시의 필드 이름 |
| required | boolean | false | 폼 제출 전에 하나를 골라야 함 |
| readOnly | boolean | false | 값은 보이지만 바꿀 수 없음. 색과 가장자리는 유지한 채 채도만 빠집니다 |
| disabled | boolean | false | 사용 불가. 색 계열을 버리고 중립 회색이 됩니다 |
| children | ReactNode | — | Radio들 |
| classNames | NebaSlots<'label' | 'control' | 'description' | 'error'> | — | 루트 뒤에 있는 각 파트의 class. 루트 자체는 className이 맡으므로 root 키는 없습니다 |
value와 onValueChange로 controlled, defaultValue로 uncontrolled 컴포넌트가 됩니다.
Radio
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| value * | Value | — | 이 옵션을 식별하는 값. 그룹의 value와 같은 언어로 말합니다 |
| label | ReactNode | — | 점 옆의 라벨 |
| description | ReactNode | — | 라벨 아래 보조 설명 |
| readOnly | boolean | false | 값은 보이지만 바꿀 수 없음. 색과 가장자리는 유지한 채 채도만 빠집니다 |
| disabled | boolean | false | 사용 불가. 색 계열을 버리고 중립 회색이 됩니다 |
| classNames | NebaSlots<'label' | 'control' | 'description' | 'indicator'> | — | 루트 뒤에 있는 각 파트의 class. 루트 자체는 className이 맡으므로 root 키는 없습니다 |
Radio에는 size도 color도 없습니다. 둘 다 RadioGroup에 지정하면 모든 선택지에 전달됩니다.
선택지가 많아 공간을 아껴야 한다면 Select, 두세 개를 한 줄에 붙여 놓아야 한다면 SegmentedButton을 쓰세요.
예시
description
선택지마다 설명을 붙일 수 있습니다. 설명이 몇 줄이 되어도 라디오 점은 라벨 첫 줄에 정렬된 채 유지됩니다.
orientation
기본값은 vertical입니다. horizontal은 라벨이 짧을 때만 쓰세요. 라벨 하나가 길어지면 줄이 읽기 어려워집니다.
disabled · readOnly
그룹 전체에도, 개별 Radio에도 지정할 수 있습니다. 그룹에 지정하면 모든 선택지에 전달됩니다.
classNames
group과 개별 option은 따로 스타일합니다. 둘은 서로 다른 컴포넌트이기 때문입니다. RadioGroup의 classNames는 label, control, description, error를 받고, 여기서 control은 option들을 담아 가로·세로 방향을 지고 있는 요소입니다. Radio의 classNames는 label, control, indicator, description을 받고, 여기서 control은 점입니다.
<RadioGroup label="Plan" classNames={{ control: 'gap-6' }}>
<Radio value="team" label="Team" classNames={{ control: 'rounded-sm' }} />
</RadioGroup>Radio에는 error slot이 없습니다. 유효성 메시지는 질문에 속하고, 질문은 group이기 때문입니다. 넘긴 class가 컴포넌트 자신의 class와 어떻게 겨루는지는 prop 규약을 보세요.
접근성
- 세트 전체가 tab 정지 하나를 차지하고, 그 안에서는 방향키로 이동합니다(roving tab index).
RadioGroup의label이 그룹의 accessible name이 됩니다.- 각
Radio의 라벨이 컨트롤과 연결되어 있어 글자를 눌러도 선택됩니다.