Modal
Bootstrap 5 modal markup, opened by a trigger with data-bs-toggle="modal" and data-bs-target="#<id>". It needs
tabler.js.
<twig:Tabler:Button variant="danger" data-bs-toggle="modal" data-bs-target="#delete-user">Delete user</twig:Tabler:Button>
<twig:Tabler:Modal id="delete-user" title="Delete Jane Doe?" text="She loses access to the workspace immediately." /><button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#delete-user">Delete user</button><div class="modal" tabindex="-1" id="delete-user"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Delete Jane Doe?</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body">She loses access to the workspace immediately.</div> </div> </div></div>Composed
Section titled “Composed”The sub-components take over for a form or custom actions. blur blurs the page behind the modal (modal-blur).
Attributes go to the root <div class="modal">: add fade for the open animation.
<twig:Tabler:Button variant="primary" data-bs-toggle="modal" data-bs-target="#invite-user">Invite user</twig:Tabler:Button>
<twig:Tabler:Modal id="invite-user" blur="{{ true }}" class="fade"> <twig:Tabler:Modal:Header> <twig:Tabler:Modal:Title>Invite a user</twig:Tabler:Modal:Title> <twig:Tabler:Modal:Close /> </twig:Tabler:Modal:Header> <twig:Tabler:Modal:Body> <label class="form-label" for="invite-email">Email</label> <input type="email" id="invite-email" class="form-control" placeholder="jane@example.com"> </twig:Tabler:Modal:Body> <twig:Tabler:Modal:Footer> <twig:Tabler:Button variant="default" data-bs-dismiss="modal">Cancel</twig:Tabler:Button> <twig:Tabler:Button variant="primary" class="ms-auto">Send invitation</twig:Tabler:Button> </twig:Tabler:Modal:Footer></twig:Tabler:Modal><button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#invite-user">Invite user</button><div class="modal modal-blur fade" tabindex="-1" id="invite-user"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Invite a user</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <label class="form-label" for="invite-email">Email</label> <input type="email" id="invite-email" class="form-control" placeholder="jane@example.com" /> </div> <div class="modal-footer"> <button type="button" class="btn" data-bs-dismiss="modal">Cancel</button> <button type="button" class="btn btn-primary ms-auto">Send invitation</button> </div> </div> </div></div>Size, position and status
Section titled “Size, position and status”size sets the width of the dialog (fullscreen covers the whole viewport), centered centers it vertically, and
status adds a colored bar at its top:
<twig:Tabler:Button variant="danger" data-bs-toggle="modal" data-bs-target="#cancel-subscription">Cancel subscription</twig:Tabler:Button>
<twig:Tabler:Modal id="cancel-subscription" size="sm" centered="{{ true }}" status="danger" title="Cancel subscription?" text="The workspace moves to the free plan at the end of the billing period." footer="You can subscribe again at any time." /><button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#cancel-subscription"> Cancel subscription</button><div class="modal" tabindex="-1" id="cancel-subscription"> <div class="modal-dialog modal-sm modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-status bg-danger"></div> <div class="modal-header"> <h5 class="modal-title">Cancel subscription?</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body">The workspace moves to the free plan at the end of the billing period.</div> <div class="modal-footer">You can subscribe again at any time.</div> </div> </div></div>The status bar is rendered outside the content block, so a composed modal keeps it: set status and pass the
sub-components as children:
<twig:Tabler:Button variant="success" data-bs-toggle="modal" data-bs-target="#payment-received">Show receipt</twig:Tabler:Button>
<twig:Tabler:Modal id="payment-received" size="sm" centered="{{ true }}" status="success"> <twig:Tabler:Modal:Body class="text-center py-4"> <twig:Tabler:Icon name="circle-check" class="text-green mb-2 fs-1" /> <h3>Payment received</h3> <div class="text-secondary">Invoice #1042 is paid: 1,250.00 EUR.</div> </twig:Tabler:Modal:Body> <twig:Tabler:Modal:Footer> <twig:Tabler:Button variant="default" block="{{ true }}" data-bs-dismiss="modal">Close</twig:Tabler:Button> </twig:Tabler:Modal:Footer></twig:Tabler:Modal><button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#payment-received"> Show receipt</button><div class="modal" tabindex="-1" id="payment-received"> <div class="modal-dialog modal-sm modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-status bg-success"></div> <div class="modal-body text-center py-4"> <i class="ti ti-circle-check text-green mb-2 fs-1"></i> <h3>Payment received</h3> <div class="text-secondary">Invoice #1042 is paid: 1,250.00 EUR.</div> </div> <div class="modal-footer"> <button type="button" class="btn w-100" data-bs-dismiss="modal">Close</button> </div> </div> </div></div>For long content, scrollable scrolls the body of the dialog instead of the page.
Blocks
Section titled “Blocks”title, text and footer are plain strings. For richer content, such as buttons in the footer, override the
matching block: header, body or footer. The other blocks keep rendering from their props. See
Composition for how blocks work.
<twig:Tabler:Button variant="primary" data-bs-toggle="modal" data-bs-target="#deploy">Deploy</twig:Tabler:Button>
<twig:Tabler:Modal id="deploy" title="Deploy to production?" text="Release v2.4.0 goes live for every customer."> <twig:block name="footer"> <twig:Tabler:Modal:Footer> <twig:Tabler:Button variant="default" data-bs-dismiss="modal">Cancel</twig:Tabler:Button> <twig:Tabler:Button variant="primary" class="ms-auto" data-bs-dismiss="modal">Deploy</twig:Tabler:Button> </twig:Tabler:Modal:Footer> </twig:block></twig:Tabler:Modal><button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#deploy">Deploy</button><div class="modal" tabindex="-1" id="deploy"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Deploy to production?</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body">Release v2.4.0 goes live for every customer.</div> <div class="modal-footer"> <button type="button" class="btn" data-bs-dismiss="modal">Cancel</button> <button type="button" class="btn btn-primary ms-auto" data-bs-dismiss="modal">Deploy</button> </div> </div> </div></div>Static backdrop
Section titled “Static backdrop”With staticBackdrop, neither a click on the backdrop nor the Escape key closes the modal. dismissible="{{ false }}"
removes the close button of the header (see boolean props), so the
footer button is the only way out:
<twig:Tabler:Button variant="primary" data-bs-toggle="modal" data-bs-target="#accept-terms">Continue</twig:Tabler:Button>
<twig:Tabler:Modal id="accept-terms" staticBackdrop="{{ true }}" dismissible="{{ false }}" title="Updated terms of service" text="Accept the new terms to keep using the workspace."> <twig:block name="footer"> <twig:Tabler:Modal:Footer> <twig:Tabler:Button variant="primary" data-bs-dismiss="modal">Accept</twig:Tabler:Button> </twig:Tabler:Modal:Footer> </twig:block></twig:Tabler:Modal><button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#accept-terms">Continue</button><div class="modal" tabindex="-1" id="accept-terms" data-bs-backdrop="static" data-bs-keyboard="false"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"><h5 class="modal-title">Updated terms of service</h5></div> <div class="modal-body">Accept the new terms to keep using the workspace.</div> <div class="modal-footer"> <button type="button" class="btn btn-primary" data-bs-dismiss="modal">Accept</button> </div> </div> </div></div>| Prop | Type | Default | Description |
|---|---|---|---|
id |
string? | null |
DOM id targeted by triggers (data-bs-target="#id") |
size |
string | 'md' |
sm md lg xl full (modal-full-width) fullscreen (modal-fullscreen) |
centered |
bool | false |
Vertically centered dialog (modal-dialog-centered) |
scrollable |
bool | false |
Scrolls the body instead of the page (modal-dialog-scrollable) |
status |
string? | null |
Color of the status bar, rendered with Modal:Status |
title |
string? | null |
Rendered with Modal:Header and Modal:Title |
text |
string? | null |
Rendered with Modal:Body |
footer |
string? | null |
Rendered with Modal:Footer |
dismissible |
bool | true |
Close button in the header rendered from title (Modal:Close) |
staticBackdrop |
bool | false |
The backdrop and the Escape key do not close the modal |
blur |
bool | false |
Blurs the page behind the backdrop (modal-blur) |
Other attributes go to the root <div class="modal" tabindex="-1">.
Sub-components
Section titled “Sub-components”| Component | Renders |
|---|---|
Modal:Header |
<div class="modal-header">: holds the title and the close button |
Modal:Title |
<h5 class="modal-title"> |
Modal:Close |
<button class="btn-close" data-bs-dismiss="modal" aria-label="Close"> |
Modal:Body |
<div class="modal-body"> |
Modal:Footer |
<div class="modal-footer">: usually the actions |
Modal:Status |
<div class="modal-status bg-…">: the colored bar; variant prop, 'primary' by default |
Modal:Status takes variant: primary secondary success danger warning info dark light.
Blocks
Section titled “Blocks”| Block | Default |
|---|---|
header |
Modal:Header with Modal:Title and Modal:Close (when dismissible), when title is set |
body |
Modal:Body with the text prop, when set |
footer |
Modal:Footer with the footer prop, when set |
content |
header, body and footer: replace it to compose freely; the status bar stays outside it |
