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

nice-use-modal

v2.1.0

Published

A React modal hook

Downloads

145

Readme

nice-use-modal

license MIT npm downloads

Docs

Introduction

A powerful React modal hook with TypeScript support that makes managing modals and drawers simple and type-safe.

✨ What's New in v2.0

  • 🎯 Enhanced TypeScript Support: Complete type safety with better inference
  • 🏗️ Improved Build System: Migrated from Vite to tsup for better compatibility
  • 🚀 Performance Optimizations: Better memoization and reduced re-renders
  • 📦 Smaller Bundle Size: Optimized build output
  • 🔧 Better API Design: More consistent and intuitive API
  • 🐛 Bug Fixes: Resolved edge cases and improved stability

Features

  • 🎯 Type-safe: Full TypeScript support with strict typing
  • 🚀 No UI Dependency: Works with any UI library (Ant Design, Material-UI, etc.)
  • 🔄 No Side Effects: Uses React Context to maintain clean state management
  • 🎨 Flexible: Use as hooks or call imperatively
  • 🧹 Auto Cleanup: Internal state automatically resets when modal closes
  • 📦 Lightweight: Minimal dependencies and small bundle size

Installation

# npm
npm install nice-use-modal

# pnpm
pnpm add nice-use-modal

# yarn
yarn add nice-use-modal

Quick Start

1. Setup Provider

Wrap your app with ModalProvider:

main.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import { ModalProvider } from 'nice-use-modal';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <ModalProvider>
      <App />
    </ModalProvider>
  </React.StrictMode>
);

2. Create Modal Component

MyModal.tsx

import React, { useEffect } from 'react';
import { Modal, message } from 'antd';
import { ModalProps, ModalType } from 'nice-use-modal';

// Define your modal's data and props types
interface MyModalData {
  title?: string;
  desc?: string;
}

interface MyModalProps {
  onOk: () => void;
  onCancel?: () => void;
}

// Create typed modal type
type MyModalType = ModalType<MyModalData, MyModalProps>;

// Modal component with full TypeScript support
const MyModal: React.FC<ModalProps<MyModalType>> = ({
  visible,
  hide,
  destroy,
  data = {},
  props
}) => {
  const { title = 'New', desc = 'Hello World!' } = data;
  const { onOk, onCancel } = props || {};

  useEffect(() => {
    message.info('Modal component mounted!');
  }, []);

  return (
    <Modal
      title={title}
      open={visible}
      onOk={() => {
        onOk?.();
        hide();
      }}
      onCancel={() => {
        onCancel?.();
        hide();
      }}
      afterClose={() => destroy()} // Preserve animations
    >
      {desc}
    </Modal>
  );
};

export default MyModal;

3. Use Modal in Components

HomePage.tsx

import React from 'react';
import { Button, Space, message } from 'antd';
import { useModal } from 'nice-use-modal';
import MyModal from './MyModal';

const HomePage: React.FC = () => {
  // Initialize modal with props
  const { show, hide, destroy } = useModal(MyModal, {
    onOk: () => {
      message.success('Operation confirmed!');
    },
    onCancel: () => {
      message.info('Operation cancelled');
    },
  });

  return (
    <Space>
      <Button
        type="primary"
        onClick={() => show()}
      >
        Create New
      </Button>
      
      <Button
        onClick={() => show({
          title: 'Edit Item',
          desc: 'You can pass dynamic data when showing the modal.',
        })}
      >
        Edit Item
      </Button>
      
      <Button 
        danger 
        onClick={() => destroy()}
      >
        Destroy Modal
      </Button>
    </Space>
  );
};

export default HomePage;

4. Alternative: Inline Modal Definition

You can also define modals inline for simpler use cases:

import React from 'react';
import { useModal, ModalProps, ModalType } from 'nice-use-modal';
import { Modal } from 'antd';

interface SimpleModalData {
  message: string;
}

interface SimpleModalProps {
  onConfirm: () => void;
}

type SimpleModalType = ModalType<SimpleModalData, SimpleModalProps>;

const useSimpleModal = (props: SimpleModalProps) => {
  return useModal<SimpleModalType>(
    ({ visible, hide, destroy, data, props: modalProps }) => (
      <Modal
        open={visible}
        title="Confirmation"
        onOk={() => {
          modalProps?.onConfirm();
          hide();
        }}
        onCancel={hide}
        afterClose={destroy}
      >
        {data?.message || 'Are you sure?'}
      </Modal>
    ),
    props
  );
};

// Usage
const MyComponent: React.FC = () => {
  const { show } = useSimpleModal({
    onConfirm: () => console.log('Confirmed!')
  });

  return (
    <button onClick={() => show({ message: 'Delete this item?' })}>
      Delete
    </button>
  );
};

API Reference

useModal

The main hook for managing modals.

import { useModal } from 'nice-use-modal';
import type { ModalProps, ModalResult, ModalType } from 'nice-use-modal';

const result: ModalResult<T['data']> = useModal<T extends ModalType>(
  component: ModalComponent<T>,
  props?: T['props']
);

Parameters:

  • component: Modal component or render function
  • props: Static props passed to modal (optional)

Returns:

  • show(data?): Function to display the modal
  • hide(): Function to hide the modal
  • destroy(): Function to destroy the modal

ModalProps

Props passed to modal components:

| Property | Type | Description | |----------|------|-------------| | visible | boolean | Whether the modal is visible | | hide | () => void | Function to hide the modal | | destroy | () => void | Function to destroy the modal | | data | T['data'] | Dynamic data passed when showing | | props | T['props'] | Static props passed during registration |

ModalType

Base interface for defining modal types:

interface ModalType<D = unknown, P = unknown> {
  data?: D;
  props?: P;
}

ModalProvider

Provider component that manages modal context:

interface ModalProviderProps {
  children: React.ReactNode;
}

Migration Guide

From v1.x to v2.0

  1. TypeScript improvements: Better type inference, no breaking changes to existing code
  2. Build system: Updated build output, but API remains the same
  3. Performance: Automatic optimizations, no code changes needed

Key Concepts

hide vs destroy:

  • hide(): Hides modal but preserves state and component instance
  • destroy(): Completely removes modal and cleans up state
  • For animated modals: use hide() first, then destroy() in afterClose

data vs props:

  • data: Dynamic data passed each time show() is called
  • props: Static configuration passed once during useModal() initialization

Examples with Popular UI Libraries

Ant Design

import { Modal } from 'antd';
import { ModalProps, ModalType } from 'nice-use-modal';

type AntModalType = ModalType<{ title: string }, { onOk: () => void }>;

const AntModal: React.FC<ModalProps<AntModalType>> = ({ visible, hide, destroy, data, props }) => (
  <Modal
    open={visible}
    title={data?.title}
    onOk={props?.onOk}
    onCancel={hide}
    afterClose={destroy}
  >
    Modal content
  </Modal>
);

Material-UI

import { Dialog, DialogTitle, DialogContent } from '@mui/material';
import { ModalProps, ModalType } from 'nice-use-modal';

type MuiModalType = ModalType<{ title: string }, { onClose: () => void }>;

const MuiModal: React.FC<ModalProps<MuiModalType>> = ({ visible, hide, data, props }) => (
  <Dialog open={visible} onClose={hide}>
    <DialogTitle>{data?.title}</DialogTitle>
    <DialogContent>
      Modal content
    </DialogContent>
  </Dialog>
);

License

MIT