Basic Modal
Basic modal dialog.
Code
<%= render(Hakumi::Button::Component.new(type: :primary, data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "basic-modal"
})) { "Open Modal" } %>
<%= render Hakumi::Modal::Component.new(
id: "basic-modal",
title: "Basic Modal",
open: false
) do %>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
<% end %>
Modal with Custom Footer
Modal with custom footer.
Code
<%= render(Hakumi::Button::Component.new(type: :primary, data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "custom-footer-modal"
})) { "Open Modal with Custom Footer" } %>
<% custom_footer = capture do %>
<%= render(Hakumi::Button::Component.new(data: { "hakumi-modal-close": true })) { "Return" } %>
<%= render(Hakumi::Button::Component.new(type: :primary, loading: true, data: { "hakumi-modal-ok": true })) { "Submit" } %>
<% end %>
<%= render Hakumi::Modal::Component.new(
id: "custom-footer-modal",
title: "Modal with Custom Footer",
open: false,
footer: custom_footer
) do %>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
<% end %>
Loading Status
Modal with loading status.
Code
<%= render(Hakumi::Button::Component.new(type: :primary, data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "loading-modal"
})) { "Open Modal with Loading" } %>
<%= render Hakumi::Modal::Component.new(
id: "loading-modal",
title: "Basic Modal",
open: false,
confirm_loading: true
) do %>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
<% end %>
Async Logic
Modal with async logic.
Code
<%= render(Hakumi::Button::Component.new(type: :primary, data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "async-modal"
})) { "Open Modal with Async Logic" } %>
<%= render Hakumi::Modal::Component.new(
id: "async-modal",
title: "Async Modal",
open: false,
confirm_loading: false
) do %>
<p>The modal will be closed after two seconds</p>
<% end %>
Modal Cannot be Closed by Backdrop
Modal with mask_closable set to false prevents closing by clicking the backdrop.
Code
<%= render(Hakumi::Button::Component.new(type: :primary, data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "mask-closable-modal"
})) { "Open Modal (Cannot close with backdrop)" } %>
<%= render Hakumi::Modal::Component.new(
id: "mask-closable-modal",
title: "Modal with mask_closable: false",
open: false,
mask_closable: false
) do %>
<p>This modal cannot be closed by clicking on the backdrop.</p>
<p>You must use the X button or the Cancel/OK buttons to close it.</p>
<% end %>
Confirmation Modal
Different types of confirmation modals with appropriate icons and styling.
Code
<%= render Hakumi::Space::Component.new(size: :small, wrap: true) do %>
<%= render(Hakumi::Button::Component.new(data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "confirm-modal"
})) { "Confirm" } %>
<%= render Hakumi::Modal::Confirm::Component.new(
id: "confirm-modal",
title: "Confirm",
message: "Do you want to delete these items?",
open: false
) %>
<%= render(Hakumi::Button::Component.new(data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "info-modal"
})) { "Info" } %>
<%= render Hakumi::Modal::Info::Component.new(
id: "info-modal",
title: "Info",
message: "This is an informational message.",
open: false
) %>
<%= render(Hakumi::Button::Component.new(data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "success-modal"
})) { "Success" } %>
<%= render Hakumi::Modal::Success::Component.new(
id: "success-modal",
title: "Success",
message: "The operation completed successfully!",
open: false
) %>
<%= render(Hakumi::Button::Component.new(data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "error-modal"
})) { "Error" } %>
<%= render Hakumi::Modal::Error::Component.new(
id: "error-modal",
title: "Error",
message: "An error occurred while processing your request.",
open: false
) %>
<%= render(Hakumi::Button::Component.new(data: {
controller: "hakumi--modal-trigger",
hakumi__modal_trigger_modal_id_value: "warning-modal"
})) { "Warning" } %>
<%= render Hakumi::Modal::Warning::Component.new(
id: "warning-modal",
title: "Warning",
message: "This action cannot be undone.",
open: false
) %>
<% end %>
Programmatic Modal
Render a modal via the component API endpoint and inject it into the page.
Code
<div class="hakumi-space hakumi-space-horizontal" style="gap: 12px;">
<%= render(Hakumi::Button::Component.new(type: :primary, id: "programmatic-modal-btn")) { "Render Modal via API" } %>
<div id="programmatic-modal-target"></div>
</div>
<script>
(() => {
const button = document.getElementById("programmatic-modal-btn")
if (!button) return
const wire = () => {
if (!window.HakumiComponents?.renderComponent) return false
button.addEventListener("click", async () => {
const result = await window.HakumiComponents.renderComponent("modal", {
params: { title: "Programmatic Modal", message: "Loaded from /hakumi/components/modal", open: true },
target: "#programmatic-modal-target",
mode: "destroy_on_close"
})
result?.element?.hakumiComponent.api?.open()
})
return true
}
if (wire()) return
const onReady = () => {
if (wire()) {
document.removeEventListener("turbo:load", onReady)
window.removeEventListener("load", onReady)
}
}
document.addEventListener("turbo:load", onReady)
window.addEventListener("load", onReady)
})()
</script>
Modal API
| Prop | Type | Default | Description |
|---|---|---|---|
open |
Boolean |
false |
Controls visibility. |
title |
String or ViewComponent |
- |
Modal header title. |
width |
Integer |
520 |
Modal width in pixels. |
centered |
Boolean |
false |
Vertically center modal. |
footer |
Boolean or ViewComponent |
nil |
Custom footer content; set to false to hide. |
closable |
Boolean |
true |
Show close button. |
mask |
Boolean |
true |
Render backdrop. |
mask_closable |
Boolean |
true |
Allow closing by clicking mask. |
keyboard |
Boolean |
true |
Close on ESC key. |
on_ok |
Proc |
- |
Callback invoked on primary button. |
on_cancel |
Proc |
- |
Callback invoked on cancel button or close action. |
confirm_loading |
Boolean |
false |
Loading state for primary button. |
ok_text |
String |
"OK" |
Primary button label. |
cancel_text |
String |
"Cancel" |
Cancel button label. |
ok_button_props |
Hash |
{} |
Props for the primary button. Supports Button props like size:, type:, disabled:, icon:, etc. |
cancel_button_props |
Hash |
{} |
Props for the cancel button. Supports Button props like size:, type:, disabled:, icon:, etc. |
content slot |
Slot |
- |
Modal body content. |
**html_attributes |
Keyword args |
- |
Attributes merged into the root `.hakumi-modal-root` (pass as kwargs such as `class:`, `style:`). |