āDialogā Component
Design: zeplin.
Under the hood the application uses a standard dialog HTML element with a polyfill to support all browsers.
The modal dialog is a disruptive dialog box that appears in front of a pageās content. It is used to convey important information within context of the page, since it blocks the pageās content while keeping it in view (on medium and large viewports).
Modal dialogs should be used intentionally and sparingly. They are disruptive to a userās flow and thus should be used to:
- Confirm a userās action, especially if the action is destructive (e.g. dropping a course) or irreversible.
- Provide additional informationāespecially rich information containing lists or imagesāthat cannot fit into a tooltip or text on the page.
- Let users fill up a form within context, in cases where this helps to either speed up the process or return users to their original flows after the completion of the form. For instance, the āAdd a member to a course scheduleā modal allows an admin to quickly add someone to a course schedule without having to go to a separate page.
By design guideline, the application should display maximum one dialog at the time. If you open another dialog, the application will close the previous one first.
Note About Accessibility
Always use <button>
to open dialogs.
Even when in cases where the button is supposed to look like a link,
button with class ālinkā should be used instead of an anchor tag.
Basic Dialog
Usage
<button class="button button--primary" data-dialog="basicDialog">
Open Modal Dialog
</button>
<x-dialog id="basicDialog">
<x-slot:title>Dialog title</x-slot:title>
<p>Dialog content</p>
</x-dialog>
Dialog with a form
By default, the whole dialog content is also wrapped by a form element: dialog > form
.
You can add method
and action
attributes directly to the <x-dialog>
component
they will be used for the form inside the dialog.
Usage
Simplified example:
<x-dialog id="dialogWithCustomizedForm" method="POST" action="/your/url">
<x-slot:title>Customized form</x-slot:title>
<input type="text" name="input1" required>
@method('PATCH')
<x-slot:footer>
<button type="submit" class="button button--primary">Submit form</button>
<button type="reset" class="button button--ghost">Reset form and close dialog</button>
</x-slot:footer>
</x-dialog>
Confirmation Dialog
Usage
<button class="button button--primary" data-dialog="deleteCommentDialog">
Open Confirmation Dialog
</button>
<x-dialog id="deleteCommentDialog">
<x-slot:title>Delete reply?</x-slot:title>
<p>
Are you sure you want to delete your reply? This action cannot be undone.
</p>
<x-slot:footer>
<button value="ACTION_DELETE" class="button button--warning">Yes, delete comment</button>
<button value="" class="button button--ghost">Cancel</button>
</x-slot:footer>
</x-dialog>
To intercept delete button click we can use code like below:
const deleteCommentDialog = document.querySelector('#deleteCommentDialog');
deleteCommentDialog.addEventListener('close', () => {
if (deleteCommentDialog.returnValue === 'DELETE_ACTION') {
deleteReply();
}
});
Dialog with AJAX form
Usage
<button class="button button--primary" data-dialog="searchMemberDialog">
Open Form Modal Dialog
</button>
<x-dialog id="searchMemberDialog">
<x-slot:title>Add a member to a course schedule</x-slot:title>
<div class="form__field">
<label for="memberKeyword" class="pb-small mb-none">
Name, email or member ID
</label>
<div class="inputGroup">
<input type="text" id="memberKeyword" name="keyword" placeholder="Please enter a memberās name, ID, or email address" required minlength="3" autofocus autocomplete="off">
<div class="inputGroup__addon inputGroup__addon--noBorder">
<button type="submit" class="button button--primary ixdf-spinner">
Search
</button>
</div>
</div>
</div>
</x-dialog>
Below is example of code that could handle AJAX requests:
const authorDialog = document.querySelector('#searchMemberDialog');
authorDialog.addEventListener('submit', (event) => {
event.preventDefault();
populateAuthorSearchResults(authorDialog);
});
authorDialog.addEventListener('close', () => {
cleanupAuthorSearchResults(authorDialog);
});