@olundot/ui · Surfaces
FormModal
짧은 입력 작업을 현재 화면 위에서 완료하도록 묶는 폼 전용 모달 조합입니다.
- 폼 submit
- children을 form body에 넣고 onSubmit으로 저장 흐름을 처리합니다.
- wide
- 필드가 많거나 본문 폭이 필요한 경우 720px 폭으로 확장합니다.
- status
- 자동 저장 아님, 검토 중 같은 보조 상태를 header 아래에 표시합니다.
- loading
- 저장 중에는 submit과 cancel 동작을 잠그는 데 사용합니다.
기본 폼
제목, 설명, 필드, 저장 footer코드 보기tsx
import { useState } from "react";
import { FormModal, Input, Textarea, Button } from "@olundot/ui";
export function FormModalBasic() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="primary" onClick={() => setOpen(true)}>
메모 작성
</Button>
<FormModal
open={open}
onOpenChange={setOpen}
title="학습 메모 작성"
description="문항 검토에 필요한 짧은 메모를 남깁니다."
submitLabel="저장"
onSubmit={async () => {
await new Promise((resolve) => setTimeout(resolve, 800));
}}
>
<Input surface="canvas" label="제목" name="title" placeholder="예: 감별진단 확인" />
<Textarea surface="canvas" label="내용" name="body" placeholder="메모 내용을 입력하세요." rows={4} />
</FormModal>
</>
);
}상태 메시지
status 영역과 비동기 저장코드 보기tsx
import { useState } from "react";
import { FormModal, Input, Badge, Button } from "@olundot/ui";
export function FormModalStatus() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>
그룹 이름 변경
</Button>
<FormModal
open={open}
onOpenChange={setOpen}
title="그룹 이름 변경"
description="학생에게 보이는 그룹 이름을 수정합니다."
status={<Badge tone="info">자동 저장 아님</Badge>}
submitLabel="변경 저장"
onSubmit={async () => {
await new Promise((resolve) => setTimeout(resolve, 900));
}}
>
<Input surface="canvas" label="그룹 이름" name="name" defaultValue="심장학 보충반" />
</FormModal>
</>
);
}넓은 폼
wide 레이아웃과 복수 필드코드 보기tsx
import { useState } from "react";
import { FormModal, Input, Textarea, Button } from "@olundot/ui";
export function FormModalWide() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>
공지 작성
</Button>
<FormModal
open={open}
onOpenChange={setOpen}
title="수업 공지 작성"
description="목록과 상세 화면에 함께 노출되는 공지를 작성합니다."
wide
submitLabel="공지 저장"
onSubmit={async () => {
await new Promise((resolve) => setTimeout(resolve, 800));
}}
>
<Input surface="canvas" label="공지 제목" name="notice-title" />
<Textarea surface="canvas" label="공지 본문" name="notice-body" rows={6} />
</FormModal>
</>
);
}