Skip to Main Content

Modals

A modal window lets users focus on completing a specific task, such as reading important information or making a decision.

Use when:

  • You want the user to read information or complete a task related to a specific page. The user can interact with the modal window without having to navigate away from a page.
  • You need to alert users of an action they’re about to take (for example, verifying an action or confirming that data will be lost).
  • You need to indicate a simple task or process that doesn’t involve complicated interactions (for example, onboarding or signing in).

Interactive component

Library integration

Use the codes below to add this component to your project. Download the latest version of the library to easily implement our full range of components.

angular

Step 1. Install

Execute the following command to install this component.

npm i [NPM-PLACE-HOLDER]/ds-modals

Step 2. Import

Import the following into your app.module.ts file.

import { DsModalsModule } from 'ds-modals';

Step 3. Import modal service into your component file

Import the following into your app.module.ts file.

import { DsModalsService } from 'ds-modals';
Large Modal
<cpc-ds-modals></cpc-ds-modals> 
<cpc-ds-button 
     [id]="'largeModal'" 
     (click)="openDialog()" 
     class='primary-button' 
     body='Large Modal'>
</cpc-ds-button>
Medium Modal
<cpc-ds-modals></cpc-ds-modals> 
<cpc-ds-button
    [id]="'largeMedium'" 
    (click)="modalService.openModal('dsModal-medium', mediumOptionModal)" 
    class='primary-button' 
    body='Medium Modal'>
</cpc-ds-button>
Small Modal
<cpc-ds-modals></cpc-ds-modals> 
<cpc-ds-button 
    [id]="'largeSmall'" 
    (click)="modalService.openModal('dsModal-small', smallOptionModal)" 
    class='primary-button' 
    body='Small Modal'>
</cpc-ds-button> 
Properties
Name Type Default Description
id string  

Button id.

class string primary-button by-keyboard

There are two types of buttons: primary-button and secondary-button

body string  

Button text : for eg: body='button text'

(click) property  

Call the method : for eg: (click)="openDialog()" or (click)="modalService.openModal('dsModal-medium', mediumOptionModal)"

openModal method   A modal service method to open the dialog. It accepts 2 parameters: modal size and modal options. Three modal sizes available: dsModal-large dsModal-medium dsModal-small Modal Options: largeOptionModal mediumOptionModal smallOptionModal
Modal options - name string   Name of modal : for eg:- largeOptionModal = { name: 'abc', heading: 'This is modal heading', bodyContent: this.largeModalBody, showActionMenu: true, showCloseButton: true, showCloseButtonTitle: 'Cancel', showConfirmButton: true, showConfirmButtonTitle: 'OK', };
Modal options - heading string   Heading of the modal  for eg:- largeOptionModal = { name: 'abc', heading: 'This is modal heading', bodyContent: this.largeModalBody, showActionMenu: true, showCloseButton: true, showCloseButtonTitle: 'Cancel', showConfirmButton: true, showConfirmButtonTitle: 'OK', };
Modal options - bodyContent string   for eg:- largeOptionModal = { name: 'abc', heading: 'This is modal heading', bodyContent: this.mediumModalBody, showActionMenu: true, showCloseButton: true, showCloseButtonTitle: 'Cancel', showConfirmButton: true, showConfirmButtonTitle: 'OK', };
Modal options – showActionMenu string   Shows the Confirm and Cancel Buttons for eg:- largeOptionModal = { name: 'abc', heading: 'This is modal heading', bodyContent: this.largeModalBody, showActionMenu: true, showCloseButton: true, showCloseButtonTitle: 'Cancel', showConfirmButton: true, showConfirmButtonTitle: 'OK', };
Modal options - showCloseButton string   Show/Hide close button for eg:- largeOptionModal = { name: 'abc', heading: 'This is modal heading', bodyContent: this.largeModalBody, showActionMenu: true, showCloseButton: true, showCloseButtonTitle: 'Cancel', showConfirmButton: true, showConfirmButtonTitle: 'OK', };
Modal options - showCloseButtonTitle string   If Close button shows, set the button text for eg:- largeOptionModal = { name: 'abc', heading: 'This is modal heading', bodyContent: this.largeModalBody, showActionMenu: true, showCloseButton: true, showCloseButtonTitle: 'Cancel', showConfirmButton: true, showConfirmButtonTitle: 'OK', };
Modal options - showConfirmButton string   Show/Hide the confirm button for eg:- largeOptionModal = { name: 'abc', heading: 'This is modal heading', bodyContent: this.largeModalBody, showActionMenu: true, showCloseButton: true, showCloseButtonTitle: 'Cancel', showConfirmButton: true, showConfirmButtonTitle: 'OK', };
Modal options - showConfirmButtonTitle string   If confirm button shows, set the button text  for eg:- largeOptionModal = { name: 'abc', heading: 'This is modal heading', bodyContent: this.largeModalBody, showActionMenu: true, showCloseButton: true, showCloseButtonTitle: 'Cancel', showConfirmButton: true, showConfirmButtonTitle: 'OK', };

HTML

Step 1: Import CSS

Import the following into your theme or page.

<link type="text/css" href="[CSS-PLACE-HOLDER]" rel="stylesheet">

Step 2: Import JS

Import the following into your theme or page.

<script src="[JS-PLACE-HOLDER]"></script> 

Code snippets

Large Modal
<div role="dialog" id="dialog1" aria-labelledby="dialog1_label" aria-modal="true" class="hidden">
                    
        <div class="modal-content">
            <button id="dialog1_label_closed" aria-label="Close modal" class="closebtn micro-buttons modal-close"></button>
            <h2 tabindex="-1" id="dialog1_label" class="dialog_label">
                Are you sure?
            </h2>
            <div id="dialog1_desc" class="dialog_desc">
                <p>
                    This is just a demonstration. If it were a real application, it would
                    provide a message telling whether the entered address is valid.
                </p>
                <p>
                    For demonstration purposes, this dialog has a lot of text. It demonstrates a
                    scenario where:
                </p>
                
                <p>
                    There are several ways to resolve this issue:
                </p>
                
                <p>
                    Please
                    <em>
                        DO NOT
                    </em>
                    make the element with role dialog focusable!
                </p>
                
                <p>
                    In this dialog, the first paragraph has
                    
                    . The first
                    paragraph is also contained inside the element that provides the dialog description, i.e., the element that is referenced
                    by
                    
                    . With some screen readers, this may have one negative
                    but relatively insignificant side effect when the dialog opens -- the first paragraph
                    may be announced twice. Nonetheless, making the first paragraph focusable and setting
                    the initial focus on it is the most broadly accessible option.
                </p><p>
                    This is just a demonstration. If it were a real application, it would
                    provide a message telling whether the entered address is valid.
                </p>
                <p>
                    For demonstration purposes, this dialog has a lot of text. It demonstrates a
                    scenario where:
                </p>
                
                <p>
                    There are several ways to resolve this issue:
                </p>
                
                <p>
                    Please
                    <em>
                        DO NOT
                    </em>
                    make the element with role dialog focusable!
                </p>
                
                <p>
                    In this dialog, the first paragraph has
                    
                    . The first
                    paragraph is also contained inside the element that provides the dialog description, i.e., the element that is referenced
                    by
                    
                    . With some screen readers, this may have one negative
                    but relatively insignificant side effect when the dialog opens -- the first paragraph
                    may be announced twice. Nonetheless, making the first paragraph focusable and setting
                    the initial focus on it is the most broadly accessible option.
                </p><p>
                    This is just a demonstration. If it were a real application, it would
                    provide a message telling whether the entered address is valid.
                </p>
                <p>
                    For demonstration purposes, this dialog has a lot of text. It demonstrates a
                    scenario where:
                </p>
                
                <p>
                    There are several ways to resolve this issue:
                </p>
                
                <p>
                    Please
                    <em>
                        DO NOT
                    </em>
                    make the element with role dialog focusable!
                </p>
                
                <p>
                    In this dialog, the first paragraph has
                    
                    . The first
                    paragraph is also contained inside the element that provides the dialog description, i.e., the element that is referenced
                    by
                    
                    . With some screen readers, this may have one negative
                    but relatively insignificant side effect when the dialog opens -- the first paragraph
                    may be announced twice. Nonetheless, making the first paragraph focusable and setting
                    the initial focus on it is the most broadly accessible option.
                </p>
            </div>
            <div class="dialog_form_actions">
                <button id="modalLargeActionYes" onclick="closeDialog(this)" class="button primary-button by-keyboard">
                    Yes
                </button>
                <button id="modalLargeActionNo" onclick="closeDialog(this)" class="button secondary-button by-keyboard">
                    No
                </button>
            </div>
        </div>
        
    </div>
Medium Modal
<div role="dialog" id="dialog2" aria-labelledby="dialog2_label" aria-modal="true" class="hidden">
        
        <div class="modal-content">
            <button id="dialog2_label_closed" aria-label="Close modal" class="closebtn micro-buttons modal-close"></button>
            <h2 tabindex="-1" id="dialog2_label" class="dialog_label">
                Are you sure?
            </h2>
            <div id="dialog2_desc" class="dialog_desc">
                <p>
                    This is just a demonstration. If it were a real application, it would
                    provide a message telling whether the entered address is valid.
                </p>
                <p>
                    For demonstration purposes, this dialog has a lot of text. It demonstrates a
                    scenario where:
                </p>

                <p>
                    This is just a demonstration. If it were a real application, it would
                    provide a message telling whether the entered address is valid.
                </p>
                <p>
                    For demonstration purposes, this dialog has a lot of text. It demonstrates a
                    scenario where:
                </p>
                
            </div>
            <div class="dialog_form_actions">
                <button id="modalMediumActionYes" onclick="closeDialog(this)" class="button primary-button by-keyboard">
                    Yes
                </button>
                <button id="modalMediumActionNo" onclick="closeDialog(this)" class="button secondary-button by-keyboard">
                    No
                </button>
            </div>
        </div>
        
    </div>
Small Modal
<div role="dialog" id="dialog3" aria-labelledby="dialog3_label" aria-modal="true" class="hidden">
        
        <div class="modal-content">
            <button id="dialog3_label_closed" aria-label="Close modal" class="closebtn micro-buttons modal-close"></button>
            <h2 tabindex="-1" id="dialog3_label" class="dialog_label">
                Are you sure?
            </h2>
            <div id="dialog2_desc" class="dialog_desc">
                <p>
                    This is just a demonstration. If it were a real application, it would
                    provide a message telling whether the entered address is valid.
                </p>
            </div>
            <div class="dialog_form_actions">
                <button id="modalActionYes" onclick="closeDialog(this)" class="button primary-button by-keyboard">
                    Yes
                </button>
                <button id="modalActionNo" onclick="closeDialog(this)" class="button secondary-button by-keyboard">
                    No
                </button>
            </div>
        </div>
        
    </div>

Interaction

Modal windows help users focus on the task at hand and avoid actions they may not want to take. They also help users complete tasks related to the page they’re on, without having to take them to another page.

Positioning

Where the modal window appears plays a key role in capturing the user’s attention. It should only contain information that’s relevant to modal window’s objectives.

  • Header: The title of the modal.
  • Body: The modal window’s main content. It can include multiple UI elements that all strategically align with what we’re asking the user to do. Make sure it’s focused and succinct.
  • Dismiss “X” icon: Enables users to close the modal window. When users do this, changes (if any) won’t be saved.
  • Action: Contains a primary action and, in some cases, a secondary action.
  • Background: In some cases, the modal window will appear over a semi-transparent dark background that blocks out the rest of the page. If the user clicks on the dark background, the modal window should close and return the user to the full-page view. It’s possible to restrict the user from doing this, if the action in the modal window is mandatory.

If you find that your modal window is excessively big, consider a different design solution.

Reduce interruption

Use modal windows only when you need to because they force users to pause their current task and focus on modal window content.
  • Don’t use a modal window for a multi-step process.

Dismissing a modal window

Users can close a modal window by clicking the “X” symbol in the top right corner, clicking on the dark background or, in some cases, clicking on a secondary “Cancel” button. When needed, you can restrict the user’s ability to dismiss a modal window when an action is mandatory.

Scrollable content

Modal windows are independent of the underlying parent page, so users shouldn’t be able to scroll through page content when the modal window is open.

General guidelines

Positioning is where the modal window plays a key role in capturing the user’s attention. It should only contain information that’s relevant to the modal window’s objectives.

Don't include multiple steps or an overwhelming amount of information. If multiple steps are required, consider using the page to describe the information instead.

  Guidelines Examples
Recommended length 1 to 3 words for headings Edit item
Line wrap Avoid for headings Delivery confirmation
Phrasing Words or phrases Your session has expired
Case Sentence case Delivery estimates

Code Samples

Basic

Note that this component may require additional styling.

Angular

The MatDialog service can be used to open modal dialogs with Material Design styling and animations.

Note that this component may require additional styling.

Positioning

A modal window sits on top of the application, focusing the user on specific content or user input. The application is typically greyed out to help direct the user’s attention to it.

Best practices

  • Tabbing should be contained within the modal window, until the modal window is dismissed.
  • When a modal window is dismissed, the user should be taken back to the entry point.
  • Pressing the Escape key (ESC) on the keyboard or clicking out of the modal window should dismiss it.

Dos and don’ts

Heading

Include a brief title for the modal. Consider the relationship between the heading and primary call to action. Users scan and, in some cases, will only read this content.

  • Heading: Delete selected item
    Button: Delete
  • Heading: Email notifications
    Button: Delete all items

Action

Let users know what to do next by including a primary button and a secondary button. Button copy should be action-oriented and give the user an idea of what will happen when they click it.

  • Primary button: Return to profile
    Secondary button: Cancel
  • Primary button: Return
    Secondary button: Close

Accessibility considerations

Alt text

If the modal window has directional arrow images, or other images that help users navigate, write alt text for accessibility. The dismiss icon tells users to close the modal window. Write alt text for the X symbol.

Dismiss “X” icon

  • Close

Guidelines

Modal focus

When a modal is triggered, keyboard focus must immediately move into the modal. Focus can move to either the first interactive element or the top heading within the modal body.

If putting the focus on the first interactive element hides content at the top of the modal due to scrolling, then the focus should be set to the top heading of the modal – see the interactive component for an example.

Moving focus to the heading is a one-time focus. This is achieved by setting “tabindex” to -1 on the heading element and using JavaScript to move focus to it. Placing focus on the heading can exist without a visible focus ring.

When a modal is dismissed, visible focus must return to the triggering element. If the modal caused a change of context, such as deleting the trigger element or taking the user to another page, then the visible focus is set to the next element in the logical flow.

Focus halo

Modals have no focus halo of their own. Interactive controls inside the modal have a prominent focus outline when they are focused or hovered. The focus outline colour should always have a minimum contrast ratio with the immediate component outline (3:1).

Keyboard interaction

When a modal opens, keyboard focus moves inside the modal.

When an interactive element inside the modal has visible focus:

  • Tab:
    • Focus moves to the next interactive element inside the modal
    • If the focus is on the last interactive element inside the modal, moves focus to the first interactive element inside the modal
  • Shift + Tab:
    • Focus moves to the preceding interactive element inside the modal
    • If the focus is on the first interactive element inside the modal, moves focus to the last interactive element inside the modal
  • Esc: Closes the modal

Users should never be able to tab outside of the modal to other page content.

ARIA properties

Modals can have following ARIA properties:

  • The role of "dialog", set on the modal container element.
  • Aria-modal set to "True" on the modal container element.
  • The modal has an accessible name, set either by using aria-labelledby (the attribute refers to a visible heading inside the modal), or aria-label (the attribute takes a string name visible only to screen readers).

To make the page contents inert, set aria-hidden to "True" and tabindex to -1 on the non-modal body contents. Once the modal is dismissed, the “tabindex” property would be removed and the aria-hidden will become “false”.

Inert content and keyboard trap

When a modal is launched, the underlying page content becomes visually and semantically inert. The user cannot interact with the underlying content using a mouse click, keyboard tab, or screen reader shortcuts. The keyboard focus is trapped within the modal body as long as it is on the screen.

Modal trigger

The element triggering the modal always has the role of "button".

Testing

When testing a modal dialog, the tester must ensure:

  • The modal is fully keyboard operable
  • The modal dialog has the role of “dialog” and aria-modal set to "True"
  • The underlying page content becomes inert to mouse clicks, keyboard tab, and any screen reader shortcuts while the modal is on the screen
  • The keyboard focus is trapped within the modal body while the modal is visible
  • The modal trigger is a button
  • On-load focus is on the first interactive element in the modal, or on the main heading of the modal
  • Focus returns to the triggering element when the modal is dismissed, or on the next element in the logical flow if the triggering element no longer exists
  • The screen reader announces the modal role and the modal’s accessible name, which either refers to the main heading of the modal or is an invisible text set in the code

Related content