Components
Form
FormField + FormLabel + FormControl + FormDescription + FormErrorMessage. useId 기반 a11y 연결만 담당.
사용
import {
FormField, FormLabel, FormControl, FormDescription, FormErrorMessage,
} from "@fluxloop-ai/pds-ui/components/form";
<FormField>
<FormLabel required>이메일</FormLabel>
<FormControl>
<Input type="email" invalid={invalid} />
</FormControl>
<FormDescription>회사 도메인이 아니어도 됩니다.</FormDescription>
<FormErrorMessage>{invalid ? "형식을 확인하세요." : null}</FormErrorMessage>
</FormField>
Input + description + error
회사 도메인이 아니어도 됩니다.
Select
초대 시 기본 소속으로 설정됩니다.
Checkbox
필수 항목입니다.
연결 모델
FormField 는 useId() 로 base id 를 생성하고, 파생 id 4개를 context 로 제공한다.
| ID 역할 | 값 | 소비처 |
|---|---|---|
| label | {base}-label | FormLabel (id) |
| field | {base}-field | FormLabel htmlFor, FormControl id, FormControl aria-labelledby 참조 |
| description | {base}-description | FormDescription id, FormControl aria-describedby |
| error | {base}-error | FormErrorMessage id, FormControl aria-describedby |
FormControl 은 @radix-ui/react-slot 으로 자식 control(Input, Select, Checkbox 등) 에 id, aria-labelledby, aria-describedby, aria-invalid 를 주입한다.
Decision: invalid 소유권
invalid 는 context 로 전파하지 않는다. Consumer 가 <Input invalid> / <Checkbox invalid> 처럼 control 에 직접 지정. FormField 는 FormErrorMessage 가 children 을 받았을 때만 aria-invalid 를 컨트롤에 반영한다 — 스타일·상태 소유권은 control 쪽.
Props
FormField
| Prop | 타입 | 기본 | 설명 |
|---|---|---|---|
name | string | (useId) | 외부에서 id base 를 지정할 수 있음 |
size | sm | md | md | Label/Description/Error 텍스트 크기 |
FormLabel
| Prop | 타입 | 기본 | 설명 |
|---|---|---|---|
required | boolean | - | 꼬리에 * |
FormErrorMessage
children 이 비어있으면(null, "", false) 자동으로 null 을 반환. 이 때 FormControl 의 aria-describedby 에서도 제외.
Registry 설치
npx shadcn add https://pds.pluto.com/r/form