Dialog
A modal dialog that interrupts the user with important content and expects a response.
Installation
Add the component to your project:
rails generate shadcn:component dialog
Usage
<%= render Shadcn::DialogComponent.new do |dialog| %>
<% dialog.with_trigger do %>
<%= render Shadcn::ButtonComponent.new(variant: :outline) do %>Open Dialog<% end %>
<% end %>
<% dialog.with_body do |content| %>
<% content.with_header do |header| %>
<% header.with_title { "Dialog Title" } %>
<% header.with_description { "Dialog description here." } %>
<% end %>
<p>Dialog body content goes here.</p>
<% content.with_footer do %>
<%= render Shadcn::ButtonComponent.new { "Save" } %>
<% end %>
<% end %>
<% end %>
Examples
Basic Dialog
<%= render Shadcn::DialogComponent.new do |dialog| %>
<% dialog.with_trigger do %>
<%= render Shadcn::ButtonComponent.new(variant: :outline) do %>Open<% end %>
<% end %>
<% dialog.with_body do |content| %>
<% content.with_header do |header| %>
<% header.with_title { "Are you sure?" } %>
<% header.with_description { "This action cannot be undone." } %>
<% end %>
<% content.with_footer do %>
<div class="flex gap-2 justify-end">
<%= render Shadcn::ButtonComponent.new(variant: :outline, data: { action: "click->shadcn--dialog#close" }) { "Cancel" } %>
<%= render Shadcn::ButtonComponent.new(variant: :destructive) { "Delete" } %>
</div>
<% end %>
<% end %>
<% end %>
Custom Close Button
Use data-action="click->shadcn--dialog#close" on any element to close the dialog.
<%= render Shadcn::ButtonComponent.new(
variant: :ghost,
size: :icon,
data: { action: "click->shadcn--dialog#close" }
) do %>
<svg>X</svg>
<% end %>
With Form
API Reference
DialogComponent
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| id |
String
|
nil
|
Unique identifier for the dialog (useful for Turbo Stream targeting) |
| open |
Boolean
|
false
|
Whether the dialog starts in open state |
| modal |
Boolean
|
true
|
Whether dialog is modal (traps focus, blocks background interaction) |
Slots
| Slot | Description |
|---|---|
| with_trigger | The element that opens the dialog (usually a button) |
| with_body | The dialog content container (yields DialogContentComponent) |
DialogContentComponent Slots
| Slot | Description |
|---|---|
| with_header | Header section (yields with_title and with_description slots) |
| with_title | Dialog title text |
| with_description | Dialog description text |
| with_footer | Footer section (usually contains action buttons) |
| with_close_button | Custom close button element |
Stimulus Controller
This component requires JavaScript. The Stimulus controller shadcn--dialog provides interactivity.
Manages dialog open/close state, focus trapping, keyboard navigation, and accessibility.
Installation
Add to your config/importmap.rb:
pin "shadcn-rails", to: "shadcn/index.js"
Then in your app/javascript/controllers/index.js:
import { Application } from "@hotwired/stimulus"
import { registerShadcnControllers } from "shadcn-rails"
const application = Application.start()
registerShadcnControllers(application)
Install the package:
npm install shadcn-rails
Then in your app/javascript/controllers/index.js:
import { Application } from "@hotwired/stimulus"
import { registerShadcnControllers } from "shadcn-rails"
const application = Application.start()
registerShadcnControllers(application)
Install the package:
yarn add shadcn-rails
Then in your app/javascript/controllers/index.js:
import { Application } from "@hotwired/stimulus"
import { registerShadcnControllers } from "shadcn-rails"
const application = Application.start()
registerShadcnControllers(application)
Install the package:
npm install shadcn-rails
Then in your app/javascript/controllers/index.js:
import { Application } from "@hotwired/stimulus"
import { registerShadcnControllers } from "shadcn-rails"
const application = Application.start()
registerShadcnControllers(application)
Or import just this controller:
import DialogController from "shadcn-rails/controllers/dialog_controller"
application.register("shadcn--dialog", DialogController)
Targets
| Name | Description |
|---|---|
| trigger | The element that triggers the dialog to open |
| template | Template containing the dialog content (for portal rendering) |
| overlay | The backdrop overlay element |
| content | The dialog content container |
Values
| Name | Type | Default | Description |
|---|---|---|---|
| open | Boolean |
false |
Current open/closed state |
| modal | Boolean |
true |
Whether dialog is modal |
Actions
| Action | Description |
|---|---|
| open | Opens the dialog |
| close | Closes the dialog |
TypeScript
Type definitions are included. Import types as needed:
import type { DialogController } from "shadcn-rails"
Accessibility
- Uses
role="dialog"for proper screen reader announcement - Sets
aria-modal="true"when modal is enabled - Traps focus within the dialog when open
- Pressing Escape closes the dialog
- Returns focus to trigger element when closed
- Links title and description via
aria-labelledbyandaria-describedby
On This Page