1.6.1 • Published 18 days ago

@georapbox/modal-element v1.6.1

Weekly downloads
-
License
MIT
Repository
github
Last release
18 days ago

npm version npm license

<modal-element>

A custom element to create a modal, using the native <dialog> element under the hood.

API documentation Demo

Install

$ npm install --save @georapbox/modal-element

Usage

Script

import { ModalElement } from './node_modules/@georapbox/modal-element/dist/modal-element.js';

// Manually define the element.
ModalElement.defineCustomElement();

Alternatively, you can import the automatically defined custom element.

import './node_modules/@georapbox/modal-element/dist/modal-element-defined.js';

Markup

<modal-element>
  <h1 slot="header">Modal Title</h1>
  <p>Modal content</p>
  <div slot="footer">Modal footer</div>
</modal-element>

Style

By default, the component comes with minimal styling to remain as less opinionated as possible. However, you can style the various elements of the component using the available CSS Parts or by overriding the default CSS Custom Properties. A working example of styling the component can be found here.

API

Properties

NameReflectsTypeRequiredDefaultDescription
openBoolean-falseDetermines whether the modal is open or not.NOTE: If you create a modal-element programmatically via document.createElement('modal-element'), you need to append it to the DOM before setting this property to true. Otherwise, you will get an error like this: Uncaught DOMException: Failed to execute 'showModal' on 'HTMLDialogElement': The element is not in a Document. This is because the native showModal method of the HTMLDialogElement requires the element to be in the DOM before it can be called.
staticBackdropstatic-backdropBoolean-falseDetermines whether the modal should be closed when the user clicks outside the modal or not.
noHeaderno-headerBoolean-falseDetermines whether the modal should have a header or not. Note, that if the modal has no header, the default close button will not be visible as well, therefore you probably need to provide an accessible way for users to dismiss the modal.
noAnimationsno-animations1Boolean-falseDetermines whether the modal should have animations or not. Animations include the modal's entrance and exit animations, as well as the static backdrop's bounce effect when users clicks on it.
noCloseButtonno-close-buttonBoolean-falseDetermines whether the modal should have a default close button or not. If the modal has no close button, you probably need to provide an accessible way for users to dismiss the modal.
fullscreenBoolean-falseDetermines whether the modal should be displayed in fullscreen or not. Note, the --me-width and --me-height CSS custom properties will be overriden if this property is set to true. Notice that the backdrop is not visible in fullscreen mode. If you still want a full-width modal with a backdrop, you can use --me-width: 100%; and --me-height: 100%; instead.
preserveOverflowpreserve-overflowBoolean-falseDetermines whether the modal should preserve the document's overflow when the modal is open. If this property is set to true, the document's overflow will not be hidden when the modal is open.
placementString-centerDetermines the placement of the modal. Possible values are 'top-start', 'top-center', 'top-end', 'center-start', 'center', 'center-end', 'bottom-start', 'bottom-center', 'bottom-end'. Placement respects the direction of the document, eg if the document is in RTL mode, the placement will be mirrored accordingly. Note, that the placement is not applied when the modal is in fullscreen mode and it might not be visible in some cases when the modal is too large for the viewport, eg in small viewports.
closeLabelclose-labelString-CloseThe label for the default close button that resides in the modal's header. It is used as the aria-label attribute of the close button. If user provides text content for the close button using the close slot, this property is ignored and the aria-label attribute is removed.

All of the above properties reflect their values as HTML attributes to keep the element's DOM representation in sync with its JavaScript state.

1 A note for animations: The entry/exit animations of the modal are implemented using the @starting-style CSS at-rule, which is a relatively new feature and currently only supported in Chromium-based browsers. Here is an interesting article for more information about the feature. As a fallback, the modal will be rendered without animations in browsers that do not support this feature. Also, keep in mind that if the user has reduced motion enabled in their operating system, the animations will be disabled as well, even if they are supported by the browser.

Slots

NameDescription
(default/unnamed)The modal's main content.
headerThe modal's header content, usually a title.
footerThe modals' footer content. Usually used for buttons or other actions.
closeThe content of the close button that appears in the modal's header.

CSS Parts

NameDescription
baseThe componen'ts base wrapper. In this case this is the native <dialog> element.
panelThe modal's panel element where the all the content is rendered.
headerThe modal's header element. It wraps the modal's title and close button.
titleThe modal's title wrapper element.
closeThe default close button rendered in the modal's header.
bodyThe modal's body element, where all main content is rendered.
footerThe modal's footer element.

CSS Custom Properties

NameDescriptionDefault
--me-widthThe preferred width of the modal. If this width is larger than the viewport, the modal's width will adjust to fit the viewport.32rem
--me-heightThe preferred height of the modal. If this height is larger than the viewport, the modal's height will adjust to fit the viewport.fit-content
--me-border-colorThe modal's border color.initial
--me-border-styleThe modal's border style.solid
--me-border-widthThe modal's border width.initial
--me-border-radiusThe modal's border radius.0
--me-box-shadowThe modal's box shadow.none
--me-background-colorThe modal's background color.canvas
--me-header-spacingThe amount of spacing (padding) to use for the header element.1rem
--me-body-spacingThe amount of spacing (padding) to use for the body element.1rem
--me-footer-spacingThe amount of spacing (padding) to use for the footer element.1rem
--me-header-background-colorThe header's background color.transparent
--me-body-background-colorThe body's background color.transparent
--me-footer-background-colorThe footer's background color.transparent
--me-backdrop-background1The backdrop's background shorthand property. It can be used to set the backdrop's background color, gradient, or image.rgba(0, 0, 0, 0.5)
--me-backdrop-filter1The backdrop's filter property. It can be used to set the backdrop's filter effects like blur, brightness, contrast, etc.none

1 At the time of writing, the ::backdrop pseudo-element (which is used under the hood) does not inherit from originating element per the specification. This means that the backdrop's CSS custom properties cannot be inherited from the modal's CSS custom properties. Fortunately, this is a known issue and it is being worked on by browser vendors and the CSS working group. Currently, it's already fixed in Firefox Nightly 120+ and Chromium Canary 121+. For more details, check the browser reported bugs below:

Events

NameDescriptionEvent Detail
me-openEmitted when the modal opens.{ element: HTMLElement }
me-closeEmitted when the modal is dismissed in any way, either by clicking on the close button, by pressing the Esc key or by clicking outside the modal.{ element: HTMLElement }
me-request-closeEmitted when the modal is about to be dismissed. This event is cancellable, hence you can prevent the modal from being dismissed by calling event.preventDefault(). This can be useful when you want to prevent users from dismissing the modal until they have completed a certain task, eg submitting a form. In the event.detail object you can find the reason why the modal is about to be dismissed. You can use the reason to determine whether the modal should be dismissed or not as demonstrated in this example. Note, that this event is not emitted if the modal is dismissed by an external event, eg by calling the hide method or by setting the open property to false manually.{ element: HTMLElement, reason: 'close-button' \| 'escape-key' \| 'backdrop-click' }

Methods

NameTypeDescriptionArguments
defineCustomElementStaticDefines/registers the custom element with the name provided. If no name is provided, the default name is used. The method checks if the element is already defined, hence will skip trying to redefine it.elementName='modal-element'
show1InstanceOpens the modal.-
hide1InstanceCloses the modal.-

1 These methods are only available after the component has been defined. To ensure the component is defined, you can use whenDefined method of the CustomElementRegistry interface, eg customElements.whenDefined('modal-element').then(() => { /* call methods here */ });

Closing mechanisms

The modal provides some default ways for the end user to dismiss the modal. These are:

  • By clicking on the default close button in the modal's header.
  • By pressing the Esc key.
  • By clicking outside the modal if the staticBackdrop property is set to false.

These default mechanisms are enough for most use cases. However, sometimes developers want to provide extra mechanisms for modal closure. The most usual scenario is to provide a "Close" button on the modal's footer or a "Cancel" button for modals that act as confirmation prompts. To achieve this the developer would need to add the button and then add a click event listener to it to dismiss the modal. This is a common pattern and it works well. However, it can be a bit cumbersome to do this for every modal, especially if the developer is using the modal in a lot of places. Therefore, as of version 1.5.0, the modal provides an automatic way to dismiss the modal by clicking on a button or a link inside the modal's content with the data-me-close attribute. This is a convenient way to dismiss the modal without the need to add a click event listener to the element. Here is an example:

<modal-element>
  <h5 slot="header">Modal Title</h5>
  <p>Modal content</p>
  <button slot="footer" type="button" data-me-close>Close</button>
</modal-element>

By just adding the data-me-close attribute to the button, the modal will be dismissed when the button is clicked.

Please note though, that by clicking on the custom close button, the me-request-close event will not be emitted. This event is only triggered when the modal is about to be dismissed by the default closing mechanisms mentioned above.

Changelog

For API updates and breaking changes, check the CHANGELOG.

License

The MIT License (MIT)

1.6.1

18 days ago

1.6.0

2 months ago

1.5.0

3 months ago

1.4.0

3 months ago

1.3.0

3 months ago

1.2.1

6 months ago

1.2.0

6 months ago

1.1.0

6 months ago

1.0.1

6 months ago

1.0.0

6 months ago