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 🙏

© 2026 – Pkg Stats / Ryan Hefner

jb-modal

v1.13.1

Published

modal web component

Readme

jb-modal

Published on webcomponents.org GitHub license NPM Version GitHub Created At

Responsive modal web component.

Benefits:

  • Responsive, opens as a centered dialog on desktop and a bottom sheet on mobile devices.
  • Framework free, so you can use it anywhere.
  • Customizable content and style.
  • Pre-styled header and footer slots.
  • TypeScript support.
  • Optional auto close on background click.
  • Optional route history with browser back handling.
  • Keeps modal open after page refresh when you provide an id.

When to use

Use jb-modal for temporary blocking UI such as confirmations, forms, detail views, and mobile bottom sheets.

Use an inline panel or page route when the content should remain part of the normal document flow or needs a shareable full-page URL.

Demo

Using With JS Frameworks

Installation

npm i jb-modal
import 'jb-modal';
<jb-modal>
  <div>Modal content</div>
</jb-modal>

API reference

Attributes

| name | type | default | description | | --- | --- | --- | --- | | is-open | boolean | false | Opens the modal when set to "true". Any other value closes it. | | id | string | "" | Modal id used for URL hash state. |

Properties

| name | type | readonly | description | | --- | --- | --- | --- | | isOpen | boolean | yes | Current isOpen state. | | id | string | no | Modal id used for URL hash state. See the Hash Id Storybook docs. | | config | { autoCloseOnBackgroundClick: boolean } | no | Runtime configuration. |

Methods

| name | returns | description | | --- | --- | --- | | open() | void | Opens the modal, sets ariaHidden to false, and pushes #id to browser history when id is set. | | close() | void | Closes the modal, sets ariaHidden to true, and navigates back when the current URL hash matches the modal id. |

Events

| event | detail | description | | --- | --- | --- | | load | none | Dispatched from connectedCallback before initialization. | | init | none | Dispatched from connectedCallback after initialization. | | urlOpen | none | Dispatched when the modal opens itself because the current URL hash matches its id. | | close | { eventType } | Dispatched for background click and browser-back close attempts. |

close event event.detail.eventType can be:

| value | meaning | | --- | --- | | BACKGROUND_CLICK | The backdrop was clicked. | | HISTORY_BACK_EVENT | Browser back/popstate was received while the modal was open. | | CLOSE_BUTTON_CLICK | Reserved close type for close button flows. |

isOpen and close

const modal = document.querySelector('jb-modal');

modal.open();
modal.close();
console.log(modal.isOpen);
<jb-modal is-open="true">
  <div>Modal content</div>
</jb-modal>

Slots

Use the default slot for simple content or named slots for structured modal sections.

<jb-modal>
  <div slot="header">Modal header</div>
  <div slot="content">Modal content</div>
  <div slot="footer">
    <jb-button>Done</jb-button>
  </div>
</jb-modal>

| slot | description | | --- | --- | | default | Modal content rendered as the fallback of the content slot. | | header | Header area at the top of the content box. | | content | Main scrollable modal content area. | | footer | Footer area at the bottom of the content box. |

Background click

The component always dispatches close with eventType: "BACKGROUND_CLICK" when the backdrop is clicked. It only closes automatically when config.autoCloseOnBackgroundClick is true.

const modal = document.querySelector('jb-modal');

modal.config.autoCloseOnBackgroundClick = true;

modal.addEventListener('close', (event) => {
  if (event.detail.eventType === 'BACKGROUND_CLICK') {
    console.log('Backdrop clicked');
  }
});

URL hash state

Set id when the modal should update the URL hash while isOpen is true. When open() runs, the modal pushes #id to browser history. If the page loads with the same hash, the modal opens itself and dispatches urlOpen.

Demo: Hash Id Storybook docs. To test the real browser hash and back-button behavior, open the isolated hash demo in a new window.

<jb-modal id="profile-modal">
  <div slot="content">Profile</div>
</jb-modal>
const modal = document.querySelector('#profile-modal');

modal.addEventListener('urlOpen', () => {
  console.log('Opened from URL hash');
});

Browser back dispatches a close event with eventType: "HISTORY_BACK_EVENT". In the current implementation, browser-back auto close uses the same config.autoCloseOnBackgroundClick flag.

CSS parts and custom style

| part | description | | --- | --- | | background | The modal backdrop/background. | | content-box | The modal content box that contains header, content, and footer slots. | | component-wrapper | div that wrap whole component |

| CSS variable name | description | | --- | --- | | --jb-modal-bg-color | Modal content background color. | | --jb-modal-back-bg-color | Modal backdrop background color. | | --jb-modal-border-radius | Modal content border radius. | | --jb-modal-z-index | Modal z-index. |

jb-modal::part(content-box) {
  min-width: 320px;
}

jb-modal {
  --jb-modal-border-radius: 16px;
  --jb-modal-z-index: 1000;
}

Animation

jb-modal does not ship with a default desktop open or close animation. Modal animation is usually tied to each project's visual language, motion duration, easing, and interaction style, so the component keeps the behavior simple and lets you add animation from your own CSS.

You can animate each exposed part independently. For example, fade the background, scale or slide the content-box, or use different durations for each part.

@media (min-width: 769px) {
  .profile-modal::part(background) {
    opacity: 1;
    transition: opacity 300ms ease;
  }

  .profile-modal::part(content-box) {
    opacity: 1;
    transform: translateY(0) scale(1);
    transition:
      opacity 300ms ease,
      transform 300ms cubic-bezier(0.16, 1, 0.3, 1);
  }

  .profile-modal:state(open)::part(background) {
    @starting-style {
      opacity: 0;
    }
  }

  .profile-modal:state(open)::part(content-box) {
    @starting-style {
      opacity: 0;
      transform: translateY(1rem) scale(0.96);
    }
  }
}

For close animations, include a discrete display transition on the modal host so the element remains rendered while its parts animate back to their closed styles.

See the Animation Storybook docs for open-only and open-close examples.

Accessibility notes

  • The component attaches ElementInternals and sets ariaModal to true.
  • ariaHidden is set to false when opened and true when closed.

Related Docs

AI agent notes

  • Import jb-modal once before using <jb-modal>.
  • Use open() and close() for imperative control; there is no public open property setter.
  • Use is-open="true" only for initial isOpen markup state.
  • Use config.autoCloseOnBackgroundClick = true when backdrop clicks should close the modal.
  • Listen to close and inspect event.detail.eventType to know why close was requested.
  • Use id only when URL hash/history integration is desired.
  • This package includes custom-elements.json and points to it with the package.json customElements field. The field is documented by the Custom Elements Manifest project in Referencing manifests from npm packages.
  • In custom-elements.json, exports.kind: "js" describes JavaScript/TypeScript exports and exports.kind: "custom-element-definition" maps the jb-modal tag name to JBModalWebComponent.