Dialog
Native <dialog>s sharing one panel: a titled header with a close button, the body, and an optional footer. Load one from the server into the shared modal, or put one on the page.
Loaded into the shared modal
Clear the name and save to see a 422 keep the dialog open. A good save closes it in the same render as the morph refresh. Slow shows the skeleton; Forbidden shows the error panel.
This example talks to a server
These are static pages, so what this example saves, posts or searches for won't answer here. Run the browser
(
bin/dev) or mount it in an app to try it for real.
- Name
- Ada Lovelace
- Role
- Engineer
<%= detail_list do |list| %>
<% list.item "Name", @profile.name %>
<% list.item "Role", @profile.role %>
<% end %>
<div class="mt-4 flex flex-wrap gap-2">
<%= modal_link_to "Edit profile", profile_dialog_path, class: button_classes(:primary) %>
<%= modal_link_to "Slow (skeleton)", slow_dialog_path, class: button_classes %>
<%= modal_link_to "Forbidden (error)", forbidden_dialog_path, class: button_classes %>
</div>Already on the page
dialog_tag and dialog_button open a dialog with no request.
<%= dialog_button "What's a scope?", dialog: "scopes_help", class: button_classes %>
<%= dialog_tag "scopes_help", title: "Scopes" do |dialog| %>
<p>A scope limits what a token can do. Grant the fewest that get the job done.</p>
<% dialog.footer do %>
<%= tag.button "Got it", type: "button", class: button_classes(:primary), data: { unmagic_dialog_close: "" } %>
<% end %>
<% end %>A drawer along the edge
side: :end (or :start) opens the panel as a drawer the full height of the screen, its body scrolling and its footer pinned. On a phone every dialog is a sheet from the bottom.
<div class="flex flex-wrap items-center gap-2">
<%= dialog_button "Filters", dialog: "job_filters", class: button_classes %>
<%= dialog_button "Details (start)", dialog: "job_details", class: button_classes %>
</div>
<%= dialog_tag "job_filters", title: "Filters", side: :end do |dialog| %>
<%= form_with url: "#", method: :get, builder: Unmagic::Components::FormBuilder do |form| %>
<%= form.field :q, "Search", as: :search_field %>
<%= form.field :status, "Status" do %>
<%= form.select :status, %w[Open Closed Any], {}, class: control_classes(:select) %>
<% end %>
<%= form.switch_field :mine, "Only mine" %>
<% dialog.footer { form.submit "Apply" } %>
<% end %>
<% end %>
<%= dialog_tag "job_details", title: "Render #4821", side: :start, size: :wide do |dialog| %>
<%= detail_list variant: :stacked do |list| %>
<% list.item "Scene", "kitchen.modelscene.json" %>
<% list.item "Kiln", "saberpc" %>
<% list.item "Started", local_time_tag(@now, format: :relative) %>
<% list.item "Samples", "256" %>
<% end %>
<% dialog.footer { button "Cancel render", :danger } %>
<% end %>