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

@versini/ui-dialog

v11.0.2

Published

[![npm version](https://img.shields.io/npm/v/@versini/ui-dialog?style=flat-square)](https://www.npmjs.com/package/@versini/ui-dialog) ![npm package minimized gzipped size](<https://img.shields.io/bundlejs/size/%40versini%2Fui-dialog?style=flat-square&labe

Readme

@versini/ui-dialog

npm version npm package minimized gzipped size

A lightweight and accessible React dialog component built with TypeScript and TailwindCSS.

The Dialog component is a minimal modal container leveraging the native HTML <dialog> element. It provides an efficient alternative to heavier modal libraries with built-in accessibility, focus management, and animation support.

Table of Contents

Features

  • ⚡ Lightweight: Uses native HTML <dialog> element for minimal overhead
  • ♿ Accessible: WCAG compliant with built-in focus management and ARIA support
  • 🎨 Flexible Layout: Two layout kinds (panel and messagebox) to suit different use cases
  • ✨ Animated: Optional slide or fade animations for opening/closing
  • 🎭 Theme Support: Multiple border modes and blur effects
  • 🌲 Tree-shakeable: Optimized for bundle size
  • 🔧 TypeScript: Fully typed with comprehensive prop definitions
  • 🎯 Focus Management: Intelligent initial focus handling with customizable options

Installation

npm install @versini/ui-dialog

Note: This component requires TailwindCSS and the @versini/ui-styles plugin for proper styling. See the installation documentation for complete setup instructions.

Usage

Basic Dialog

import { useState } from "react";
import { Dialog } from "@versini/ui-dialog";

function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Dialog</button>
      <Dialog
        open={open}
        onOpenChange={setOpen}
        title="Welcome"
      >
        <p>This is a simple dialog content.</p>
      </Dialog>
    </>
  );
}

Dialog with Footer

import { useState } from "react";
import { Dialog } from "@versini/ui-dialog";
import { Button } from "@versini/ui-button";

function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Dialog</button>
      <Dialog
        open={open}
        onOpenChange={setOpen}
        title="Confirm Action"
        footer={
          <div className="flex gap-2 justify-end">
            <Button onClick={() => setOpen(false)}>Cancel</Button>
            <Button variant="primary" onClick={() => setOpen(false)}>Confirm</Button>
          </div>
        }
      >
        <p>Are you sure you want to proceed?</p>
      </Dialog>
    </>
  );
}

Dialog with Animation

import { useState } from "react";
import { Dialog } from "@versini/ui-dialog";

function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Dialog</button>
      <Dialog
        open={open}
        onOpenChange={setOpen}
        title="Animated Dialog"
        animation
        animationType="fade"
      >
        <p>This dialog slides in with a fade animation.</p>
      </Dialog>
    </>
  );
}

Messagebox Layout

import { useState } from "react";
import { Dialog } from "@versini/ui-dialog";

function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Messagebox</button>
      <Dialog
        open={open}
        onOpenChange={setOpen}
        title="Important Message"
        kind="messagebox"
      >
        <p>This uses the messagebox layout for centered, compact dialogs.</p>
      </Dialog>
    </>
  );
}

Custom Focus Management

import { useRef, useState } from "react";
import { Dialog } from "@versini/ui-dialog";

function App() {
  const [open, setOpen] = useState(false);
  const submitButtonRef = useRef<HTMLButtonElement>(null);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Dialog</button>
      <Dialog
        open={open}
        onOpenChange={setOpen}
        title="Focus Management"
        initialFocus={submitButtonRef}
      >
        <input type="text" placeholder="This is skipped" />
        <button ref={submitButtonRef}>This gets focus</button>
      </Dialog>
    </>
  );
}

API

Dialog Props

| Prop | Type | Default | Description | | ----------------- | ----------------------------------------------------------- | ------------ | ----------------------------------------------------------------------------------------------- | | open | boolean | - | Controls whether the dialog is visible | | onOpenChange | (open: boolean) => void | - | Callback fired when the dialog should open or close | | title | string | - | The title displayed in the dialog header | | children | React.ReactNode | - | The main content of the dialog | | footer | React.ReactNode | - | Optional footer content, typically containing action buttons | | kind | "panel" \| "messagebox" | "panel" | Layout type (panel for general content, messagebox for centered alerts) | | borderMode | "dark" \| "medium" \| "light" | "light" | Border styling mode | | animation | boolean | false | Enable animations for opening/closing | | animationType | "slide" \| "fade" | "slide" | Animation style (only used when animation is true) | | maxWidth | "small" \| "medium" \| "large" | "medium" | Maximum width for panel layout (does not affect messagebox) | | maxHeight | "small" \| "medium" \| "large" | - | Maximum height (large for panel, small for messagebox) | | blurEffect | "none" \| "small" \| "medium" \| "large" | "none" | Blur effect for header and footer backgrounds | | initialFocus | number \| React.RefObject<HTMLElement \| null> \| -1 | 0 | Element to focus on open: number = tabbable index, ref = element, -1 = no focus | | className | string | - | CSS class(es) to add to the dialog element |

Examples

Responsive Dialog

import { useState } from "react";
import { Dialog } from "@versini/ui-dialog";

function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Dialog</button>
      <Dialog
        open={open}
        onOpenChange={setOpen}
        title="Responsive Dialog"
        maxWidth="large"
        maxHeight="medium"
      >
        <p>This dialog adapts to different screen sizes.</p>
      </Dialog>
    </>
  );
}

Dialog with Blur Effect

import { useState } from "react";
import { Dialog } from "@versini/ui-dialog";

function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Dialog</button>
      <Dialog
        open={open}
        onOpenChange={setOpen}
        title="Dialog with Blur"
        blurEffect="medium"
      >
        <p>The header and footer have a blur effect applied.</p>
      </Dialog>
    </>
  );
}

Custom Styling

import { useState } from "react";
import { Dialog } from "@versini/ui-dialog";

function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Dialog</button>
      <Dialog
        open={open}
        onOpenChange={setOpen}
        title="Styled Dialog"
        className="rounded-lg shadow-2xl"
        borderMode="dark"
      >
        <p>Custom styling applied to the dialog.</p>
      </Dialog>
    </>
  );
}

Accessibility

import { useState } from "react";
import { Dialog } from "@versini/ui-dialog";

function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Dialog</button>
      <Dialog
        open={open}
        onOpenChange={setOpen}
        title="Accessible Dialog"
        initialFocus={0}
      >
        <p>The first interactive element receives focus automatically.</p>
        <input type="text" placeholder="Focus is managed for you" />
      </Dialog>
    </>
  );
}