Form
입력 컨트롤을 24칸 격자로 배치하고 라벨 설정을 한 번에 적용하는 폼 컨테이너 컴포넌트
개요
Cals Form은 Foundation Form을 래핑하여 24칸 CSS Grid 레이아웃을 제공하는 컴포넌트입니다. Form.Col로 칸을 나누고, 컨트롤이 label·required·description·error prop으로 라벨과 오류를 직접 그립니다. orientation, labelWidth 같은 라벨 설정을 Form에 한 번 주면 하위 컨트롤에 적용되고, 컨트롤에 같은 prop을 주면 컨트롤 값이 이깁니다.
주요 특징
- ✅ 24칸 격자:
Form.Col의span·offset으로 칸 배치,colGap·rowGap으로 간격 지정 - ✅ 라벨 일괄 설정:
orientation·labelWidth·labelAlign·labelVerticalAlign·required를 Form에서 한 번에 지정, 컨트롤 prop이 우선 - ✅ 컨트롤 내장 라벨: 컨트롤의
label·description·errorprop으로 라벨·설명·오류 표시 - ✅ 제출 보호:
action이 없으면 제출 시 페이지 이동을 막은 뒤onSubmit호출 - ✅ 칸 숨김:
span={0},className="hidden", 조건부 렌더로 칸 영역과 DOM 제어 - ✅ 표준 form 속성:
onSubmit·role·id·aria-*등을<form>에 그대로 전달
기본 사용
Form.Col로 칸 수를 정하고 컨트롤에 label을 줍니다. 컨트롤이 라벨을 직접 그리므로 FormItem으로 한 번 더 감싸지 않습니다. FormItem은 InputGroup처럼 label prop이 없는 내용에만 씁니다.
Preview
칸 나누기 (span / colGap / rowGap)
Form.Col의 span으로 칸 수를 정합니다. 칸 사이 가로 간격은 colGap(기본 15), 줄 사이 세로 간격은 rowGap(기본 20), 줄 기준 시작 위치는 offset으로 정합니다.
Preview
라벨 설정 (orientation / labelWidth)
Form의 orientation, labelWidth, labelAlign, labelVerticalAlign, required는 하위 컨트롤 라벨에 한 번에 적용됩니다. 컨트롤에 같은 prop을 주면 컨트롤 값이 Form 값을 이깁니다.
Preview
필수 입력 / 오류 표시
required로 필수 표시(*)를, description으로 보조 설명을, error로 입력 아래 오류 문구를 표시합니다. error가 있으면 description은 그려지지 않습니다.
Preview
제출 시 검사
onSubmit에서 직접 검사하고 error를 지정합니다. action이 없으면 Form이 제출의 기본 동작(페이지 이동)을 막은 뒤 onSubmit을 부릅니다. required는 입력에 HTML required를 붙이므로 직접 검사하려면 noValidate로 브라우저 검사를 끕니다. Enter로 제출하려면 제출 버튼(type="submit")이 필요하고, 제출 버튼이 없으면 입력이 하나일 때만 제출됩니다.
Preview
읽기 전용 (readOnly)
readOnly는 컨트롤마다 줍니다. Form의 readOnly는 하위 컨트롤에 내려가고 컨트롤에 준 readOnly가 이깁니다(지금은 Text만 읽습니다). ZipCodeKR(입력란이 늘 읽기 전용), ImageView, Button에는 readOnly prop이 없습니다.
Preview
칸 숨기기 (className / span)
칸을 숨기는 방법은 세 가지이며 모두 영역을 차지하지 않습니다. 입력값을 남길지에 따라 고릅니다.
| 방법 | DOM | 다시 보일 때 |
|---|---|---|
className="hidden" | 유지 | 값 유지 |
조건부 렌더 ({show && …}) | 없음 | 새로 마운트 |
span={0} | 유지 | 값 유지 |
Preview
API Reference
Props
Foundation FormProps를 받습니다. 표준 form 속성은 <form>에 그대로 갑니다.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | 폼 격자 안에 둘 내용 (Form.Col) |
columns | number | 24 | 격자 칸 수 |
colGap | number | 15 | 칸 사이 가로 간격 (px) |
rowGap | number | 20 | 줄 사이 세로 간격 (px). 마지막 줄 뒤에는 없음 |
readOnly | boolean | false | 하위 컨트롤에 내림. 컨트롤 값이 이김 (지금은 Text만 읽음) |
orientation | "vertical" | "horizontal" | "responsive" | - | 하위 컨트롤 라벨 배치 |
labelWidth | number | - | 하위 컨트롤 라벨 너비 (px, horizontal일 때) |
labelAlign | "start" | "center" | "end" | - | 하위 컨트롤 라벨 가로 정렬 |
labelVerticalAlign | "start" | "center" | "end" | - | 하위 컨트롤 라벨 세로 정렬 |
align | "start" | "center" | "end" | - | 하위 컨트롤 본문 정렬 |
required | boolean | - | 하위 컨트롤 필수 표시(*) |
requiredPosition | "left" | "right" | - | 필수 표시 위치 |
requiredOffsetX | number | - | 필수 표시 가로 오프셋 (px) |
requiredOffsetY | number | - | 필수 표시 세로 오프셋 (px) |
className | string | - | <form> className. 마운트를 유지하며 숨기려면 hidden |
style | React.CSSProperties | - | 인라인 스타일. 격자 스타일 뒤에 합쳐집니다 |
| (그 밖) | foundation FormProps | - | role·id·aria-label·noValidate 등 표준 form 속성 |
컨트롤에 같은 라벨 설정 prop을 주면 컨트롤 값이 이깁니다. 안쪽 Form은 바깥 Form의 설정을 병합하지 않고 통째로 바꿉니다.
Form.Col
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | 칸 안에 둘 내용 |
span | number | 24 | 차지할 칸 수 (0 이상). 0이면 자리를 차지하지 않습니다 (DOM 유지) |
offset | number | 0 | 줄의 몇 번째 칸 뒤에서 시작할지 (줄 기준 절대 위치) |
className | string | - | 칸 className. 마운트를 유지하며 숨기려면 hidden |
Events
| Event | Type | Description |
|---|---|---|
onSubmit | (event: FormEvent<HTMLFormElement>) => void | 제출 시 호출. action이 없으면 기본 동작(페이지 이동)을 막은 뒤 호출 |
Ref
ref는 <form> 요소(HTMLFormElement)로 연결됩니다.
접근성
권장 사항
- ✅ 네이티브
<form>요소를 씁니다 - ✅
aria-label로 폼 식별자 제공 가능 - ✅ 제출은 제출 버튼(
type="submit")으로 하며, Enter 제출도 같은 버튼으로 동작
관련 컴포넌트
- FormItem:
labelprop이 없는 내용에 라벨을 붙이는 래퍼 - ToolbarForm: 제목·도구 모음이 있는 접이식 폼