Discourse 3.1.0.beta6에는 완전히 새로운 <DModal> 컴포넌트 기반 API가 포함되어 있습니다. DModal은 UI 키트의 일부이며 discourse/ui-kit/d-modal에서 가져옵니다.
이는 이제 비추천(deprecated)된 기존 컨트롤러 기반 API를 대체합니다. 기존 API를 사용하는 모달이 있는 경우, 마이그레이션 가이드를 여기에서 확인하세요.
모달 렌더링
모달은 Handlebars 템플릿에 <DModal> 컴포넌트를 포함하여 렌더링됩니다. 이미 적합한 템플릿이 없다면 https://meta.discourse.org/t/using-plugin-outlet-connectors-from-a-theme-or-plugin/32727을 확인하세요.
간단한 모달은 다음과 같은 형태를 가질 수 있습니다:
<DButton
@translatedLabel="Show Modal"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<DModal @title="My Modal" @closeModal={{fn (mut this.modalIsVisible) false}}>
Hello world, this is some content in a modal
</DModal>
{{/if}}
여기서는
mut헬퍼가 hbs 전용 방식으로 값을 설정하는 데 사용됩니다.modalIsVisible을 다른 표준 Ember 메서드를 사용하여 설정할 수도 있습니다.
이 예제는 다음과 같은 간단한 모달을 생성합니다:
컴포넌트로 래핑하기
더 많은 복잡성을 도입하기 전에, 새로운 모달을 자체 컴포넌트 정의에 래핑하는 것이 일반적으로 가장 좋습니다. <DModal> 관련 코드를 새로운 <MyModal /> 컴포넌트 안으로 이동해 보겠습니다.
// components/my-modal.gjs
<template>
<DModal @title="My Modal" @closeModal={{@closeModal}}>
Hello world, this is some content in a modal
</DModal>
</template>
이 .gjs 파일을 클래스 기반 컴포넌트로 업그레이드하면 더 복잡한 로직과 상태를 도입할 수 있습니다.
새로운 컴포넌트를 활용하려면 호출 지점을 업데이트하여 해당 컴포넌트를 참조하고 @closeModal 인자를 전달하도록 하세요.
<DButton
@translatedLabel="Show Modal"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}
푸터 추가하기
많은 모달에는某种의 행동 유도(call-to-action)가 있습니다. Discourse에서는 이러한 요소들이 모달 하단에 위치하는 경향이 있습니다. 이를 가능하게 하기 위해 DModal에는 내부에 콘텐츠가 렌더링될 수 있는 여러 '이름 지정 블록(named blocks)'이 있습니다. 여기서는 푸터에 두 개의 버튼(그중 하나는 표준 DModalCancel 버튼)을 포함하도록 업데이트된 예제입니다.
<DModal @title="My Modal" @closeModal={{@closeModal}}>
<:body>
Hello world, this is some content in a modal
</:body>
<:footer>
<DButton class="btn-primary" @translatedLabel="Submit" />
<DModalCancel @close={{@closeModal}} />
</:footer>
</DModal>
hbs가 아닌 컨텍스트에서 모달 렌더링
이상적으로는 위에서 시연한 선언적 기법을 사용하여 Ember 템플릿 내에서 <DModal> 인스턴스를 렌더링해야 합니다. 사용 사례에서 이것이 불가능한 경우, modal 서비스를 주입하고 modal.show()를 호출하여 수행할 수 있습니다.
위에서 설명한 대로 모달을 자체 컴포넌트로 래핑했는지 확인하세요. 그런 다음 showModal에 컴포넌트 클래스의 참조를 전달하여 모달을 트리거합니다:
import MyModal from "discourse/components/my-modal";
// (관련 위치에 modal 서비스를 주입)
// 모달을 열 때마다 이 호출을 추가하세요.
// `@closeModal` 인자가 컴포넌트에 자동으로 전달됩니다.
this.modal.show(MyModal);
// 선택적으로 '`model`' 매개변수를 전달합니다. `@model`로 컴포넌트에 전달됩니다.
// 여기에는 데이터와 모달이 사용할 동작/콜백을 포함할 수 있습니다.
this.modal.show(MyModal, {
model: { topic: this.topic, someAction: this.someAction },
});
// `modal.show()`는 Promise를 반환하므로, 닫힐 때까지 기다릴 수 있습니다.
// `@closeModal` 동작에 전달된 데이터로 resolve됩니다.
const result = await this.modal.show(MyModal);
더 많은 커스터마이징!
<DModal>에는 여러 이름 지정 블록과 인자가 있습니다.
인자(Arguments)
| Arg | Purpose |
|---|---|
@closeModal |
닫기 UI가 표시되려면 필수입니다. |
@title |
<h1 id="discourse-modal-title">을 렌더링하고 aria-labelledby를 연결합니다. |
@subtitle |
제목 아래에 표시되는 작은 텍스트입니다. |
@flash / @flashType |
모달 상단의 인라인 알림(DFlashMessage)입니다. |
@hideHeader, @hideFooter |
전체 영역을 숨깁니다. |
@headerClass, @bodyClass |
헤더/바디 래퍼에 추가할 클래스입니다. |
@dismissable |
@closeModal이 설정되어 있으면 기본적으로 true입니다. Esc / 배경 클릭 / X를 비활성화합니다. |
@autofocus |
기본적으로 true입니다. dTrapTab을 통해 첫 번째 포커스 가능한 요소에 자동으로 포커스를 맞춥니다. |
@submitOnEnter |
기본적으로 true입니다. 포커스가 폼 / textarea / select-kit에 있지 않으면 Enter 키가 .d-modal__footer .btn-primary을 클릭합니다. |
@beforeClose |
async ({ initiatedBy }) => boolean. false를 반환하면 닫기 동작을 취소합니다(예: 수정된 폼 확인). |
@hidden |
키보드 처리를 일시 중지합니다. 중첩된 모달이 위에 있을 때 사용됩니다. |
@tagName |
"div"(기본값) 또는 "form". 네이티브 제출(submit)이 작동하도록 폼에는 "form"을 사용하세요. |
블록(Blocks)
| Block | Position | When to use |
|---|---|---|
default / :body |
Main content area | 기본 영역 |
:aboveHeader |
Very top, before header | 거의 필요하지 않습니다; 제목 바 위에 있어야 하는 콘텐츠(예: 배너)에 사용됩니다. |
:headerAboveTitle |
Inside header, before title | 존재하지만 미사용입니다. 거의 필요하지 않습니다. |
:belowModalTitle |
Inside .d-modal__title, after the <h1> |
보조 메타 정보를 위한 훌륭한 위치입니다. |
:headerBelowTitle |
Inside header, after title block | 헤더의 일부인 탭, 서브 내비게이션 또는 검색 입력 필드에 사용됩니다. |
:headerPrimaryAction |
Right side of header on mobile only | X 닫기 버튼을 기본 동작(예: “저장”)으로 대체합니다. 또한 왼쪽에 “취소” 버튼을 자동으로 렌더링하고 헤더에 .--has-primary-action을 추가합니다. |
:belowHeader |
Between header and body | 스크롤 가능한 바디 외부에 위치하여 고정(sticky) 표시되는 영구적인 서브 헤더 콘텐츠(예: 검색 바)에 사용됩니다. |
:aboveFooter |
Between body and footer | @hideFooter이 설정되면 억제됩니다. 푸터와 관련되었지만 푸터 외부에 있는 콘텐츠에 사용됩니다. 또한 드뭅니다. |
:footer |
Bottom action bar | 기본 및 보조 버튼. 여기의 첫 번째 .btn-primary은 Enter 키가 트리거하는 버튼입니다. |
:belowFooter |
After the footer | 거의 필요하지 않습니다; @hideFooter을 무시합니다. 경계가 있는 푸터 영역 외부의 상태 텍스트에 유용합니다. |
출처: 인자에 대한 인터랙티브 스타일 가이드 및 이름 지정 블록에 대한 d-modal 템플릿 구현.
CSS
.d-modal 클래스를 앵커로 사용하여 코어를 오버라이드하고 레거시 .modal 선택자를 피하세요.
사용 가능한 4개의 수정자(modifiers):
- .
--large는 최대 너비를 800px으로 설정합니다 (데스크톱 전용) - .
--max는 최대 너비를 90vw로 설정합니다 (데스크톱 전용) - .
has-search는 고정 높이(80vh)를 설정합니다: 결과 길이에 따른 높이 변화를 피하기 위해 검색/필터 시스템이 있는 모달에 intended (데스크톱 전용) .--stacked는 푸터 버튼을 스택 방식으로 설정합니다 (모바일 전용)
이 문서는 버전 관리됩니다 - 변경 사항을 github에서 제안하세요.

