Modale
Ce composant présente une fenêtre modale
Classes utilisables
Modificateurs de taille
.modal--sm: Small.modal--md: Medium.modal--lg: Large.modal--xl: Extra-large
Modificateurs d'apparence
.modal--sticky-header: rend le header de la modale "sticky".modal--sticky-footer: rend le footer de la modale "sticky".modal--backdrop-dark: Fonce l'arrière-plan du volet.modal--backdrop-light: Éclaircit l'arrière-plan du volet.modal--backdrop-blur: Floute l'arrière-plan du volet
Taille
sm
md
lg
xl
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="kuik" uri="kuik" %>
<kuik:heading size="lg" skin="a" title="Taille" level="3" />
<kuik:heading size="lg" title="sm" level="4" />
<kuik:button command="show-modal" commandfor="modal-example-sm" size="sm">
Afficher Modale sm
</kuik:button>
<kuik:modal
size="sm"
modalTitle="Modal sm"
closeIconTitle="Fermer"
id="modal-example-sm"
backdrop="dark"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-sm" size="sm">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<kuik:heading size="lg" title="md" level="4" />
<kuik:button command="show-modal" commandfor="modal-example-md" size="md">
Afficher Modale md
</kuik:button>
<kuik:modal
size="md"
modalTitle="Modal md"
closeIconTitle="Fermer"
id="modal-example-md"
backdrop="dark"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-md" size="md">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<kuik:heading size="lg" title="lg" level="4" />
<kuik:button command="show-modal" commandfor="modal-example-lg" size="lg">
Afficher Modale lg
</kuik:button>
<kuik:modal
size="lg"
modalTitle="Modal lg"
closeIconTitle="Fermer"
id="modal-example-lg"
backdrop="dark"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-lg" size="lg">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<kuik:heading size="lg" title="xl" level="4" />
<kuik:button command="show-modal" commandfor="modal-example-xl" size="xl">
Afficher Modale xl
</kuik:button>
<kuik:modal
size="xl"
modalTitle="Modal xl"
closeIconTitle="Fermer"
id="modal-example-xl"
backdrop="dark"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-xl" size="xl">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
Backdrop
| Light | Dark | Aucun | |
|---|---|---|---|
| Sans flouté | |||
| Avec flouté |
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="kuik" uri="kuik" %>
<kuik:heading size="lg" skin="a" title="Backdrop" level="3" />
<table class="table table--xl">
<thead>
<tr class="table__tr">
<th class="table__th"></th>
<th class="table__th">Light</th>
<th class="table__th">Dark</th>
<th class="table__th">Aucun</th>
</tr>
</thead>
<tbody>
<tr class="table__tr">
<td class="table__th">Sans flouté</td>
<td class="table__td"><kuik:button command="show-modal" commandfor="modal-example-bd-light" size="sm">Afficher</kuik:button></td>
<td class="table__td"><kuik:button command="show-modal" commandfor="modal-example-bd-dark" size="sm">Afficher</kuik:button></td>
<td class="table__td"><kuik:button command="show-modal" commandfor="modal-example-bd-none" size="sm">Afficher</kuik:button></td>
</tr>
<tr class="table__tr">
<td class="table__th">Avec flouté</td>
<td class="table__td"><kuik:button command="show-modal" commandfor="modal-example-bd-light-blur" size="sm">Afficher</kuik:button></td>
<td class="table__td"><kuik:button command="show-modal" commandfor="modal-example-bd-dark-blur" size="sm">Afficher</kuik:button></td>
<td class="table__td"><kuik:button command="show-modal" commandfor="modal-example-bd-blur" size="sm">Afficher</kuik:button></td>
</tr>
</tbody>
</table>
<kuik:modal
size="sm"
modalTitle="Modale avec backdrop light"
closeIconTitle="Fermer"
id="modal-example-bd-light"
backdrop="light"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-bd-light" size="sm">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<kuik:modal
size="sm"
modalTitle="Modale avec backdrop dark"
closeIconTitle="Fermer"
id="modal-example-bd-dark"
backdrop="dark"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-bd-dark" size="sm">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<kuik:modal
size="sm"
modalTitle="Modale avec backdrop light"
closeIconTitle="Fermer"
id="modal-example-bd-light-blur"
backdrop="light blur"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-bd-light-blur" size="sm">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<kuik:modal
size="sm"
modalTitle="Modale avec backdrop dark"
closeIconTitle="Fermer"
id="modal-example-bd-dark-blur"
backdrop="dark blur"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-bd-dark-blur" size="sm">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<kuik:modal
size="sm"
modalTitle="Modale sans backdrop mais avec blur"
closeIconTitle="Fermer"
id="modal-example-bd-blur"
backdrop="blur"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-bd-blur" size="sm">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<kuik:modal
size="sm"
modalTitle="Modale sans backdrop"
closeIconTitle="Fermer"
id="modal-example-bd-none"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-bd-none" size="sm">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
Exemples utilisant Javascript
confirm
prompt
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="kuik" uri="kuik" %>
<kuik:heading size="lg" skin="a" title="Exemples utilisant Javascript" level="3" />
<kuik:heading size="lg" title="confirm" level="4" />
<kuik:button id="for-modal-example-confirm" size="md">
Afficher Modale Confirm
</kuik:button>
<kuik:modal
size="md"
modalTitle="Modal Confirm"
closeIconTitle="Fermer"
id="modal-example-confirm"
backdrop="dark blur"
>
<kuik:modal-body>
<p class="u-pi-sm">
Voulez-vous continuer ?
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex" style="--column-gap:var(--space-2)">
<div class="u-hspacer-auto"></div>
<kuik:button priority="secondary" size="md" value="no" type="submit">
Non
</kuik:button>
<kuik:button size="md" value="yes" type="submit">
Oui
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<kuik:heading size="lg" title="prompt" level="4" />
<kuik:button id="for-modal-example-prompt" size="md">
Afficher Modale Prompt
</kuik:button>
<kuik:modal
size="md"
modalTitle="Modal Confirm"
closeIconTitle="Fermer"
id="modal-example-prompt"
backdrop="dark blur"
>
<kuik:modal-body>
<div class="u-p-sm">
<kuik:form-field-input id="name" label="Votre nom" />
</div>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex" style="--column-gap:var(--space-2)">
<div class="u-hspacer-auto"></div>
<kuik:button priority="secondary" size="md" command="close" commandfor="modal-example-prompt">
Annuler
</kuik:button>
<kuik:button size="md" value="send" type="submit">
Envoyer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<script type="module" defer>
import { declareCustomFormModal, requestModal } from "/static/kuik/modal/modal-form.js";
const buttonConfirm = document.getElementById('for-modal-example-confirm');
buttonConfirm.addEventListener('click', async () => {
const returnValue = await requestModal('modal-example-confirm');
alert(`Return value = \${returnValue}`);
});
const confirmModal = declareCustomFormModal('modal-example-prompt', (event, modal, formData) => {
if (modal.returnValue === 'send') {
return formData.get('name');
}
});
const buttonPrompt = document.getElementById('for-modal-example-prompt');
buttonPrompt.addEventListener('click', async () => {
const returnValue = await requestModal(confirmModal);
alert(`Return value = \${returnValue}`);
});
</script>
Taille
sm
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="kuik" uri="kuik" %>
<kuik:heading size="lg" skin="a" title="Taille" level="3" />
<kuik:heading size="lg" title="sm" level="4" />
<kuik:button command="show-modal" commandfor="modal-example-sticky-header" size="sm">
Afficher Modale sm
</kuik:button>
<kuik:modal
size="sm"
modalTitle="Modal sm"
closeIconTitle="Fermer"
id="modal-example-sticky-header"
backdrop="dark"
class="modal--sticky-footer modal--sticky-header"
>
<kuik:modal-body>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
<p class="u-pi-sm">
Diam eu maximus fusce <strong>sollicitudin</strong> placerat lorem <i>molestie</i> leo gravida interdum nunc <u>cursus condimentum</u> felis facilisis nisi rutrum condimentum sollicitudin purus purus ipsum suspendisse nisl.
</p>
</kuik:modal-body>
<kuik:modal-footer>
<div class="l-flex">
<div class="u-hspacer-auto"></div>
<kuik:button command="close" commandfor="modal-example-sticky-header" size="sm">
Fermer
</kuik:button>
</div>
</kuik:modal-footer>
</kuik:modal>
<%@ tag pageEncoding="UTF-8" trimDirectiveWhitespaces="true" dynamic-attributes="dynattrs" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${requestScope.__modalStep eq 'modalFooter'}">
<footer class="modal__footer">
<jsp:doBody />
</footer>
</c:if>
@use 'mixins/mixins-customizables' as custom;
@use 'mixins/mixins-accessibility' as accessibility;
$prefix: 'modal';
$prefix-header: 'modal-header';
$prefix-footer: 'modal-footer';
.modal {
@include custom.component($prefix, true);
--modal-min-margin: var(--space-8);
max-width: min(100vw - var(--modal-min-margin) * 2, var(--modal-max-width));
opacity: 0;
overflow: hidden;
transition: var(--duration-normal) all allow-discrete;
translate: 0 calc(-1 * var(--space-4));
}
.modal[open] {
opacity: 1;
translate: 0 0;
}
.modal__header {
@include custom.component($prefix-header, true);
align-items: center;
display: flex;
justify-content: start;
width: 100%;
}
.modal__title {
font-size: var(--font-size-50);
font-weight: var(--font-weight-700);
margin-block: var(--space-0);
}
.modal__close-label {
@include accessibility.visually-hidden;
}
.modal__footer {
@include custom.component($prefix-footer, true);
width: 100%;
}
.modal--sticky-header {
.modal__header {
position: sticky;
top: 0;
}
}
.modal--sticky-footer {
.modal__footer {
bottom: 0;
position: sticky;
}
}
.modal--sticky-header.modal--sticky-footer {
.modal__body {
overflow-y: auto;
}
}
@each $size in 'sm', 'md', 'lg', 'xl' {
.modal--#{$size} {
--modal-max-width: var(--maxwidth-#{$size});
@include custom.component($prefix);
.modal__header {
@include custom.component($prefix-header);
}
.modal__footer {
@include custom.component($prefix-footer);
}
}
}
.modal::backdrop {
backdrop-filter: blur(var(--size-0));
background-color: transparent;
opacity: 0;
position: fixed;
transition: var(--duration-normal) all allow-discrete;
}
.modal[open]::backdrop {
opacity: 1;
}
.modal--backdrop-dark[open]::backdrop {
background-color: rgb(0 0 0 / 40%);
}
.modal--backdrop-light[open]::backdrop {
background-color: rgb(255 255 255 / 40%);
}
.modal--backdrop-blur[open]::backdrop {
backdrop-filter: blur(var(--size-1));
}
:root:has(.modal) {
scrollbar-gutter: stable;
}
:root:has(.modal[open]) {
overflow: hidden;
}
@starting-style {
.modal[open] {
opacity: 0;
translate: 0 calc(-1 * var(--space-4));
}
.modal::backdrop {
backdrop-filter: blur(var(--size-0));
background-color: transparent;
opacity: 0;
}
}
/**
* Vérifie si l'élément fourni en paramètre est une modale et la renvoie si c'est le cas.
* @param modal {String|HTMLDialogElement} Identifiant unique ou élément HTML à vérifier.
* @returns {HTMLDialogElement} Modale comme élément HTML.
* @throws {Error} Erreur si l'élément n'est pas trouvé ou si ce n'est pas une modale.
*/
export function retrieveModal(modal) {
const originalModal = modal;
if (typeof modal === typeof '') {
modal = document.getElementById(modal);
}
if (!(modal && modal instanceof HTMLDialogElement)) throw new Error(`#${originalModal} is not a dialog.`);
return modal;
}
/**
* Permet d'invoquer une fenêtre de dialogue modale pour interroger un utilisateur.
* @param modal {String|HTMLDialogElement} Fenêtre de dialogue modale. Peut être un identifiant unique ou un élément HTML
* @returns {Promise} Valeur de retour
*/
export function requestModal(modal) {
return new Promise((resolve, reject) => {
try {
modal = retrieveModal(modal);
modal.addEventListener('close', event => {
resolve(event.target.returnValue);
}, { once: true });
modal.showModal();
} catch (e) {
reject(e);
}
});
}
/**
* Permet à une fenêtre de dialogue modale contenant un formulaire de renvoyer une valeur de retour personnalisée.
* @param modal {String|HTMLDialogElement} Fenêtre de dialogue modale. Peut être un identifiant unique ou un élément HTML
* @param closeHookCallback {Function} Fonction à appeler avant la fermeture de la modale.
* Cette fonction reçoit l'événement de fermeture (event), la modale (modal) et le formulaire (form) en paramètre.
* Elle peut envoyer une valeur de retour qui sera prise en charge par le handler de l'événement de fermeture.
* @returns {HTMLDialogElement} Renvoie la modale comme élément HTML.
* @throws {Error} Erreur si la modale demandée n'est pas trouvée ou n'est pas une fenêtre de dialogue.
*/
export function declareCustomFormModal(modal, closeHookCallback) {
modal = retrieveModal(modal);
modal.addEventListener('close', async event => {
event.preventDefault();
const [ form ] = modal.getElementsByTagName('form');
const formData = new FormData(form);
const returnValue = await closeHookCallback(event, modal, formData);
modal.returnValue = returnValue;
modal.close(returnValue);
}, { capture: true });
return modal;
}