Modal

Modal component for dialog overlays and popups.

Usage

# <% Async modal (loads content via Turbo Frame) %>
<%= ui.btn "Open Modal", url: some_path, data: { turbo_frame: :modal } %>

# <% Sync modal (content already on page) %>
<%= ui.btn "Open Modal", data: { action: "click->modals#show", id: "myModal" } %>
<%= ui.modal(title: "Title", id: "myModal") do %>
  <%= ui.modal_body do %>
    Content here
  <% end %>
<% end %>
Props
PropTypeDefaultDescription
titleStringnilModal title displayed in the header.
subtitleStringnilModal subtitle displayed below the title.
sizeString
"sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "6xl"
"2xl"Width of the modal dialog.
idStringnilUnique identifier for sync modals. Required for modals triggered by `modals#show` action.

Also accepts any HTML attributes via **options (e.g., id:, data:, aria:). class: is also supported for custom styling.

SubcomponentsUse subcomponents below or any HTML.
NameHelperDescription
modal_headerui.modal_headerHeader section with title, subtitle, and close button. Automatically rendered when title/subtitle props are provided.
modal_bodyui.modal_bodyScrollable content area of the modal.
modal_footerui.modal_footerFooter section typically containing action buttons.

Examples

Async Modal

<%= ui.btn "Async Modal", url: privacy_path, data: { turbo_frame: :modal } %>

Sync Modal

Dialog content

<%= ui.btn "Open Modal", data: { action: "click->modals#show", id: "dialog1" } %>

<%= ui.modal(title: "Modal Title", subtitle: "Modal Subtitle", id: "dialog1") do %>
  <p class="p-4">Dialog content</p>
<% end %>

Multiple Modals

Dialog content

Dialog content 2

<div class="flex gap-2">
  <%= ui.btn "One modal", data: { action: "click->modals#show", id: "dialog1" } %>
  <%= ui.btn "Another modal", variant: :secondary, data: { action: "click->modals#show", id: "dialog2" } %>
</div>

<%= ui.modal(title: "One Modal Title", subtitle: "Modal Subtitle", id: "dialog1") do %>
  <p class="p-4">Dialog content</p>
<% end %>

<%= ui.modal(title: "Another Modal Title", subtitle: "Another Subtitle", id: "dialog2") do %>
  <p class="p-4">Dialog content 2</p>
<% end %>