Modal

현재 작업에 집중하도록 별도의 대화상자를 표시합니다.

Live preview
컴포넌트를 조작하면 여기에 결과가 표시됩니다.
코드 보기
HTML
<sy-modal
  closable
  oktext="확인"
  canceltext="취소"
  width="300"
  variant="dialog"
  animation="none"
  id="sample"
><span slot="header">프로젝트 설정</span>
  <p slot="body">설정 내용을 확인한 뒤 진행하세요. 예제 밖의 데이터에는 영향을 주지 않습니다.</p>
</sy-modal>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">대화상자 열기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

사용 가이드

#

현재 작업을 잠시 멈추고 확인이나 제한된 입력을 완료해야 할 때 사용합니다. 짧은 확인은 Popconfirm, 병행 작업은 Modeless가 알맞습니다.

  1. 결정에 필요한 내용 구성

    header·body·footer 슬롯을 나누고 okText·cancelText로 동작을 구체적으로 표현하세요. hideFooter로 기본 하단을 숨길 수 있습니다.

  2. 대화상자 열고 닫기

    setOpen()으로 열고 setOk()·setCancel()·setClose()로 종료할 수 있습니다.

  3. 종료 이유에 맞춰 처리

    closed.detail.event의 ok·cancel·close와 value를 읽으세요.

예제

#

확인 대화상자

확인·취소 결과를 구분합니다.

코드 보기
HTML
<sy-modal
  closable
  oktext="확인"
  canceltext="취소"
  width="300"
  id="sample"
><span slot="header">프로젝트 설정</span>
  <p slot="body">설정 내용을 확인한 뒤 진행하세요. 예제 밖의 데이터에는 영향을 주지 않습니다.</p>
</sy-modal>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">대화상자 열기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

닫기 정책

닫기 버튼과 배경 클릭으로 종료하도록 설정합니다.

코드 보기
HTML
<sy-modal
  closable
  oktext="확인"
  canceltext="취소"
  width="300"
  maskclosable
  id="sample"
><span slot="header">프로젝트 설정</span>
  <p slot="body">설정 내용을 확인한 뒤 진행하세요. 예제 밖의 데이터에는 영향을 주지 않습니다.</p>
</sy-modal>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">대화상자 열기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

최대화

내용을 크게 볼 수 있도록 최대화 버튼을 허용합니다.

코드 보기
HTML
<sy-modal
  closable
  oktext="확인"
  canceltext="취소"
  width="300"
  enablemodalmaximize
  id="sample"
><span slot="header">프로젝트 설정</span>
  <p slot="body">설정 내용을 확인한 뒤 진행하세요. 예제 밖의 데이터에는 영향을 주지 않습니다.</p>
</sy-modal>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">대화상자 열기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

결과 전달

프로그램에서 확인 결과를 전달하며 닫을 수 있습니다.

코드 보기
HTML
<sy-modal
  closable
  width="300"
  hidefooter
  id="sample"
><span slot="header">결과 전달</span>
  <div slot="body">
    <p>버튼을 누르면 예제 결과를 전달합니다.</p>
    <sy-button id="confirm-modal">선택 완료</sy-button>
  </div>
</sy-modal>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">대화상자 열기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  await ((root) => {
    const modal = root.querySelector('#sample');
    modal.querySelector('#confirm-modal').addEventListener('click', () => modal.setOk({
      selected: 'design'
    }));
  })(document);
</script>

전환 효과

대화상자 등장·퇴장에 효과를 적용합니다.

코드 보기
HTML
<sy-modal
  closable
  oktext="확인"
  canceltext="취소"
  width="300"
  animation="fade-scale"
  id="sample"
><span slot="header">프로젝트 설정</span>
  <p slot="body">설정 내용을 확인한 뒤 진행하세요. 예제 밖의 데이터에는 영향을 주지 않습니다.</p>
</sy-modal>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">대화상자 열기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

이벤트와 전달 값

컴포넌트를 조작하고 최근 이벤트의 이름과 detail 값을 확인하세요. 코드에는 이 컴포넌트와 하위 구성 요소가 보내는 이벤트의 구독 방법이 모두 포함되어 있습니다.

코드 보기
HTML
<sy-modal
  closable
  oktext="확인"
  canceltext="취소"
  width="300"
  variant="dialog"
  animation="none"
  id="sample"
><span slot="header">프로젝트 설정</span>
  <p slot="body">설정 내용을 확인한 뒤 진행하세요. 예제 밖의 데이터에는 영향을 주지 않습니다.</p>
</sy-modal>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">대화상자 열기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>
<output id="demo-events" aria-live="polite">컴포넌트를 조작하면 최근 이벤트와 전달 값이 표시됩니다.
</output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  for (const name of ["closed"]) {
    document.addEventListener(name, event => {
      document.querySelector('#demo-events').textContent =
        `${event.target.localName} · ${name}: ${describeResult(event.detail)}`;
    });
  }
</script>

대화상자 높이

height로 대화상자 높이를 지정합니다. 내용이 길면 본문에서 스크롤할 수 있도록 여유 공간을 확보하세요.

코드 보기
HTML
<sy-modal
  closable
  oktext="확인"
  canceltext="취소"
  width="300"
  variant="dialog"
  animation="none"
  height="320"
  id="sample"
><span slot="header">프로젝트 설정</span>
  <p slot="body">설정 내용을 확인한 뒤 진행하세요. 예제 밖의 데이터에는 영향을 주지 않습니다.</p>
</sy-modal>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">대화상자 열기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "height": 320
  });
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

본문 중심 대화상자

푸터 버튼을 숨기고 헤더의 닫기 버튼을 유지합니다.

코드 보기
HTML
<sy-modal
  closable
  oktext="확인"
  canceltext="취소"
  width="420"
  variant="dialog"
  hidefooter
  animation="none"
  id="sample"
><span slot="header">프로젝트 설정</span>
  <p slot="body">설정 내용을 확인한 뒤 진행하세요. 예제 밖의 데이터에는 영향을 주지 않습니다.</p>
</sy-modal>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">대화상자 열기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "hideFooter": true,
    "closable": true,
    "width": 420
  });
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

API reference

#

이름에 마우스를 올리거나 키보드로 선택하면 적용 코드를 확인할 수 있습니다. 터치 화면에서는 이름을 누르세요.

<sy-modal>

Properties

Attribute / PropertyTypeDefaultDescription
string''취소 버튼 문구입니다.
booleanfalse닫기 버튼을 표시합니다.
booleanfalse대화상자 최대화 동작을 허용합니다.
booleanfalse기본 하단 동작 영역을 숨깁니다.
booleanfalse배경 클릭으로 닫습니다.
booleanfalse배경 마스크를 생략합니다.
string''확인 버튼 문구입니다.
booleanfalse하위 메뉴가 펼쳐진 상태입니다.
number0대화상자 너비(px)입니다. 0은 기본 크기입니다.
number0대화상자 높이(px)입니다. 0은 내용에 맞춥니다.
string'-1'화면 위쪽 위치입니다. -1은 자동 가운데 정렬입니다.
string'-1'화면 왼쪽 위치입니다. -1은 자동 가운데 정렬입니다.
'modal' | 'dialog''dialog'modal 또는 dialog 스타일입니다.
| 'none' | 'fade' | 'fade-scale' | 'zoom' | 'pop' | 'slide-top' | 'slide-bottom' | 'slide-left' | 'slide-right' | 'slide-fade-top' | 'slide-fade-bottom' | 'slide-fade-left' | 'slide-fade-right' | 'reveal-top' | 'reveal-bottom' | 'reveal-left' | 'reveal-right' | 'flip-x' | 'flip-y' | 'bounce' | 'spin''none'Enter/exit animation type. `none` (default) toggles instantly. Direction-aware values are explicit (`slide-top`, `slide-fade-left`, `reveal-bottom`, …) because the modal has no `position` attribute to derive direction from. Direction-less values (`fade`, `pop`, `flip-*`, `bounce`, `spin`) play the same regardless of orientation.
'x-fast' | 'fast' | 'medium' | 'slow' | 'x-slow''fast'Animation playback speed token. Maps to `--transition-*` global tokens.

Events

EventDetailDescription
CustomEvent<{ event: 'ok' | 'cancel' | 'close'; value: any; maximized: boolean; position: { top: string; left: string }; }>Fires when the modal closes. `detail.event` distinguishes ok / cancel / close.

Methods

MethodReturnsDescription
Promise<void>하위 메뉴를 펼칩니다.
Promise<void>항목을 닫습니다.
Promise<void>취소 결과와 함께 대화상자를 닫습니다.
Promise<void>확인 결과와 함께 대화상자를 닫습니다.
Promise<void>창을 최대화합니다.

Slots

SlotDescription
header 영역에 표시할 내용입니다.
body 영역에 표시할 내용입니다.
footer 영역에 표시할 내용입니다.