Modal · Docs

스토리북 개발자들을 위한 내부 문서

Components

Modal

Docs

API 사용가이드입니다. 변형·색상·props 프리뷰는 Overview를 참고하세요.

API

Modal · ModalTrigger · ModalContent · ModalTitle · ModalDescription · ModalFooter · ModalClose 합성 API로 사용합니다. 포커스 트랩·ESC 닫기·ARIA 연결은 내부에서 자동 처리됩니다. 오버레이 클릭으로는 닫히지 않습니다.

import {
  Modal,
  ModalTrigger,
  ModalContent,
  ModalTitle,
  ModalDescription,
  ModalFooter,
  ModalClose,
} from "@/components/modal";
import Button from "@/components/button";

<Modal>
  <ModalTrigger asChild>
    <Button variant="secondary">게시글 삭제</Button>
  </ModalTrigger>
  <ModalContent>
    <ModalTitle>게시글을 삭제할까요?</ModalTitle>
    <ModalDescription>삭제한 게시글은 복구할 수 없습니다.</ModalDescription>
    <ModalFooter actions="confirm">
      <ModalClose asChild>
        <Button variant="tertiary">취소</Button>
      </ModalClose>
      <Button onClick={handleDelete}>삭제</Button>
    </ModalFooter>
  </ModalContent>
</Modal>

{/* CTA 색 커스텀 — Button className (hover·active 포함) */}
<ModalFooter actions="confirm">
  <ModalClose asChild>
    <Button variant="tertiary">취소</Button>
  </ModalClose>
  <Button
    className="bg-emerald-500 text-white hover:bg-emerald-600 active:bg-emerald-700"
  >
    확인
  </Button>
</ModalFooter>

{/* 커스텀 크기 셸 — Tailwind className */}
<ModalContent className="max-h-[80vh] w-[min(calc(100vw-2rem),32rem)]">
  …
</ModalContent>

Props

NameTypeDefaultDescription
Modal.open / defaultOpen
boolean열림 상태. open + onOpenChange로 제어하거나 defaultOpen으로 비제어로 사용합니다.
ModalTrigger
asChild?: boolean클릭 시 모달을 엽니다. asChild로 Button 등 커스텀 트리거에 연결합니다.
ModalContent.className
string크기·스타일. 미전달 시 w-[min(calc(100vw-2rem),400px)] max-h-[400px]. w/h/max-*를 넣으면 기본 박스를 대체합니다.
ModalFooter.actionsRequired
"single" | "dual" | "confirm"버튼 구성·균등 폭 레이아웃 프리셋. 색은 강제하지 않습니다. CTA는 Button 기본(primary), 커스텀은 각 Button className으로 전달합니다.
ModalTitle / ModalDescription
React.ReactNode제목·설명. 제목을 시각적으로 숨기려면 ModalTitle에 className="sr-only"를 전달합니다(접근성 유지).
ModalClose
asChild?: boolean클릭 시 모달을 닫습니다. 취소·닫기 버튼에 연결합니다.

Events

NameSignatureDescription
Modal.onOpenChange(open: boolean) => void열림 상태 변경 시 호출됩니다. ESC·ModalClose로 닫힐 때 전달됩니다. 오버레이 클릭으로는 닫히지 않습니다.

Notes

  • 소비 앱 필수: React 19, Tailwind CSS v4, ClaBi tokens.css(+ @theme 매핑), clsx, @radix-ui/react-dialog.
  • clsx 패키지가 필수입니다. className 병합에 import { clsx } from "clsx" 를 사용합니다.
  • 내부적으로 @radix-ui/react-dialog를 사용합니다. 소비 앱에도 해당 패키지가 필요합니다.
  • Footer CTA 기본색은 Button variant(미지정 시 primary)입니다. bg-·hover:bg-·active:bg-·text-* className을 넣으면 variant 색 대신 해당 클래스가 적용됩니다.
  • 확인형 모달이므로 오버레이(외부) 클릭으로는 닫히지 않습니다. Footer 버튼 또는 ESC로 닫습니다.
  • 별도의 제목을 전달하지 않을 경우, 제목 없이 설명 텍스트만 표시됩니다(ModalTitle sr-only 권장).
  • 최대 크기는 className으로 전달합니다. 미전달 시 400×400(뷰포트 여백 포함). 예: className="w-[min(calc(100vw-2rem),32rem)] max-h-[80vh]".
  • 설명 텍스트가 길면 ModalDescription이 스크롤됩니다. 더 큰 콘텐츠·커스텀 팝업도 ModalContent 껍데기 + className으로 구성합니다.