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

svelte-html-modal

v5.0.0

Published

Svelte modal component that utilizes the HTML dialog element

Readme

Svelte HTML Modal

Create modals using the <dialog> element.

See examples with custom transitions:

  • Centered, Bottom Sheet on Mobile (fly-up)
  • Navigation Drawer (slide-right[^slide-right])

[^slide-right]: Consider setting scrollbar-gutter: stable; on the HTML element to avoid layout shift during transition.

Features

Requires Svelte v5 and runes mode.

  • State Management: Open and close modals with a single $state(boolean)
  • Backdrop Control: Close the modal by clicking anywhere outside of it
  • Accessibility: Native <dialog> element with focus trap and Esc support
  • Event Handling: oncancel and onclose event handlers are supported
  • SSR Support: The modal can be opened(shown) before Svelte hydration
  • Browser Support: Works in 96.66% of browsers as of November, 2024

Quick Start

To upgrade from previous versions, see the migration guide.

pnpm add svelte-html-modal -D
npm i svelte-html-modal -D
/* Add to your global CSS file (e.g. src/routes/layout.css) */
/* For Tailwind v4 users, place it inside `@layer base` */
/* See https://tailwindcss.com/docs/adding-custom-styles */
body:has(dialog:modal) {
  overflow: hidden;
  touch-action: none;
}
<!-- See src/routes/docs/+page.svelte -->

<script>
  import { Modal } from 'svelte-html-modal';

  // Client-side JavaScript is required to display the modal.
  // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/showModal
  let isOpen = $state(false);

  const open = () => (isOpen = true);
  const close = () => (isOpen = false);
</script>

<button type="button" onclick={open}>Open Modal</button>

<!-- The wrapper <div> is used for styling. -->
<!-- See the <style> element below. -->
<div class="modal-wrapper">
  <Modal bind:isOpen closeOnBackdropClick={true} closeOnEscapeKey={true}>
    <strong>Close the Modal</strong>
    <ul>
      <li>Click on the backdrop</li>
      <li>Press the <kbd>Esc</kbd> key</li>
      <li>
        <button type="button" onclick={close}>JavaScript Button</button>
      </li>
      <li>
        <!-- See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#method -->
        <form method="dialog">
          <button>Submit Button</button>
        </form>
      </li>
    </ul>
  </Modal>
</div>

<!-- Vanilla CSS -->
<style lang="postcss">
  /* Style <dialog> within the .modal-wrapper element. */
  /* See https://svelte.dev/docs/svelte/scoped-styles */
  .modal-wrapper :global {
    > dialog {
      width: 20rem;
      padding: 1rem;
      border-radius: 0.375rem;
      &:modal {
        overscroll-behavior: contain;
      }
      &::backdrop {
        backdrop-filter: blur(8px) brightness(0.5);
      }
    }
  }
</style>

Tailwind CSS v4 class names can be used as well:

<Modal
  class="m-auto w-80 rounded-md p-4 backdrop:backdrop-blur backdrop:backdrop-brightness-50 open:overscroll-contain"
></Modal>

[!NOTE]
For fullscreen modal, override max-size values:

dialog {
  /* Override user-agent dialog:modal max-sizes. */
  max-height: 100%; /* calc((100% - 6px) - 2em); */
  max-width: 100%; /* calc((100% - 6px) - 2em); */
}

Default Options

{
  "closeOnBackdropClick": false,
  "closeOnEscapeKey": true
}

Component Props

type Props = {
  dialog?: HTMLDialogElement | undefined; // bindable
  isOpen: boolean; // bindable
  closeOnBackdropClick?: boolean | undefined;
  closeOnEscapeKey?: boolean | undefined;
  class?: HTMLDialogAttributes['class'] | undefined;
  children?: Snippet | undefined;
} & Partial<Pick<HTMLDialogAttributes, 'id' | 'oncancel' | 'onclose'>>;

[!IMPORTANT]
The closeOnEscapeKey prop has a known issue in Chrome 126~133. The modal can be closed by pressing the Esc key twice. This will be resolved in a future update when the closedby attribute is implemented. Learn more