Files
komp_ac/web/templates/ui/dialog.html
2026-08-15 12:44:36 +02:00

53 lines
4.0 KiB
HTML

{#
Blocking failure modal — Penguin UI's danger modal, taken from
penguinui-components/modal/modal-alerts.html.
Same deal as ui/alert.html: the component's copy lives in its markup, so this
is the library file's danger variant with its text nodes replaced and nothing
else changed. Two structural edits, both because the server, not a click,
decides when this appears:
- the library's trigger button is dropped, and `dangerModalIsOpen` starts
`true`. The server only sends the dialog when there is something the user
has to be told, so the response itself is the trigger.
- the footer button dismisses instead of acting ("Back to the form"): a
failure has nothing to confirm.
It is Tailwind + Alpine markup; x-trap needs the focus plugin, which
ui/base.html loads before Alpine itself.
{% import "ui/dialog.html" as dialog %}
{% call dialog::error("Could not add the column", message) %}{% endcall %}
#}
{% macro error(locale, title, message) %}
<div x-data="{ dangerModalIsOpen: true }">
<div x-cloak x-show="dangerModalIsOpen" x-transition.opacity.duration.200ms x-trap.inert.noscroll="dangerModalIsOpen" x-on:keydown.esc.window="dangerModalIsOpen = false" x-on:click.self="dangerModalIsOpen = false" class="fixed inset-0 z-30 flex items-end justify-center bg-black/20 p-4 pb-8 backdrop-blur-md sm:items-center lg:p-8" role="dialog" aria-modal="true" aria-labelledby="dangerModalTitle">
<!-- Modal Dialog -->
<div x-show="dangerModalIsOpen" x-transition:enter="transition ease-out duration-200 delay-100 motion-reduce:transition-opacity" x-transition:enter-start="opacity-0 scale-50" x-transition:enter-end="opacity-100 scale-100" class="flex max-w-lg flex-col gap-4 overflow-hidden rounded-radius border border-outline bg-surface text-on-surface dark:border-outline-dark dark:bg-surface-dark-alt dark:text-on-surface-dark">
<!-- Dialog Header -->
<div class="flex items-center justify-between border-b border-outline bg-surface-alt/60 px-4 py-2 dark:border-outline-dark dark:bg-surface-dark/20">
<div class="flex items-center justify-center rounded-full bg-danger/20 text-danger p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-6" aria-hidden="true">
<path fill-rule="evenodd" d="M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM8.28 7.22a.75.75 0 0 0-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 1 0 1.06 1.06L10 11.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L11.06 10l1.72-1.72a.75.75 0 0 0-1.06-1.06L10 8.94 8.28 7.22Z" clip-rule="evenodd" />
</svg>
</div>
<button x-on:click="dangerModalIsOpen = false" aria-label="{{ locale.lookup("ui-close-dialog") }}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" stroke="currentColor" fill="none" stroke-width="1.4" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<!-- Dialog Body -->
<div class="px-4 text-center">
<h3 id="dangerModalTitle" class="mb-2 font-semibold tracking-wide text-on-surface-strong dark:text-on-surface-dark-strong">{{ title }}</h3>
<p class="whitespace-pre-wrap">{{ message }}</p>
</div>
<!-- Dialog Footer -->
<div class="flex items-center justify-center border-outline p-4 dark:border-outline-dark">
<button x-on:click="dangerModalIsOpen = false" type="button" class="w-full whitespace-nowrap rounded-radius border border-danger bg-danger px-4 py-2 text-center text-sm font-semibold tracking-wide text-on-danger transition hover:opacity-75 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-danger active:opacity-100 active:outline-offset-0">{{ locale.lookup("ui-back-to-form") }}</button>
</div>
</div>
</div>
</div>
{% endmacro %}