# Dialog A modal pop-up window that appears on top of the page. Think of it like a small piece of paper sliding onto the desk — the rest of the page dims and you have to deal with the dialog before you can go back to work. Opening and closing is handled entirely with `data-dialog-open` and `data-dialog-close` HTML attributes — no custom JavaScript needed. --- ## Quick example ```csharp new Dialog( id: "about-dialog", title: "About this app", content: "

Version 1.0 — built with .NET 10.

", footer: """""") ``` Then somewhere on the page, add a trigger: ```html ``` That's it. No JavaScript needed in your templates. --- ## All the options ```csharp public Dialog( string id, string content, string title = "", string description = "", string footer = "") ``` | Parameter | What it does | |---|---| | `id` | A unique identifier. Used both on the `` element and in `data-dialog-open`. | | `content` | The body of the dialog. Raw HTML. | | `title` | Optional bold heading at the top of the dialog panel. | | `description` | Optional smaller text below the title. | | `footer` | Optional button row at the bottom. Raw HTML. | The title, description, and footer sections are omitted entirely from the HTML when not provided. --- ## Real-world examples ### Confirmation before a destructive action Place the dialog in the page template, then trigger it from a button: ```html $$DeleteDialog$$ ``` ```csharp // Templates/ItemsPage.htmx.cs _deleteDialog = new Dialog( id: "confirm-delete", title: "Delete item", content: "

This action cannot be undone.

", footer: """ """); ``` ### Dialog that loads content on demand Use HTMX's `revealed` trigger to load the dialog body only when it opens: ```csharp new Dialog( id: "user-detail", title: "User details", content: """
""") ``` ### Closing from outside the dialog Any element anywhere on the page can close a dialog by setting `data-dialog-close`: ```html ``` --- ## How it works Dialog uses the native HTML `` element with `showModal()`. A backdrop (the dark overlay) comes from the browser's built-in `::backdrop` pseudo-element, styled in `input.css`. JavaScript in `components.js` listens for clicks anywhere on the page. If the clicked element has `data-dialog-open`, it calls `showModal()` on the matching dialog. If it has `data-dialog-close`, it calls `close()`. Clicking outside the dialog panel (on the backdrop) also closes it. Because the listener is on `document`, dialogs that are HTMX-swapped in work automatically without any re-initialisation. All `content` and `footer` strings are raw HTML — HTML-encode any user-supplied values before passing them in. --- ## Complete page example **`Templates/ItemsPage.htmx`** ```html

Items

$$ItemsTable$$ $$DeleteDialog$$
``` **`Templates/ItemsPage.htmx.cs`** ```csharp namespace Htmx.ApiDemo.Templates; public sealed class ItemsPage : ItemsPageBase { private readonly IHtmxComponent _table; private readonly IHtmxComponent _deleteDialog; public ItemsPage(IEnumerable items, string? deleteTargetId = null) { // Build table with a per-row Delete button that opens the dialog _table = new Components.Table( headers: new[] { "Name", "Created", "Actions" }, rows: items.Select(item => new[] { System.Net.WebUtility.HtmlEncode(item.Name), item.CreatedAt.ToShortDateString(), $"""""", })); _deleteDialog = new Components.Dialog( id: "confirm-delete", title: "Delete item", content: """

This action cannot be undone.

""", footer: """ """); } protected override void RenderItemsTable(HtmxRenderContext ctx) => _table.Render(ctx.Next()); protected override void RenderDeleteDialog(HtmxRenderContext ctx) => _deleteDialog.Render(ctx.Next()); } ``` **GET + DELETE handlers** ```csharp [Handler] [MapGet("/items")] public static partial class GetItemsHandler { public record Query(); private static Task HandleAsync( Query _, HttpContext ctx, CancellationToken ct) { var items = new[] { new Item("1", "Widget A", DateTime.Today.AddDays(-10)), new Item("2", "Widget B", DateTime.Today.AddDays(-5)), }; return ctx.WriteHtmxPage(new ItemsPage(items), title: "Items"); } } [Handler] [MapDelete("/items")] public static partial class DeleteItemHandler { public record Command([property: FromForm] string ItemId); private static IResult HandleAsync([AsParameters] Command cmd, CancellationToken ct) { // Delete item from database… return Results.Ok(); // HTMX swaps the row out with outerHTML } } public record Item(string Id, string Name, DateTime CreatedAt); ```