Примитивы
34

Dialog

Модальный диалог: затемнение, карточка по центру, ловушка фокуса и блокировка прокрутки. Всё это уже существовало — внутри рецепта FormDialog, из-за чего рецепт был единственным способом получить модалку, и диалог, не являющийся формой, означал заново написанные ловушку, блокировку, клик по затемнению и aria. После выделения примитива от рецепта остался Dialog с формой внутри, а это пример, а не компонент. Диалог с заголовком и рядом кнопок внизу собирается из тех же трёх композиционных классов, что и карточка, — .aura-card__header, .aura-card__extra и .aura-card__footer — на ваших собственных <header> и <footer> внутри слота по умолчанию. Имена «карточные», потому что .aura-dialog носит .aura-card: второго набора учить не нужно, а отрицательный маргин, выводящий линейку к краям панели, — это и есть причина, по которой они существуют.

чистая разметка — библиотеки на странице нет
отрендерил aura-react
отрендерил aura-vue
отрендерил aura-svelte
собрано из классов самого aura-angular

Код

index.html
<div class="aura-overlay" data-state="open">
  <div class="aura-card aura-popup aura-dialog" data-state="open" role="dialog" aria-modal="true" aria-label="Delete space">
    <div class="aura-text aura-text--h3 aura-dialog__title">Delete space</div>
    <p class="aura-text aura-text--body">This cannot be undone.</p>
  </div>
</div>
Demo.tsx
import { Dialog, Typography } from '@ilomee/aura-react';

/**
 * Открыт с самого начала и не забирает фокус. Закрытый диалог не рендерит ничего, а панель каждого
 * стека обязана показать на этой странице одно и то же — пустая панель Vue рядом с живым React
 * читалась бы как отсутствие порта. `autoFocus` выключен по смежной причине: читатель этого не
 * открывал, поэтому диалог не вправе забирать фокус и утаскивать страницу из-под него. И то и
 * другое — решения про *демо*; собственный DOM компонента не тронут.
 */
export default function Demo() {
  return (
    <Dialog open autoFocus={false} onClose={() => {}} title="Delete space">
      <Typography variant="body">This cannot be undone.</Typography>
    </Dialog>
  );
}
Demo.vue
<script setup lang="ts">
import { Dialog } from '@ilomee/aura-vue';
</script>

<template>
  <Dialog :open="open" title="Delete space" @close="open = false">
    <p>This cannot be undone.</p>
  </Dialog>
</template>
Demo.svelte
<script lang="ts">
  import { Dialog } from '@ilomee/aura-svelte';
  let open = $state(true);
</script>

<Dialog {open} title="Delete space" onclose={() => (open = false)}>
  <p>This cannot be undone.</p>
</Dialog>

Используется как aura-dialog.

demo.component.ts
<aura-dialog [open]="open" title="Delete space" (closed)="open = false">
  <p auraText>This cannot be undone.</p>
</aura-dialog>

Пока нет входа top и заголовка-узла: вариант --top принадлежит рецепту палитры, а шаблонному заголовку понадобился бы id для ссылки, тогда как строковый именуется напрямую.

Пропсы

У чистой разметки нет пропсов — классы ниже и есть весь API. Четыре пакета не делают ничего сверх того, что проставляют вам те же самые классы.
ИмяТипПо умолчаниюПримечания
widthnumber | stringШирина панели: число — пиксели, строка — любая длина CSS. Задаёт --dialog-w — переменную, которую стили читали всегда и которая до сих пор была единственным способом это выразить.
openbooleanfalse
onClose*событие() => voidКлик по затемнению или Escape.
titleReactNodeРендерится заголовком и служит доступным именем, если это обычная строка.
labelstringДоступное имя, когда видимого заголовка нет или он не строка. Диалог без имени объявляется как группа без подписи.
topbooleanfalseЛожится поверх уже открытого диалога и ближе к верху экрана.
withCloseButtonbooleanfalseКрестик в углу. По умолчанию выключен: Escape и клик по затемнению уже закрывают диалог, а тот, что задаёт вопрос, должен закрываться своими кнопками.
closeLabelstring'Close'
autoFocusbooleantrueПеревести фокус внутрь при открытии и вернуть при закрытии. Выключается для диалога, отрендеренного открытым как иллюстрация: перехват фокуса вместе с прокруткой был бы засадой.
ИмяТипПо умолчаниюПримечания
widthnumber | stringШирина панели: число — пиксели, строка — любая длина CSS. Задаёт --dialog-w — переменную, которую стили читали всегда и которая до сих пор была единственным способом это выразить.
openbooleanfalse
closeсобытие() => void
titlestring | slot
labelstring
topbooleanfalse
withCloseButtonbooleanfalseКрестик в углу. По умолчанию выключен: Escape и клик по затемнению уже закрывают диалог, а тот, что задаёт вопрос, должен закрываться своими кнопками.
closeLabelstring'Close'
autoFocusbooleantrue
ИмяТипПо умолчаниюПримечания
widthnumber | stringШирина панели: число — пиксели, строка — любая длина CSS. Задаёт --dialog-w — переменную, которую стили читали всегда и которая до сих пор была единственным способом это выразить.
openbooleanfalse
onclose*событие() => void
titlestring | Snippet
labelstring
topbooleanfalse
withCloseButtonbooleanfalseКрестик в углу. По умолчанию выключен: Escape и клик по затемнению уже закрывают диалог, а тот, что задаёт вопрос, должен закрываться своими кнопками.
closeLabelstring'Close'
autoFocusbooleantrue
ИмяТипПо умолчаниюПримечания
widthnumber | stringШирина панели: число — пиксели, строка — любая длина CSS. Задаёт --dialog-w — переменную, которую стили читали всегда и которая до сих пор была единственным способом это выразить.
openbooleanfalse
closedсобытие() => void
titlestring
labelstring
topbooleanfalse
withCloseButtonbooleanfalseКрестик в углу. По умолчанию выключен: Escape и клик по затемнению уже закрывают диалог, а тот, что задаёт вопрос, должен закрываться своими кнопками.
closeLabelstring'Close'
autoFocusbooleantrue

Какие классы отдаёт

Все фреймворки отдают одни и те же классы — именно поэтому четыре библиотеки выглядят одинаково. Их можно использовать напрямую, вообще без библиотеки компонентов.

КлассРольПримечания
.aura-overlayбазаОбязательный. Без него модификатор не работает.
.aura-dialogбазаОбязательный. Без него модификатор не работает.
.aura-dialog__titleэлемент
.aura-cardбазаОбязательный. Без него модификатор не работает.
.aura-card__headerэлемент
.aura-card__extraэлемент
.aura-card__footerэлемент

Токены и правила

components.css
панель
min(var(--dialog-w, 480px), 100%) · max-block-size: 90dvh
затемнение
var(--opacity-scrim) over #000, with the safe-area insets
слой
var(--z-modal) — above a dropdown, below a palette