Components
A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
Review and accept our updated terms of service before continuing. These changes help protect you and our service.
Demo
Review and accept our updated terms of service before continuing. These changes help protect you and our service.
<div data-controller="modal">
<button type="button" data-action="click->modal#open" class="btn btn-primary" tabindex="0">
Open modal
</button>
<div
aria-labelledby="modal-title"
aria-modal="true"
data-action="keyup@window->modal#closeWithEsc"
data-modal-target="container"
class="hidden fixed inset-0 z-50 overflow-y-auto"
role="dialog"
>
<div class="h-screen w-full relative flex items-center justify-center">
<div
data-modal-target="content"
data-transition-enter-active="transition ease-out duration-300"
data-transition-enter-from="transform opacity-0 scale-95"
data-transition-enter-to="transform opacity-100 scale-100"
data-transition-leave-active="transition ease-in duration-300"
data-transition-leave-from="transform opacity-100 scale-100"
data-transition-leave-to="transform opacity-0 scale-95"
class="hidden rounded shadow-xl max-w-lg bg-white m-1 p-8 prose origin-bottom mx-auto dark:bg-slate-700 dark:text-slate-200">
<h3 id="modal-title" class="text-2xl font-extrabold text-slate-900 dark:text-slate-100 tracking-tight">Hang on one sec</h3>
<div class="prose prose-slate dark:prose-invert mt-2 mb-6">
<p>Review and accept our updated terms of service before continuing. These changes help protect you and our service.</p>
</div>
<div class="flex justify-end items-center flex-wrap gap-4">
<button class="btn btn-primary" data-action="click->railsui-modal#close">Close</button>
</div>
</div>
</div>
</div>
</div>
%div{"data-controller" => "modal"}
%button.btn.btn-primary{"data-action" => "click->modal#open", tabindex: "0", type: "button"}
Open modal
.hidden.fixed.inset-0.z-50.overflow-y-auto{"aria-labelledby" => "modal-title", "aria-modal" => "true", "data-action" => "keyup@window->modal#closeWithEsc", "data-modal-target" => "container", role: "dialog"}
.h-screen.w-full.relative.flex.items-center.justify-center
.hidden.rounded.shadow-xl.max-w-lg.bg-white.m-1.p-8.prose.origin-bottom.mx-auto.dark:bg-slate-700.dark:text-slate-200{"data-modal-target" => "content", "data-transition-enter-active" => "transition ease-out duration-300", "data-transition-enter-from" => "transform opacity-0 scale-95", "data-transition-enter-to" => "transform opacity-100 scale-100", "data-transition-leave-active" => "transition ease-in duration-300", "data-transition-leave-from" => "transform opacity-100 scale-100", "data-transition-leave-to" => "transform opacity-0 scale-95"}
%h3#modal-title.text-2xl.font-extrabold.text-slate-900.dark:text-slate-100.tracking-tight Hang on one sec
.prose.prose-slate.dark:prose-invert.mt-2.mb-6
%p Review and accept our updated terms of service before continuing. These changes help protect you and our service.
.flex.justify-end.items-center.flex-wrap.gap-4
%button.btn.btn-primary{"data-action" => "click->railsui-modal#close"} Close
import { RailsuiModal } from 'railsui-stimulus'
application.register('railsui-modal', RailsuiModal)
Are you ready to deploy your changes to production? This action cannot be undone.
Demo
Are you ready to deploy your changes to production? This action cannot be undone.
<div data-controller="railsui-modal">
<button type="button" data-action="click->railsui-modal#open" class="btn btn-primary" tabindex="0">
Open single action modal
</button>
<div
aria-labelledby="single-action-modal-title"
aria-modal="true"
data-railsui-modal-target="container"
class="hidden fixed inset-0 z-50 overflow-y-auto"
role="dialog"
>
<div class="h-screen w-full relative flex items-center justify-center">
<div
data-railsui-modal-target="content"
data-action="keyup@window->railsui-modal#closeWithEsc"
data-transition-enter-active="transition ease-out duration-300"
data-transition-enter-from="transform opacity-0 scale-95"
data-transition-enter-to="transform opacity-100 scale-100"
data-transition-leave-active="transition ease-in duration-300"
data-transition-leave-from="transform opacity-100 scale-100"
data-transition-leave-to="transform opacity-0 scale-95"
class="hidden rounded mx-auto shadow-xl max-w-xs bg-white m-1 p-8 origin-bottom text-center dark:bg-slate-700 dark:text-slate-200 text-slate-600">
<div class="flex justify-center">
<div class="w-12 h-12 rounded-full bg-emerald-50 flex items-center justify-center mb-3">
<%= icon "rocket-launch", class: "size-6 text-emerald-600 flex-shrink-0" %>
</div>
</div>
<h3 id="single-action-modal-title" class="text-2xl font-extrabold text-slate-900 dark:text-slate-100 tracking-tight">Time to launch</h3>
<div class="prose prose-slate dark:prose-invert mt-2 mb-6">
<p>Are you ready to deploy your changes to production? This action cannot be undone.</p>
</div>
<button type="button" class="btn btn-primary w-full" data-action="click->railsui-modal#close">Launch away</button>
</div>
</div>
</div>
</div>
%div{"data-controller" => "railsui-modal"}
%button.btn.btn-primary{"data-action" => "click->railsui-modal#open", tabindex: "0", type: "button"}
Open single action modal
.hidden.fixed.inset-0.z-50.overflow-y-auto{"aria-labelledby" => "single-action-modal-title", "aria-modal" => "true", "data-railsui-modal-target" => "container", role: "dialog"}
.h-screen.w-full.relative.flex.items-center.justify-center
.hidden.rounded.mx-auto.shadow-xl.max-w-xs.bg-white.m-1.p-8.origin-bottom.text-center.dark:bg-slate-700.dark:text-slate-200.text-slate-600{"data-action" => "keyup@window->railsui-modal#closeWithEsc", "data-railsui-modal-target" => "content", "data-transition-enter-active" => "transition ease-out duration-300", "data-transition-enter-from" => "transform opacity-0 scale-95", "data-transition-enter-to" => "transform opacity-100 scale-100", "data-transition-leave-active" => "transition ease-in duration-300", "data-transition-leave-from" => "transform opacity-100 scale-100", "data-transition-leave-to" => "transform opacity-0 scale-95"}
.flex.justify-center
.w-12.h-12.rounded-full.bg-emerald-50.flex.items-center.justify-center.mb-3
= icon "rocket-launch", class: "size-6 text-emerald-600 flex-shrink-0"
%h3#single-action-modal-title.text-2xl.font-extrabold.text-slate-900.dark:text-slate-100.tracking-tight Time to launch
.prose.prose-slate.dark:prose-invert.mt-2.mb-6
%p Are you ready to deploy your changes to production? This action cannot be undone.
%button.btn.btn-primary.w-full{"data-action" => "click->railsui-modal#close", type: "button"} Launch away
import { RailsuiModal } from 'railsui-stimulus'
application.register('railsui-modal', RailsuiModal)
Are you sure you want to launch this project to production? This action cannot be undone and will be visible to all users.
Demo
Are you sure you want to launch this project to production? This action cannot be undone and will be visible to all users.
<div data-controller="railsui-modal">
<button type="button" data-action="click->railsui-modal#open:prevent" class="btn btn-primary" tabindex="0">Open centered dual action modal</button>
<div
aria-labelledby="dual-action-modal-title"
aria-modal="true"
data-railsui-modal-target="container"
data-action="keyup@window->railsui-modal#closeWithEsc"
class="hidden fixed inset-0 z-50 overflow-y-auto"
role="dialog"
>
<div class="h-screen w-full relative flex items-center justify-center">
<div
data-railsui-modal-target="content"
data-transition-enter-active="transition ease-out duration-300"
data-transition-enter-from="transform opacity-0 scale-95"
data-transition-enter-to="transform opacity-100 scale-100"
data-transition-leave-active="transition ease-in duration-300"
data-transition-leave-from="transform opacity-100 scale-100"
data-transition-leave-to="transform opacity-0 scale-95"
class="hidden rounded mx-auto shadow-xl max-w-lg bg-white m-1 p-8 origin-bottom text-center dark:bg-slate-700 dark:text-slate-200">
<div class="flex justify-center">
<div class="w-12 h-12 rounded-full bg-emerald-50 flex items-center justify-center mb-3">
<%= icon "rocket-launch", class: "size-6 text-emerald-600 flex-shrink-0" %>
</div>
</div>
<h3 id="dual-action-modal-title" class="text-2xl font-extrabold text-slate-900 dark:text-slate-100 tracking-tight">Time to launch</h3>
<div class="prose prose-slate dark:prose-invert mt-2 mb-6">
<p>Are you sure you want to launch this project to production? This action cannot be undone and will be visible to all users.</p>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
<button class="btn btn-white w-full sm:order-1 order-2" data-action="click->railsui-modal#close">Cancel</button>
<button class="btn btn-primary w-full sm:order-2 order-1">Proceed to launch</button>
</div>
</div>
</div>
</div>
</div>
%div{"data-controller" => "railsui-modal"}
%button.btn.btn-primary{"data-action" => "click->railsui-modal#open:prevent", tabindex: "0", type: "button"} Open centered dual action modal
.hidden.fixed.inset-0.z-50.overflow-y-auto{"aria-labelledby" => "dual-action-modal-title", "aria-modal" => "true", "data-action" => "keyup@window->railsui-modal#closeWithEsc", "data-railsui-modal-target" => "container", role: "dialog"}
.h-screen.w-full.relative.flex.items-center.justify-center
.hidden.rounded.mx-auto.shadow-xl.max-w-lg.bg-white.m-1.p-8.origin-bottom.text-center.dark:bg-slate-700.dark:text-slate-200{"data-railsui-modal-target" => "content", "data-transition-enter-active" => "transition ease-out duration-300", "data-transition-enter-from" => "transform opacity-0 scale-95", "data-transition-enter-to" => "transform opacity-100 scale-100", "data-transition-leave-active" => "transition ease-in duration-300", "data-transition-leave-from" => "transform opacity-100 scale-100", "data-transition-leave-to" => "transform opacity-0 scale-95"}
.flex.justify-center
.w-12.h-12.rounded-full.bg-emerald-50.flex.items-center.justify-center.mb-3
= icon "rocket-launch", class: "size-6 text-emerald-600 flex-shrink-0"
%h3#dual-action-modal-title.text-2xl.font-extrabold.text-slate-900.dark:text-slate-100.tracking-tight Time to launch
.prose.prose-slate.dark:prose-invert.mt-2.mb-6
%p Are you sure you want to launch this project to production? This action cannot be undone and will be visible to all users.
.grid.grid-cols-1.sm:grid-cols-2.gap-3
%button.btn.btn-white.w-full.sm:order-1.order-2{"data-action" => "click->railsui-modal#close"} Cancel
%button.btn.btn-primary.w-full.sm:order-2.order-1 Proceed to launch
import { RailsuiModal } from 'railsui-stimulus'
application.register('railsui-modal', RailsuiModal)
Once your account is deleted it is gone for good. There is no data saved that we keep on hand. Are you sure you want to continue?
Demo
Once your account is deleted it is gone for good. There is no data saved that we keep on hand. Are you sure you want to continue?
<div data-controller="railsui-modal">
<button type="button" data-action="click->railsui-modal#open" class="btn btn-primary" tabindex="0">
Open dismissable with icon modal
</button>
<div
aria-labelledby="dismissable-action-modal-title"
aria-modal="true"
data-railsui-modal-target="container"
class="hidden fixed inset-0 z-50 overflow-y-auto"
role="dialog">
<div class="h-screen w-full relative flex items-center justify-center">
<div
data-railsui-modal-target="content"
data-action="keyup@window->railsui-modal#closeWithEsc"
data-transition-enter-active="transition ease-out duration-300"
data-transition-enter-from="transform opacity-0 scale-95"
data-transition-enter-to="transform opacity-100 scale-100"
data-transition-leave-active="transition ease-in duration-300"
data-transition-leave-from="transform opacity-100 scale-100"
data-transition-leave-to="transform opacity-0 scale-95"
class="hidden rounded mx-auto shadow-xl sm:w-full sm:max-w-lg bg-white m-1 p-6 origin-bottom md:flex items-start relative gap-4 dark:bg-slate-700 dark:text-slate-200">
<div class="flex items-start">
<button type="button" class="absolute top-2 right-2 size-8 bg-transparent hover:bg-slate-50 flex items-center justify-center rounded-full group dark:hover:bg-slate-50/50" data-action="click->railsui-modal#close">
<%= icon "x-mark", class: "text-slate-400 size-6 group-hover:text-slate-500 pointer-events-none dark:group-hover:text-slate-800 dark:text-slate-400" %>
</button>
<div class="size-8 rounded-full bg-red-50 flex items-center justify-center dark:bg-red-500/30">
<%= icon "exclamation-circle", class: "size-6 text-red-600 flex-shrink-0 dark:text-red-300" %>
</div>
<div class="flex-1">
<h3 class="text-2xl font-extrabold text-slate-900 dark:text-slate-100 tracking-tight">Delete account</h3>
<div class="prose prose-slate dark:prose-invert mb-6 mt-2 pr-6">
<p>Once your account is deleted it is gone for good. There is no data saved that we keep on hand. Are you sure you want to continue?</p>
</div>
<div class="flex justify-end items-center space-x-3">
<button class="btn btn-light" data-action="click->railsui-modal#close">Cancel</button>
<button class="btn bg-red-600 text-white focus:ring-red-100 hover:bg-red-700 hover:shadow-sm hover:shadow-slate-600/10">Delete</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
%div{"data-controller" => "railsui-modal"}
%button.btn.btn-primary{"data-action" => "click->railsui-modal#open", tabindex: "0", type: "button"}
Open dismissable with icon modal
.hidden.fixed.inset-0.z-50.overflow-y-auto{"aria-labelledby" => "dismissable-action-modal-title", "aria-modal" => "true", "data-railsui-modal-target" => "container", role: "dialog"}
.h-screen.w-full.relative.flex.items-center.justify-center
.hidden.rounded.mx-auto.shadow-xl.sm:w-full.sm:max-w-lg.bg-white.m-1.p-6.origin-bottom.md:flex.items-start.relative.gap-4.dark:bg-slate-700.dark:text-slate-200{"data-action" => "keyup@window->railsui-modal#closeWithEsc", "data-railsui-modal-target" => "content", "data-transition-enter-active" => "transition ease-out duration-300", "data-transition-enter-from" => "transform opacity-0 scale-95", "data-transition-enter-to" => "transform opacity-100 scale-100", "data-transition-leave-active" => "transition ease-in duration-300", "data-transition-leave-from" => "transform opacity-100 scale-100", "data-transition-leave-to" => "transform opacity-0 scale-95"}
.flex.items-start
%button.absolute.top-2.right-2.size-8.bg-transparent.hover:bg-slate-50.flex.items-center.justify-center.rounded-full.group{class: "dark:hover:bg-slate-50/50", "data-action" => "click->railsui-modal#close", type: "button"}
= icon "x-mark", class: "text-slate-400 size-6 group-hover:text-slate-500 pointer-events-none dark:group-hover:text-slate-800 dark:text-slate-400"
.size-8.rounded-full.bg-red-50.flex.items-center.justify-center{class: "dark:bg-red-500/30"}
= icon "exclamation-circle", class: "size-6 text-red-600 flex-shrink-0 dark:text-red-300"
.flex-1
%h3.text-2xl.font-extrabold.text-slate-900.dark:text-slate-100.tracking-tight Delete account
.prose.prose-slate.dark:prose-invert.mb-6.mt-2.pr-6
%p Once your account is deleted it is gone for good. There is no data saved that we keep on hand. Are you sure you want to continue?
.flex.justify-end.items-center.space-x-3
%button.btn.btn-light{"data-action" => "click->railsui-modal#close"} Cancel
%button.btn.bg-red-600.text-white.focus:ring-red-100.hover:bg-red-700.hover:shadow-sm{class: "hover:shadow-slate-600/10"} Delete
import { RailsuiModal } from 'railsui-stimulus'
application.register('railsui-modal', RailsuiModal)
Join our community to get early access to new features, exclusive content, and connect with other developers.
Demo
Join our community to get early access to new features, exclusive content, and connect with other developers.
<div data-controller="railsui-modal">
<button type="button" data-action="click->railsui-modal#open" class="btn btn-primary" tabindex="0">
Open modal with form
</button>
<div aria-labelledby="modal-with-form" aria-modal="true" data-railsui-modal-target="container" data-action="keyup@window->railsui-modal#closeWithEsc" class="hidden fixed inset-0 z-50 overflow-y-auto" role="dialog">
<div class="h-screen w-full relative flex items-center justify-center">
<div data-railsui-modal-target="content"
data-transition-enter-active="transition ease-out duration-300"
data-transition-enter-from="transform opacity-0 scale-95"
data-transition-enter-to="transform opacity-100 scale-100"
data-transition-leave-active="transition ease-in duration-300"
data-transition-leave-from="transform opacity-100 scale-100"
data-transition-leave-to="transform opacity-0 scale-95"
class="hidden rounded shadow-xl mx-auto max-w-lg bg-white m-1 p-8 origin-bottom relative dark:bg-slate-700 dark:text-slate-200">
<button type="button" class="absolute top-2 right-2 w-8 h-8 bg-transparent hover:bg-slate-50 flex items-center justify-center rounded-full group dark:hover:bg-slate-50/50" data-action="click->railsui-modal#close">
<%= icon "x-mark", class: "text-slate-400 size-6 group-hover:text-slate-500 pointer-events-none dark:group-hover:text-slate-800 dark:text-slate-400" %>
</button>
<h3 id="modal-with-form" class="mb-3 text-2xl font-extrabold text-slate-900 dark:text-slate-100 tracking-tight">Subscribe</h3>
<div class="prose prose-slate dark:prose-invert mt-2 mb-6">
<p>Join our community to get early access to new features, exclusive content, and connect with other developers.</p>
</div>
<form action="#">
<div class="form-group">
<label for="email_demo" class="form-label">E-mail</label>
<input id="email_demo" type="email" class="form-input" placeholder="saasquatch@railsui.com">
</div>
<div class="form-group">
<label for="reason_demo" class="form-label">Reason for joining</label>
<textarea name="reason" id="reason_demo" class="form-input" placeholder="In a couple sentences let us know your reason for joining the Rails UI community"></textarea>
</div>
</form>
<div class="mt-8 flex justify-start items-center flex-wrap bg-gray-50 px-8 py-4 -mx-8 -mb-8 border-t border-slate-300 rounded-b shadow-inner space-x-4 dark:bg-slate-700 dark:text-slate-200 dark:border-slate-600/70">
<button class="btn btn-primary">Subscribe</button>
<button class="btn btn-white" data-action="click->railsui-modal#close">Cancel</button>
</div>
</div>
</div>
</div>
</div>
%div{"data-controller" => "railsui-modal"}
%button.btn.btn-primary{"data-action" => "click->railsui-modal#open", tabindex: "0", type: "button"}
Open modal with form
.hidden.fixed.inset-0.z-50.overflow-y-auto{"aria-labelledby" => "modal-with-form", "aria-modal" => "true", "data-action" => "keyup@window->railsui-modal#closeWithEsc", "data-railsui-modal-target" => "container", role: "dialog"}
.h-screen.w-full.relative.flex.items-center.justify-center
.hidden.rounded.shadow-xl.mx-auto.max-w-lg.bg-white.m-1.p-8.origin-bottom.relative.dark:bg-slate-700.dark:text-slate-200{"data-railsui-modal-target" => "content", "data-transition-enter-active" => "transition ease-out duration-300", "data-transition-enter-from" => "transform opacity-0 scale-95", "data-transition-enter-to" => "transform opacity-100 scale-100", "data-transition-leave-active" => "transition ease-in duration-300", "data-transition-leave-from" => "transform opacity-100 scale-100", "data-transition-leave-to" => "transform opacity-0 scale-95"}
%button.absolute.top-2.right-2.w-8.h-8.bg-transparent.hover:bg-slate-50.flex.items-center.justify-center.rounded-full.group{class: "dark:hover:bg-slate-50/50", "data-action" => "click->railsui-modal#close", type: "button"}
= icon "x-mark", class: "text-slate-400 size-6 group-hover:text-slate-500 pointer-events-none dark:group-hover:text-slate-800 dark:text-slate-400"
%h3#modal-with-form.mb-3.text-2xl.font-extrabold.text-slate-900.dark:text-slate-100.tracking-tight Subscribe
.prose.prose-slate.dark:prose-invert.mt-2.mb-6
%p Join our community to get early access to new features, exclusive content, and connect with other developers.
%form{action: "#"}
.form-group
%label.form-label{for: "email_demo"} E-mail
%input#email_demo.form-input{placeholder: "saasquatch@railsui.com", type: "email"}/
.form-group
%label.form-label{for: "reason_demo"} Reason for joining
%textarea#reason_demo.form-input{name: "reason", placeholder: "In a couple sentences let us know your reason for joining the Rails UI community"}
.mt-8.flex.justify-start.items-center.flex-wrap.bg-gray-50.px-8.py-4.-mx-8.-mb-8.border-t.border-slate-300.rounded-b.shadow-inner.space-x-4.dark:bg-slate-700.dark:text-slate-200{class: "dark:border-slate-600/70"}
%button.btn.btn-primary Subscribe
%button.btn.btn-white{"data-action" => "click->railsui-modal#close"} Cancel
import { RailsuiModal } from 'railsui-stimulus'
application.register('railsui-modal', RailsuiModal)