Skip to main content
New tool CRON Expression Builder — preview next run times before you schedule Apex. Open the builder →
Screenshot showing a custom LWC modal popup component overlaying a Salesforce record page.
LWC

LWC Modal: How to Build a Reusable Salesforce Modal Popup

Build a reusable LWC modal in Salesforce — markup, CSS, parent-child events, focus trap, and the LightningModal base class for the modern, accessible pattern.

Modal popups are a powerful tool in user interface design, providing a focused and controlled way to display information or collect user input. In Salesforce's apex-cursors-lwc-expressions/" class="auto-link">Lightning Web Components (LWC), you can easily create modal popups that integrate seamlessly with your application's UI. In this blog post, we will provide a step-by-step guide on how to create a modal popup in LWC Salesforce.

How to Create Modal Popups in LWC Salesforce: A Step-by-Step Guide

Step 1: Create a New LWC Component

The first step is to create a new LWC component. This can be done by navigating to the LWC component's folder in your Salesforce org and clicking the "New" button. Give your component a name and click "Submit".

Step 2: Import the Required Modules

In order to create a modal popup, you will need to import the required modules in your LWC component's JavaScript file. The two modules required are LightningElement and track. Add the following lines of code to your JavaScript file to import the modules:

import { LightningElement, track } from 'lwc';

Step 3: Define the Modal Content

The next step is to define the content that will be displayed in the modal popup. This can be done by creating an HTML template within your LWC component's file. Here is an example of what the HTML code might look like:

<template>
  <template if:true={isModalOpen}>
    <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
      <div class="slds-modal__container">
        <header class="slds-modal__header">
          <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Modal Header</h2>
        </header>
        <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
          Modal Content
        </div>
        <footer class="slds-modal__footer">
          <lightning-button label="Cancel" onclick={closeModal}></lightning-button>
          <lightning-button label="Save" variant="brand" onclick={saveModal}></lightning-button>
        </footer>
      </div>
    </section>
    <div class="slds-backdrop slds-backdrop_open"></div>
  </template>
</template>

Step 4: Define the Event Handlers

In order to show and hide the modal popup, you will need to define event handlers. These event handlers will be triggered by user actions, such as clicking a button. Here is an example of what the JavaScript code might look like to define the event handlers:

export default class MyComponent extends LightningElement {
  @track isModalOpen = false;

  showModal() {
    this.isModalOpen = true;
  }

  hideModal() {
    this.isModalOpen = false;
  }
}

The @track decorator is used to ensure that the isModalOpen property is tracked and updated in the UI when its value changes. The showModal() and hideModal() methods are called to show and hide the modal popup, respectively.

Step 5: Trigger the Modal Popup

The final step is to trigger the modal popup by adding a button or other UI element that will call the event handlers defined in Step 4. Here is an example of what the HTML code might look like:

<template>
  <lightning-button label="Open Modal" onclick={openModal}></lightning-button>
  <template if:true={isModalOpen}>
    <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
      <div class="slds-modal__container">
        <header class="slds-modal__header">
          <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Modal Header</h2>
        </header>
        <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
          Modal Content
        </div>
        <footer class="slds-modal__footer">
          <lightning-button label="Cancel" onclick={closeModal}></lightning-button>
          <lightning-button label="Save" variant="brand" onclick={saveModal}></lightning-button>
        </footer>
      </div>
    </section>
    <div class="slds-backdrop slds-backdrop_open"></div>
  </template>
</template>

In this example, a button is added to the component that triggers the showModal() event handler when clicked. The modal popup is displayed when the isModalOpen property is set to true, and the hideModal() event handler is triggered when the "Close" button in the modal popup is clicked.

Conclusion

Modal popups are an important tool in user interface design, and can greatly enhance the user experience of your Salesforce application. In this blog post, we provided a step-by-step guide on how to create a modal popup in LWC Salesforce. By following these steps, you can easily integrate modal popups into your application's UI and improve its functionality.

Frequently asked questions

What is an LWC modal?

An LWC modal is a Lightning Web Component that displays a dialog box layered over the rest of the page, blocking interaction with content behind it until the user closes it. It's used for confirmations, forms, and detail views. Modern Salesforce orgs (Winter '23+) should extend the LightningModal base class for built-in accessibility, focus management, and SLDS styling.

How do you create a modal in LWC?

Two patterns: (1) Custom modal — a child component with conditional template rendering, slds-modal CSS classes, and parent-child events for open/close. (2) Modern: extend LightningModal from 'lightning/modal', which gives you headers, footers, focus trap, and ARIA out of the box. The modern pattern requires Spring '23+ and is the official Salesforce recommendation.

How do I close an LWC modal from a child component?

Dispatch a CustomEvent named 'close' from the child: this.dispatchEvent(new CustomEvent('close')). The parent listens with @event onclose={handleClose} and toggles a tracked boolean that controls the modal's visibility via if:true. With LightningModal, call this.close('ok') from inside the modal — the parent receives the result via await modal.open().

What CSS classes does an LWC modal need?

Three SLDS classes are the foundation: slds-modal (positioning), slds-modal__container (the box), and slds-backdrop (the dark overlay). Add slds-fade-in-open and slds-fade-in--open to the modal and backdrop respectively to make them visible. SLDS handles z-index and centering automatically when those classes are applied.

Can an LWC modal be reusable across multiple components?

Yes — that's the recommended approach. Build the modal as a standalone child component (e.g., c-confirm-modal) that exposes @api properties like header and message, dispatches close/confirm events, and is included via <c-confirm-modal> in any parent. With LightningModal, the same modal component can be opened programmatically from any LWC via import { open } from 'lightning/modal'.

How do I prevent body scroll when an LWC modal is open?

LightningModal handles this automatically. For a custom modal, toggle a CSS class on document.body when the modal opens: document.body.classList.add('slds-modal-open'). Pair this with overflow: hidden in your CSS. Remember to remove the class on close — failing to clean up is a common bug that breaks the page after the modal disappears.

Is LightningModal better than building a custom LWC modal?

For new orgs on Spring '23+, yes. LightningModal handles ARIA roles, focus trap, ESC-to-close, and SLDS styling — features that take 100+ lines of code to implement correctly in a custom modal. Use a custom modal only when you need a unique visual treatment that LightningModal can't accommodate, or when supporting older API versions.

Newsletter

One email every Tuesday

New guides, tool updates, and the release-note changes that break things.

No spam. Unsubscribe in one click.

Comments

Loading comments...

Leave a Comment