MeDo

AI 모달 생성기.

필요한 다이얼로그를 설명하면 MeDo가 전체를 생성합니다 — 헤더, 스크롤 가능한 본문, 액션 푸터에 더해 포커스 트랩, 닫을 때 포커스 복원, body 스크롤 락, 모바일 바텀 시트 변형까지.

모달
모달

모달의 어려운 부분은 그 뒤에 있는 페이지입니다

모달은 그림자가 있는 중앙 정렬된 상자처럼 보입니다. 그래서 그렇게 자주 엉성하게 다시 만들어집니다. 시각적 레이어는 사소하고, 어려운 부분은 전부 컴포넌트 밖에 있습니다. 다이얼로그를 열면 아래 문서를 고정하고, Tab이 숨겨진 콘텐츠로 흘러가지 않도록 키보드 포커스를 붙잡고, 페이지의 나머지를 보조 기술로부터 숨기고, 마지막에는 그것을 열었던 정확한 요소로 포커스를 되돌려야 합니다. 이 마지막 단계를 놓치면 키보드 사용자는 아무 안내도 없이 문서 맨 위로 돌아가 자신이 어디에 있는지 알 수 없게 됩니다. 다이얼로그와 그 포커스 계약을 함께 생성하면, 이 상태 기계는 QA 이후에 덧붙이는 것이 아니라 첫 렌더링부터 올바르게 동작합니다.

템플릿 6개

생성할 수 있는 모달 템플릿

모든 템플릿은 스크린샷이 아니라 실제 프롬프트입니다. 어떤 AI 에디터에든 붙여넣거나 MeDo에서 실행해 React + Tailwind 코드를 그대로 받으세요.

BasicHeader + Footer

Composable Dialog With Focus Management

The base every other dialog extends. The visual layer takes minutes; the focus contract is the part worth generating rather than hand-writing.

Create a modal dialog with three sizes — sm 400px, md 560px, lg 760px — centered over a black backdrop at 50 percent opacity, 16px radius, soft shadow. Compose it from Header, Body and Footer slots: the header holds a title and an icon-only close button with an aria-label, the body scrolls independently at max-height 70vh, and the footer right-aligns Cancel next to a primary action. On open, move focus to the first interactive element, trap Tab and Shift+Tab inside the dialog, and lock body scroll by compensating for the scrollbar width so the page does not shift. Set role="dialog", aria-modal="true" and aria-labelledby pointing at the title, and restore focus to the trigger on close.

MeDo에서 시도하기
ConfirmationDestructive Confirm

Non-Dismissible Delete Dialog

The one dialog that must ignore Escape and backdrop clicks. A stray click outside the box should never be the gesture that deletes an account.

Create a destructive confirmation dialog: a warning icon, a heading naming the exact resource, a body stating what will be lost and whether it is recoverable, and a footer with Cancel on the left and a red Confirm on the right. Ignore both Escape and backdrop clicks so the action requires a deliberate button press. Move initial focus to Cancel rather than Confirm, so a stray Enter keypress cancels instead of destroying. Use role="alertdialog" with aria-describedby on the body text. Add an optional type-to-confirm mode requiring the resource name to be typed before Confirm enables, with the comparison case-sensitive and trimmed.

MeDo에서 시도하기
FormForm Dialog

Scrolling Form With Sticky Actions

A long form in a dialog needs a body that scrolls under a fixed header and footer, plus an unsaved-changes guard. Losing typed input to a misclick is unforgivable.

Create a form dialog with a fixed header, a scrolling body and a sticky footer holding Cancel and Save. Keep the header and footer outside the scroll container so the actions stay reachable in a long form. Add a dirty-state guard: when any field has changed, intercept Escape and backdrop clicks and show a nested confirm-discard step inside the same dialog rather than opening a second overlay. On validation failure, move focus to the first invalid field and scroll it into view inside the body. Set aria-busy while saving, disable Save without removing it from the tab order, and close only after the request resolves.

MeDo에서 시도하기
MobileBottom Sheet

Sheet That Slides Up on Phones

A centered card on a phone leaves the buttons floating mid-screen, away from the thumb. Same component, different layout under 640px.

Create a dialog that renders as a centered card above 640px and as a bottom sheet below it: full width, rounded top corners only, sliding up from the bottom edge with a 250ms ease-out transform. Add a drag handle at the top and support swipe-to-dismiss with a velocity threshold, falling back to the close button for keyboard and assistive technology. Cap the sheet height at 90vh with the body scrolling inside, and use dynamic viewport units so the mobile browser chrome does not clip the footer. Keep focus trapping and scroll lock identical in both layouts, and disable the slide animation under prefers-reduced-motion.

MeDo에서 시도하기
PlatformNative Dialog

HTML dialog With showModal

The browser already ships focus trapping, top-layer stacking and Escape handling. Choose this and you delete most of the code the custom overlay needed.

Create a modal built on the native HTML dialog element opened with showModal(), so the browser supplies focus trapping, Escape handling and top-layer stacking with no z-index management. Style the backdrop through the ::backdrop pseudo-element. Add the parts the platform does not give you: body scroll lock on open, an entry and exit animation using allow-discrete and the transition-behavior property, and a close-on-backdrop handler that compares the click target to the dialog element rather than its children. Listen for the close event to restore focus and read returnValue, and use autofocus on the element that should receive focus first.

MeDo에서 시도하기
OverlayCommand Palette

Cmd+K Search Dialog

A modal whose focus stays in the input while arrow keys drive a list elsewhere. Roving focus would break typing, so this one runs on aria-activedescendant.

Create a command palette dialog opened by Cmd+K or Ctrl+K: a search input at the top with results grouped by section below, positioned near the top of the viewport rather than vertically centered. Keep DOM focus in the input at all times and move the visual selection with aria-activedescendant so arrow keys navigate the list without stealing focus from typing. Support Enter to run the highlighted command, Escape to close with focus restored to the previously active element, and a scroll-into-view on the highlighted row. Debounce the query, render an empty state naming what was searched for, and announce the result count through a polite live region.

MeDo에서 시도하기

모달 커스터마이즈 방법

닫을 수 없어야 하는 다이얼로그를 명시하세요

Escape와 백드롭 클릭은 정보성 다이얼로그에 알맞은 기본값이지만, 파괴적인 확인이나 저장하지 않은 입력이 있는 다단계 폼에서는 위험합니다. 둘 다 무시해야 하는 변형을 지정해서, 상자 밖의 실수 클릭으로 계정이 삭제되지 않게 하세요.

포커스 트랩뿐 아니라 포커스 복원도 요청하세요

대부분의 프롬프트는 트랩만 얻고 돌아오는 길을 잊습니다. 닫을 때 포커스가 트리거 요소로 돌아가고, 열 때 다이얼로그가 그 참조를 저장하도록 지정하면 키보드 사용자는 멈춘 지점에서 정확히 이어갈 수 있습니다.

브레이크포인트마다 중앙 정렬과 바텀 시트를 선택하세요

휴대폰에서 중앙 정렬 다이얼로그는 액션 버튼을 화면 중간에 띄워 엄지에서 멀어지게 만듭니다. 640px 미만에서는 주요 액션이 손에 닿는 바텀 시트를 요청하고, 더 넓은 뷰포트에서는 중앙 정렬 레이아웃을 유지하세요.

모달 안에서 모달을 열지 마세요

첫 번째 다이얼로그 위에 두 번째를 쌓으면 포커스 트랩이 깨지고 백드롭이 두 겹이 되며 Escape가 어느 레이어를 닫는지 모호해집니다. 대신 하나의 다이얼로그 안에서 단계별 콘텐츠를 요청해, 오버레이가 포커스 소유자가 하나뿐인 단일 레이어로 유지되게 하세요.

모달 컴포넌트를 사용하는 사람

SaaS 제품

구독 취소를 위한 닫을 수 없는 확인 다이얼로그로, 본문에 플랜 이름을 다시 표시하고 빨간 확인 버튼을 둡니다. 여기에 팀원 초대를 위한 더 가볍고 닫을 수 있는 다이얼로그를 함께 씁니다.

이커머스 스토어

상품 이미지, 사이즈 선택기, 장바구니 추가 버튼을 담은 퀵뷰 다이얼로그. 휴대폰에서는 바텀 시트로 렌더링해 사이즈 옵션과 장바구니 버튼이 모두 엄지 범위에 들어옵니다.

대시보드 또는 관리 도구

정확한 레코드 개수를 명시하고 확인 버튼이 활성화되기 전에 리소스 이름 입력을 요구하는 대량 삭제 확인. 여기에 고정 헤더와 푸터 사이에서 긴 폼이 스크롤되는 편집 다이얼로그를 함께 둡니다.

콘텐츠 또는 미디어 사이트

전체 크기 이미지를 위한 라이트박스 다이얼로그. 방향키 내비게이션, Escape로 닫기, 그리고 그것을 열었던 썸네일로 포커스가 돌아가므로 갤러리에서 보던 위치를 잃지 않습니다.

웹사이트 유형별 모달 패턴

같은 모달 컴포넌트를 게시되는 사이트 유형에 맞춰 조정합니다.

01 / 06

SaaS Product Dialogs

Two classes of dialog with opposite dismissal rules: invite-a-teammate should close on Escape and backdrop click, cancel-my-subscription should close on neither. Decide that per variant rather than globally, because a single dismissal policy across a product means either annoying dialogs or destroyed data.

모달 스타일과 변형

페이지의 나머지 부분과 어울리는 변형을 골라 바로 생성하세요.

01 / 06

Centered Dialog

The default above 640px: a fixed-width card centered over a dimmed backdrop. Cap the height at around 70vh with the body scrolling internally, because a dialog taller than the viewport pushes its own footer out of reach and there is no page scroll left to recover it.

React, Next.js, Vue, Svelte에서의 모달

React, Next.js, Vue 3, SvelteKit, Astro 또는 순수 HTML — 같은 모달을 여섯 가지 방식으로 넣을 수 있습니다.

01 / 06

React Modal

Render through a portal so the dialog escapes any ancestor with overflow hidden or a transform, both of which would clip it. Store the trigger element on open and focus it again in the cleanup, which is the step most hand-rolled modals skip.

src/components/Modal.tsx

export function Modal({ open, onClose, children }) {
  const trigger = useRef(null)

  useEffect(() => {
    if (!open) return
    trigger.current = document.activeElement
    return () => trigger.current?.focus()
  }, [open])

  if (!open) return null
  return createPortal(
    <div role="dialog" aria-modal="true">{children}</div>,
    document.body
  )
}

모달을 프로젝트에 추가하는 방법

모달 템플릿을 고르고 프로덕션에 배포하기까지 네 단계.

01~30s

Pick a Dialog Template

Scan the six templates and start from the interaction — a destructive confirm, a scrolling form, a mobile bottom sheet, or a Cmd+K palette.

02~10s

Copy the Prompt

Take the prompt into MeDo, Lovable, Bolt, v0 or Cursor. State whether this dialog may be dismissed by Escape and backdrop click before you run it, since that single decision separates a helpful overlay from one that deletes data on a misclick.

03~1min

Generate and Refine

You get React + Tailwind back with a live preview. Follow up in plain English — "make it a bottom sheet under 640px", "focus Cancel first", "build it on the native dialog element" — rather than rewiring the focus trap yourself.

04~2min

Test It With the Keyboard Only

Open it, Tab to the end and confirm focus cycles instead of escaping into the page, then close it and check focus returned to the trigger. Those two checks catch nearly every modal defect that ships.

모달에 대한 자주 묻는 질문

AI로 모달 컴포넌트를 생성하는 방법은?

레이아웃, 크기, 닫기 규칙을 하나의 프롬프트로 설명하세요 — 예를 들어 "스크롤 가능한 본문, 취소와 확인 액션, Escape를 무시하는 파괴적 변형을 갖춘 560px 중앙 정렬 다이얼로그"처럼요. MeDo는 포커스 트랩, 포커스 복원, 스크롤 락, 다이얼로그 시맨틱을 포함해 컴포넌트를 생성하므로 스타일만 입힌 div가 아니라 실제로 동작하는 오버레이를 얻습니다.

포커스 트랩이란 무엇이며 모달에 왜 필요한가요?

포커스 트랩은 Tab과 Shift+Tab이 아래 페이지로 빠져나가지 않고 다이얼로그 내부의 인터랙티브 요소를 순환하게 유지합니다. 이것이 없으면 키보드 사용자는 확인 버튼을 지나 보이지 않는 링크로 이동하게 되어 혼란스럽고 WCAG 위반이기도 합니다. 트랩은 항상 포커스 복원과 함께 써서, 다이얼로그가 닫힐 때 트리거 요소로 포커스를 되돌려야 합니다.

백드롭을 클릭하면 모달이 닫혀야 하나요?

정보성이고 위험이 낮은 다이얼로그라면 네 — 백드롭 클릭과 Escape는 사람들이 기대하는 닫기 패턴입니다. 파괴적인 확인이나 저장하지 않은 입력이 있는 폼이라면 아니요. 상자 밖의 우연한 클릭으로 데이터가 삭제되거나 입력이 버려져서는 안 됩니다. 되돌릴 수 없는 동작에는 명시적인 버튼 클릭을 요구하세요.

커스텀 모달 대신 네이티브 HTML <dialog> 요소를 사용할 수 있나요?

대개 가능합니다. showModal()과 함께 쓰는 네이티브 <dialog> 요소는 포커스 트랩, Escape 처리, 최상위 레이어 스태킹, ::backdrop 의사 요소를 무료로 제공하며 z-index 관리도 필요 없습니다. 다만 body 스크롤 락과 애니메이션은 직접 구현해야 하고, 구형 브라우저에는 폴백이 필요합니다. 네이티브 요소를 원한다고 MeDo에 말하면 동작을 다시 구현하지 않고 그 위에 구축합니다.

모바일에서 모달은 어떻게 동작해야 하나요?

대략 640px 미만에서는 보통 바텀 시트가 중앙 정렬 카드보다 낫습니다. 주요 액션을 엄지 근처에 고정하고, 폼 필드에 전체 너비를 쓰며, 사용자가 이미 아는 플랫폼 관례에 맞습니다. MeDo는 두 레이아웃을 하나의 컴포넌트에서 생성하고 지정한 브레이크포인트에서 전환할 수 있습니다.

모달에 role="dialog"와 aria-modal이 필요한가요?

네. 시맨틱을 스스로 제공하는 네이티브 <dialog> 요소를 쓰는 경우가 아니라면 필요합니다. 커스텀 오버레이에는 role="dialog", aria-modal="true", 그리고 보이는 제목을 가리키는 aria-labelledby 또는 보이는 제목이 없을 때의 aria-label이 필요합니다. aria-modal이 없으면 스크린 리더는 오버레이 뒤의 페이지를 계속 탐색 가능한 콘텐츠로 노출합니다.