4.1 KiB
4.1 KiB
입력 위젯 가이드
Superport v2의 폼 UI는 shadcn_ui 구성 요소를 기반으로 하며, 아래 지침을 따를 때 레이아웃과 상호작용이 일관되게 유지된다.
1. 기본 컨테이너 — SuperportFormField
- 라벨/필수 표시/보조 설명/에러 메시지를 하나의 빌딩 블록으로 묶는다.
- 라벨은 좌측 정렬, 12pt, 필수 항목은
*(파괴색)으로 표시한다. - 자식 위젯은
ShadInput,ShadSelect,SuperportDatePickerButton등 어떤 입력 요소든 가능하다. - 에러 문구는 상단 Validator에서 내려오는 한글 메시지를 그대로 사용한다.
SuperportFormField(
label: '창고',
required: true,
caption: '입고가 진행될 창고를 선택하세요.',
errorText: state.errorMessage,
child: ShadSelect<String>(
initialValue: controller.selectedWarehouse,
options: warehouses.map((w) => ShadOption(value: w.id, child: Text(w.name))).toList(),
onChanged: controller.onWarehouseChanged,
),
);
2. 텍스트 입력 — SuperportTextInput
ShadInput에 공통 프리셋을 적용한 래퍼.- 플레이스홀더는 한글 문장형으로 작성하고, 검색 필드라면 돋보기 아이콘을
leading으로 배치한다. - 여러 줄 입력은
maxLines변경만으로 처리한다.
SuperportFormField(
label: '비고',
child: SuperportTextInput(
controller: remarkController,
placeholder: const Text('추가 설명을 입력하세요.'),
maxLines: 3,
),
);
3. 선택 컴포넌트 — ShadSelect
- 단일 선택은
ShadSelect<T>를 그대로 사용하고,SuperportFormField로 라벨만 감싼다. - 다중 선택이 필요한 경우
ShadSelect.multiple과 토큰(UiChip) 스타일을 조합한다. - 최초 옵션은
전체/선택하세요처럼 명확한 기본값을 제공한다.
SuperportFormField(
label: '상태',
required: true,
child: ShadSelect<OrderStatus?>(
initialValue: controller.pendingStatus,
selectedOptionBuilder: (_, value) => Text(value?.label ?? '전체 상태'),
options: [
const ShadOption(value: null, child: Text('전체 상태')),
for (final status in OrderStatus.values)
ShadOption(value: status, child: Text(status.label)),
],
onChanged: controller.onStatusChanged,
),
);
4. 토글 — SuperportSwitchField
- 스위치 단독 사용 시 라벨·캡션 레이아웃을 제공한다.
- 접근성 관점에서 토글 설명은 문장형으로 작성한다.
SuperportSwitchField(
label: '파트너사 전용',
value: controller.isPartnerOnly,
onChanged: controller.onPartnerOnlyChanged,
caption: '활성화 시 파트너사만 접근할 수 있습니다.',
);
5. 날짜/기간 — SuperportDatePickerButton
- 단일 날짜는
SuperportDatePickerButton, 기간은SuperportDateRangePickerButton을 사용한다. - 포맷은 기본적으로
yyyy-MM-dd, 필요 시dateFormat으로 주입. - 기간 선택은
firstDate/lastDate범위를 명시해 엣지 케이스를 제한한다.
SuperportFormField(
label: '처리 기간',
child: SuperportDateRangePickerButton(
value: controller.pendingRange,
onChanged: controller.onRangeChanged,
firstDate: DateTime(2020),
lastDate: DateTime(2030),
),
);
6. 검증 메시지
- Validator는 필수 오류 → 형식 오류 → 업무 규칙 순서로 확인하고, 메시지는
SuperportFormField.errorText로 전달한다. - 포커스 이동 시 즉시 에러를 표시하며, 성공 시
caption으로 가이드를 남겨 재입력을 돕는다.
7. 레이아웃
- 가로 240px/500px 프리셋은
SizedBox로 감싸 사용하며, 반응형 환경에서는ResponsiveLayoutSlot(섹션 13 참조)을 이용한다. - 두 줄 이상 배치 시
Wrap+spacing:16/runSpacing:16을 기본으로 한다.
8. 샘플 코드 경로
lib/widgets/components/form_field.dartlib/features/inventory/inbound/presentation/pages/inbound_page.dart— 입고 등록 모달
위 가이드를 준수하면 폼 간 스타일과 상호작용 규칙을 동일하게 유지할 수 있다.