# Radio Group
URL: /lynx/components/radio-group
Source: https://github.com/daangn/seed-design/blob/dev/docs/content/lynx/components/radio-group.mdx
사용자가 여러 옵션 중 하나만 선택할 수 있게 하는 라디오 그룹 컴포넌트입니다.
Lynx Engine 최소 버전: 3.6
사용 가능 버전: @seed-design/lynx-react@0.1.0, @seed-design/lynx-css@0.1.0
## Preview
```tsx
import "./styles";
import { VStack, useSeedClassName } from "@seed-design/lynx-react";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
);
}
```
## Installation
- npm: npx @seed-design/cli add ui:radio-group
- pnpm: pnpm dlx @seed-design/cli add ui:radio-group
- yarn: yarn dlx @seed-design/cli add ui:radio-group
- bun: bun x @seed-design/cli add ui:radio-group
## Usage
`RadioGroup`은 선택 상태와 함께 Field의 안내 정보를 표시합니다. `label`, `labelWeight`, `indicator`, `showRequiredIndicator`, `description`, `errorMessage`를 사용할 수 있습니다.
```tsx
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export function ContactMethod() {
return (
);
}
```
`invalid`가 `true`이고 `errorMessage`가 있으면 화면에는 `description` 대신 오류 메시지를 표시합니다.
## Props
### `RadioGroup`
### `RadioGroupItem`
### `Radiomark`
## 접근성
`RadioGroup`은 기본적으로 접근성 요소이며 `accessibility-role-description="radiogroup"`을 사용합니다. 그룹이 비활성 상태이면 `accessibility-traits="disabled"`도 전달합니다. Registry `RadioGroup`에 문자열 `label`을 전달하면 같은 내용을 `accessibility-label`에도 연결합니다.
`RadioGroupItem`은 기본적으로 `accessibility-role-description="radio"`를 사용합니다. 선택 상태는 `accessibility-value`의 `selected` 또는 `not selected`로 전달하며, 비활성 상태는 `accessibility-traits="disabled"`로 전달합니다.
문자열 `label`을 사용하면 Registry 래퍼가 그 값을 항목의 `accessibility-label`로 연결합니다. `label`에 문자열이 아닌 콘텐츠를 넣거나 컴파운드 API를 직접 조합할 때는 각 항목에 `accessibility-label`을 명시하세요. 필요하면 모든 기본 접근성 prop을 직접 덮어쓸 수 있습니다.
## Examples
### Sizes
```tsx
import "./styles";
import { VStack, useSeedClassName } from "@seed-design/lynx-react";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
);
}
```
### Tones
#### Brand
```tsx
import "./styles";
import { VStack, useSeedClassName } from "@seed-design/lynx-react";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
);
}
```
#### Neutral
```tsx
import "./styles";
import { VStack, useSeedClassName } from "@seed-design/lynx-react";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
);
}
```
### Weights
React의 항목별 `weight`와 달리 Lynx의 `weight`는 그룹 단위 prop입니다. 아래 예제는 굵기마다 그룹을 나눕니다. 두 그룹은 같은 제어 값을 공유하므로 두 항목 중 하나만 선택됩니다.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { VStack, useSeedClassName } from "@seed-design/lynx-react";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
const [value, setValue] = useState("regular");
return (
);
}
```
### Long Label
Lynx의 `size`도 그룹 단위 prop입니다. 아래 예제는 크기마다 그룹을 나눕니다. 두 그룹은 같은 제어 값을 공유하므로 두 항목 중 하나만 선택됩니다.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { VStack, useSeedClassName } from "@seed-design/lynx-react";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
const longLabel =
"Consequat ut veniam aliqua deserunt occaecat enim occaecat veniam et et cillum nulla officia incididunt incididunt. Sint laboris labore occaecat fugiat culpa voluptate ullamco in elit dolore exercitation nulla.";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
const [value, setValue] = useState("medium");
return (
);
}
```
### Disabled
`RadioGroup`의 `disabled`는 그룹 전체를 비활성화합니다. 개별 `RadioGroupItem`도 따로 비활성화할 수 있습니다.
```tsx
import "./styles";
import { VStack, useSeedClassName } from "@seed-design/lynx-react";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
);
}
```
### Listening to Value Changes
`RadioGroup`의 `onValueChange`로 선택 값 변경을 감지할 수 있습니다. Controlled 모드에서는 `value`와 `onValueChange`를 함께 사용합니다.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { VStack, useSeedClassName } from "@seed-design/lynx-react";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
const [count, setCount] = useState(0);
const [lastValue, setLastValue] = useState(null);
return (
{
setCount((previous) => previous + 1);
setLastValue(value);
}}
>
onValueChange called: {count} times, last value: {lastValue ?? "-"}
);
}
```
### Use Cases
#### React Hook Form
React Hook Form은 HTML 폼과 input을 전제로 하므로 Lynx에서는 같은 예제를 실행할 수 없습니다. Lynx에서는 `value`와 `onValueChange`로 선택 값을 제어하세요. 제출과 검증은 앱의 상태 관리와 요청 흐름에서 처리합니다.
#### Using `Radiomark`
Registry의 `Radiomark`와 `@seed-design/lynx-react`의 컴파운드 API를 함께 사용하면 선택 상태를 공유하면서 항목의 배치를 바꿀 수 있습니다. `Radiomark`는 `RadioGroup.Item` 안에서만 사용할 수 있습니다.
```tsx
import "./styles";
import {
HStack,
RadioGroup as RadioGroupPrimitive,
VStack,
useSeedClassName,
} from "@seed-design/lynx-react";
import { RadioGroup, Radiomark } from "@/components/ui/radio-group";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
regularmediumbold
);
}
```
### RadioGroupField Integration
`label`, `description`, `errorMessage` 등의 RadioGroupField 관련 prop을 사용할 수 있습니다.
```tsx
import "./styles";
import { useState } from "@lynx-js/react";
import { ActionButton, HStack, VStack, useSeedClassName } from "@seed-design/lynx-react";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
const [contact, setContact] = useState("email");
const [firstErrorMessage, setFirstErrorMessage] = useState();
const [option, setOption] = useState("option1");
const [secondErrorMessage, setSecondErrorMessage] = useState();
const handleFirstSubmit = () => {
setFirstErrorMessage(contact === "email" ? "이메일은 선택할 수 없습니다." : undefined);
};
const handleSecondSubmit = () => {
setSecondErrorMessage(option === "option1" ? "옵션 1은 선택할 수 없습니다." : undefined);
};
return (
제출
제출
);
}
```
## Scale Feedback
Lynx `RadioGroupItem`은 누르는 동안 `Radiomark`의 배경색을 바꿉니다. React처럼 크기를 줄이지 않으므로 `--seed-radiomark-feedback-scale` CSS 변수도 사용하지 않습니다.
## 웹 버전과의 차이
Lynx `RadioGroup`은 React `RadioGroup`과 다음과 같은 차이가 있습니다.
- **오류 안내 렌더링**: React는 오류가 표시될 때 `description`을 접근성 트리에 남기지만, Lynx에는 DOM의 visually hidden 처리 방식이 없어 화면과 접근성 트리에서 `description`을 제외하고 `errorMessage`만 렌더링합니다.
- **아이콘 렌더링 방식**: 기본 `RadioGroup.ItemIndicator`는 `` 점으로 렌더됩니다. 사용자 지정 아이콘을 전달하려면 `@karrotmarket/lynx-monochrome-icon`을 별도로 설치하고 단색 아이콘 컴포넌트를 사용하세요. `
사용자 지정 아이콘 패키지는 Registry 기본 설치에 포함되지 않습니다.
```sh
bun add @karrotmarket/lynx-monochrome-icon@^1.20.0
```
## Lynx 미지원 기능
현재 Lynx 플랫폼 제약으로 다음 기능이 지원되지 않습니다.
### 런타임 모델 차이로 제외
| 기능 | 웹 대응 | 설명 |
| --------------------------- | ---------------------- | ------------------------------------------ |
| React Hook Form | HTML form 라이브러리 | `value`와 `onValueChange` 및 앱 수준 제출 로직으로 대체 |
| `RadioGroupItemHiddenInput` | `` | Lynx에 HTML form 제출 모델 없음 |
| `name` | native form field name | Lynx에 native form 제출 모델 없음 |
| `focus` / `focusVisible` | 키보드 포커스 | Lynx에 키보드 포커스 개념 없음 |
| `onChange` (raw DOM event) | `React.ChangeEvent` | 의미 없음. `onValueChange`로 대체 |