Modal Component
A component for creating modals with Bootstrap 5.
Parameters:
- id: string - Modal ID (required)
- header_icon: icon for header (optional)
- title: string - Modal title (optional)
- content: string/block - Modal body content (optional)
- footer: string/block - Modal footer content (optional)
- size: string - Modal size (sm, lg, xl) (optional)
- centered: boolean - Whether to vertically center the modal (optional)
- scrollable: boolean - Whether to make the modal body scrollable (optional)
- fullscreen: boolean/string - Make modal fullscreen (true, sm-down, md-down, etc.) (optional)
- static: boolean - Whether to disable closing when clicking outside (optional)
- trigger: object - Trigger button configuration (optional)
- text: string - Button text (optional)
- variant: string - Button variant (optional)
- size: string - Button size (optional)
- icon: string - Button icon (optional)
- header_class: string - Additional header classes (optional)
- body_class: string - Additional body classes (optional)
- footer_class: string - Additional footer classes (optional)
- class: string - Additional modal classes (optional)
- attributes: string - Additional modal attributes (optional)
Basic modals are the most basic type of modal.
ThemedComponent::make('overlays/modal')
->title('Basic Modal')
->content('<p>This is a basic modal example with a simple content.</p>')
->footer(
ThemedComponent::make('buttons/button')
->type('button')
->variant('secondary')
->text('Close')
->attributes('data-bs-dismiss=modal')
->render() .
ThemedComponent::make('buttons/button')
->type('button')
->variant('primary')
->text('Save changes')
->render()
)
->trigger([
'text' => 'Basic Modal',
'variant' => 'primary',
])
->id('basicModal')
->render();
Small modals are useful for quick information.
ThemedComponent::make('overlays/modal')
->title('Small Modal')
->size('sm')
->content('<p>This is a smaller modal for quick information.</p>')
->footer(
ThemedComponent::make('buttons/button')
->type('button')
->variant('secondary')
->text('Close')
->attributes('data-bs-dismiss=modal')
->render()
)
->trigger([
'text' => 'Small Modal',
'variant' => 'secondary',
'icon' => ThemedComponent::make('icons/icon')
->name('calendar-month')
->render()
])
->header_icon(
ThemedComponent::make('icons/icon')
->name('calendar-month')
->render()
)
->id('smallModal')
->render();
Large modals are ideal for detailed content or forms.
ThemedComponent::make('overlays/modal')
->title('Large Modal')
->size('lg')
->content('<p>This is a larger modal for displaying more detailed content or forms.</p>')
->footer(
ThemedComponent::make('buttons/button')
->type('button')
->variant('secondary')
->text('Close')
->attributes('data-bs-dismiss=modal')
->render() .
ThemedComponent::make('buttons/button')
->type('button')
->variant('primary')
->text('Submit')
->render()
)
->trigger([
'text' => 'Large Modal',
'variant' => 'success'
])
->id('largeModal')
->render();
Fullscreen modals take up the entire screen for immersive experiences.
ThemedComponent::make('overlays/modal')
->title('Fullscreen Modal')
->size('fullscreen')
->content('<p>This modal takes up the entire screen, useful for immersive experiences or complex workflows.</p>')
->footer(
ThemedComponent::make('buttons/button')
->type('button')
->variant('secondary')
->text('Close')
->attributes('data-bs-dismiss=modal')
->render()
)
->trigger([
'text' => 'Fullscreen Modal',
'variant' => 'danger'
])
->id('fullscreenModal')
->render();
The Twig template file for the Modal component
{# Modal Component
A component for creating modals with Bootstrap 5.
Parameters:
- id: string - Modal ID (required)
- header_icon: icon for header (optional)
- title: string - Modal title (optional)
- content: string/block - Modal body content (optional)
- footer: string/block - Modal footer content (optional)
- size: string - Modal size (sm, lg, xl) (optional)
- centered: boolean - Whether to vertically center the modal (optional)
- scrollable: boolean - Whether to make the modal body scrollable (optional)
- fullscreen: boolean/string - Make modal fullscreen (true, sm-down, md-down, etc.) (optional)
- static: boolean - Whether to disable closing when clicking outside (optional)
- trigger: object - Trigger button configuration (optional)
- text: string - Button text (optional)
- variant: string - Button variant (optional)
- size: string - Button size (optional)
- icon: string - Button icon (optional)
- header_class: string - Additional header classes (optional)
- body_class: string - Additional body classes (optional)
- footer_class: string - Additional footer classes (optional)
- class: string - Additional modal classes (optional)
- attributes: string - Additional modal attributes (optional)
#}
{# Set default values #}
{% set size = content.size|default(null) %}
{% set centered = content.centered ?? false %}
{% set scrollable = content.scrollable ?? false %}
{% set static = content.static ?? false %}
{# Build modal classes #}
{% set modal_classes = ['modal'] %}
{% set dialog_classes = ['modal-dialog'] %}
{% if size %}
{% set dialog_classes = dialog_classes|merge(['modal-' ~ size]) %}
{% endif %}
{% if centered %}
{% set dialog_classes = dialog_classes|merge(['modal-dialog-centered']) %}
{% endif %}
{% if scrollable %}
{% set dialog_classes = dialog_classes|merge(['modal-dialog-scrollable']) %}
{% endif %}
{% if content.fullscreen %}
{% if content.fullscreen == true %}
{% set dialog_classes = dialog_classes|merge(['modal-fullscreen']) %}
{% else %}
{% set dialog_classes = dialog_classes|merge(['modal-fullscreen-' ~ content.fullscreen]) %}
{% endif %}
{% endif %}
{% if content.class %}
{% set modal_classes = modal_classes|merge([content.class]) %}
{% endif %}
{# Render trigger button if configured #}
{% if content.trigger %}
<button
type="button"
class="btn btn-{{ content.trigger.variant|default('primary') }}{% if content.trigger.size %} btn-{{ content.trigger.size }}{% endif %}{% if content.trigger.class %} {{ content.trigger.class }}{% endif %}"
data-bs-toggle="modal"
data-bs-target="#{{ content.id }}"
>
{% if content.trigger.icon %}
{{ content.trigger.icon|raw }}
{% endif %}
{{ content.trigger.text|raw }}
</button>
{% endif %}
{# Render modal #}
<div
class="{{ modal_classes|join(' ') }}"
id="{{ content.id }}"
tabindex="-1"
aria-labelledby="{{ content.id }}-label"
aria-hidden="true"
{% if static %}data-bs-backdrop="static" data-bs-keyboard="false"{% endif %}
{% if content.attributes %}
{{ content.attributes }}
{% endif %}
>
<div class="{{ dialog_classes|join(' ') }}">
<div class="modal-content">
{% if content.title %}
<div class="modal-header{% if content.header_class %} {{ content.header_class }}{% endif %}">
<h5 class="modal-title" id="{{ content.id }}-label">
{% if content.header_icon %}
{{ content.header_icon|raw }}
{% endif %}
{{ content.title|raw }}
</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
{% endif %}
<div class="modal-body{% if content.body_class %} {{ content.body_class }}{% endif %}">
{{ content.content|raw }}
</div>
{% if content.footer %}
<div class="modal-footer{% if content.footer_class %} {{ content.footer_class }}{% endif %}">
{{ content.footer|raw }}
</div>
{% endif %}
</div>
</div>
</div>
{# Initialize modal if static #}
{% if static %}
<script>
document.addEventListener('DOMContentLoaded', function() {
var modal = document.getElementById('{{ content.id }}');
if (modal) {
var modalInstance = new bootstrap.Modal(modal, {
backdrop: 'static',
keyboard: false
});
}
});
</script>
{% endif %}