npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@georapbox/modal-element

v1.8.0

Published

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

Downloads

66

Readme

npm version npm license

<modal-element>

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

API documentationDemo

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

| Name | Reflects | Type | Required | Default | Description | | ---- | -------- | ---- | -------- | ------- | ----------- | | open | ✓ | Boolean | - | false | Determines 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-backdrop | ✓ | Boolean | - | false | Determines whether the modal should be closed when the user clicks outside the modal or not. | | noHeaderno-header | ✓ | Boolean | - | false | Determines 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-animations1 | ✓ | Boolean | - | false | Determines 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-button | ✓ | Boolean | - | false | Determines 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. | | fullscreen | ✓ | Boolean | - | false | Determines 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-overflow | ✓ | Boolean | - | false | Determines 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. | | placement | ✓ | String | - | center | Determines 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-label | ✓ | String | - | Close | The 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

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

CSS Parts

| Name | Description | | ---- | ----------- | | base | The componen'ts base wrapper. In this case this is the native <dialog> element. | | panel | The modal's panel element where the all the content is rendered. | | header | The modal's header element. It wraps the modal's title and close button. | | title | The modal's title wrapper element. | | close | The default close button rendered in the modal's header. | | close-icon | The default close button's icon. | | body | The modal's body element, where all main content is rendered. | | footer | The modal's footer element. |

CSS Custom Properties

| Name | Description | Default | | ---- | ----------- | ------- | | --me-width | The 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-height | The 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-color | The modal's border color. | initial | | --me-border-style | The modal's border style. | solid | | --me-border-width | The modal's border width. | initial | | --me-border-radius | The modal's border radius. | 0 | | --me-box-shadow | The modal's box shadow. | none | | --me-background-color | The modal's background color. | canvas | | --me-color | The modal's foreground color. | canvastext | | --me-header-spacing | The amount of spacing (padding) to use for the header element. | 1rem | | --me-header-background-color | The header's background color. | transparent | | --me-header-color | The header's foreground color. | initial | | --me-body-spacing | The amount of spacing (padding) to use for the body element. | 1rem | | --me-body-background-color | The body's background color. | transparent | | --me-body-color | The body's foreground color. | initial | | --me-footer-spacing | The amount of spacing (padding) to use for the footer element. | 1rem | | --me-footer-background-color | The footer's background color. | transparent | | --me-footer-color | The footer's foreground color. | initial | | --me-close-padding | The padding of the default close button. | 0.4375rem | | --me-close-border | The border shorthand property of the default close button. | none | | --me-close-border-radius | The border radius shorthand property of the default close button. | 0 | | --me-close-background-color | The background color of the default close button. | transparent | | --me-close-color | The foreground color of the default close button. | inherit | | --me-close-font-size | The font size of the default close button. | 1rem | | --me-backdrop-background1 | The 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-filter1 | The 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

| Name | Description | Event Detail | | ---- | ----------- | ------------ | | me-open | Emitted when the modal opens. | { element: HTMLElement } | | me-close | Emitted 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-close | Emitted 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' \| 'external-invoker' } |

Methods

| Name | Type | Description | Arguments | | ---- | ---- | ----------- | --------- | | defineCustomElement | Static | Defines/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' | | show1 | Instance | Opens the modal. | - | | hide1 | Instance | Closes 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 v1.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.

Hopefully, in the future we are going to have more declarative ways to handle these kinds of scenarions natively with Invokers, but for now, this is a simple way to achieve the same result.

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.

Note: As of v1.7.0, by clicking on the custom close button, the me-request-close event will also be emitted with the reason set to 'external-invoker' and therefore the user can prevent the modal from being dismissed by calling event.preventDefault() in the event listener if needed.

Changelog

For API updates and breaking changes, check the CHANGELOG.

Development setup

Prerequisites

The project requires Node.js and npm to be installed on your environment. Preferrably, use nvm Node Version Manager and use the version of Node.js specified in the .nvmrc file by running nvm use.

Install dependencies

Install the project dependencies by running the following command.

npm install

Build for development

Watch for changes and start a development server by running the following command.

npm start

Linting

Lint the code by running the following command.

npm run lint

Testing

Run the tests by running any of the following commands.

npm test
npm run test:watch # watch mode

Build for production

Create a production build by running the following command.

npm run build

License

The MIT License (MIT)