DocsComponentsDialog
Dialog
A modal window, opened by its trigger or by name.
Alpine.jsdepends on button6 files
<pb-ui.dialog name="delete">
<pb-slot:trigger><pb-ui.button variant="outline">Delete account</pb-ui.button></pb-slot:trigger>
<pb-ui.dialog-header>
<pb-ui.dialog-title>Are you sure?</pb-ui.dialog-title>
<pb-ui.dialog-description>This action cannot be undone. Your account and your data will be deleted.</pb-ui.dialog-description>
</pb-ui.dialog-header>
<pb-ui.dialog-footer>
<pb-ui.dialog-close><pb-ui.button variant="outline">Cancel</pb-ui.button></pb-ui.dialog-close>
<pb-ui.button variant="destructive">Delete</pb-ui.button>
</pb-ui.dialog-footer>
</pb-ui.dialog>Installation
pyblade-ui add dialog- Install the dependencies
button and Alpine.js, loaded in your
<head>. - Copy these files into your projectcomponents/ui/dialog.html
@props({'name': '', 'trigger': '', 'open': False}) <div data-slot="dialog" x-data="{ open: {{ str(bool(open)).lower() }} }" x-on:keydown.escape.window="open = false" x-on:dialog-open.window="$event.detail === '{{ name }}' && (open = true)" x-on:dialog-close.window="$event.detail === '{{ name }}' && (open = false)" x-effect="document.body.classList.toggle('overflow-hidden', open)" class="contents"> <span data-slot="dialog-trigger" class="contents" x-on:click="open = true">{{ trigger }}</span> <div x-show="open" x-cloak class="fixed inset-0 z-50 flex items-center justify-center p-4"> <div data-slot="dialog-overlay" x-show="open" x-transition.opacity class="fixed inset-0 bg-black/50" x-on:click="open = false"></div> <div role="dialog" aria-modal="true" data-slot="dialog-content" x-show="open" x-transition:enter="duration-200 ease-out" x-transition:enter-start="scale-95 opacity-0" x-transition:enter-end="scale-100 opacity-100" x-transition:leave="duration-150 ease-in" x-transition:leave-start="scale-100 opacity-100" x-transition:leave-end="scale-95 opacity-0" {{ attributes.cn("relative z-50 grid w-full max-w-[calc(100%-2rem)] gap-4 rounded-lg border bg-background p-6 shadow-lg sm:max-w-lg") }}> {{ slot }} <button type="button" x-on:click="open = false" class="absolute top-4 right-4 cursor-pointer rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden [&_svg]:size-4"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg> <span class="sr-only">Close</span> </button> </div> </div> </div>components/ui/dialog_header.html<div data-slot="dialog-header" {{ attributes.cn("flex flex-col gap-2 text-center sm:text-left") }}>{{ slot }}</div>components/ui/dialog_title.html<h2 data-slot="dialog-title" {{ attributes.cn("text-lg leading-none font-semibold") }}>{{ slot }}</h2>components/ui/dialog_description.html<p data-slot="dialog-description" {{ attributes.cn("text-sm text-muted-foreground") }}>{{ slot }}</p>components/ui/dialog_footer.html<div data-slot="dialog-footer" {{ attributes.cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end") }}>{{ slot }}</div>components/ui/dialog_close.html<span data-slot="dialog-close" x-on:click="open = false" {{ attributes.cn("contents") }}>{{ slot }}</span> - Update the path to fit your project
The
componentsfolder is the one set inpyblade.toml.
Usage
The tags <pb-ui.dialog> <pb-ui.dialog-header> <pb-ui.dialog-title> <pb-ui.dialog-description> <pb-ui.dialog-footer> <pb-ui.dialog-close> are available in all your templates.
<pb-ui.dialog name="delete">
<pb-slot:trigger><pb-ui.button variant="destructive">Delete</pb-ui.button></pb-slot:trigger>
<pb-ui.dialog-header>
<pb-ui.dialog-title>Are you sure?</pb-ui.dialog-title>
<pb-ui.dialog-description>This cannot be undone.</pb-ui.dialog-description>
</pb-ui.dialog-header>
<pb-ui.dialog-footer>
<pb-ui.dialog-close><pb-ui.button variant="outline">Cancel</pb-ui.button></pb-ui.dialog-close>
</pb-ui.dialog-footer>
</pb-ui.dialog>
{# Or from anywhere: $dispatch('dialog-open', 'delete') #}Examples
Opened by name
<pb-ui.button variant="secondary" x-data x-on:click="$dispatch('dialog-open', 'welcome')">Open from anywhere</pb-ui.button>
<pb-ui.dialog name="welcome">
<pb-ui.dialog-header>
<pb-ui.dialog-title>Welcome</pb-ui.dialog-title>
<pb-ui.dialog-description>This dialog was opened with $dispatch('dialog-open', 'welcome').</pb-ui.dialog-description>
</pb-ui.dialog-header>
</pb-ui.dialog>Props
| Prop | Default |
|---|---|
| name | '' |
| trigger | '' |
| open | False |
Any other attribute (class, id, x-on:click, hx-post…) is passed to the root element; your Tailwind classes win over the component's.