Skip to content

stainless-code/react-modal-manager

Repository files navigation

@stainless-code/react-modal-manager

A powerful, type-safe modal management system for React applications. This library provides utilities to create, manage, and render modals programmatically with full TypeScript support.

A simpler and improved version of eBay's nice-modal-react - designed with modern React patterns and enhanced developer experience.

Features

  • Type-safe: Full TypeScript support with intelligent type inference
  • Programmatic control: Open and close modals from anywhere in your app
  • Performance optimized: Uses Zustand for efficient state management
  • Component caching: Efficient component registration system
  • Simple API: Intuitive methods for modal management
  • Modern React: Built with modern React patterns and hooks
  • Lightweight: Minimal dependencies (nanoid + zustand)

Installation

npm

npm install @stainless-code/react-modal-manager

yarn

yarn add @stainless-code/react-modal-manager

pnpm

pnpm add @stainless-code/react-modal-manager

bun

bun add @stainless-code/react-modal-manager

Usage

1. Setup Provider

First, wrap your app with the ModalProvider:

import { ModalProvider } from "@stainless-code/react-modal-manager";

function App() {
  return (
    <ModalProvider>
      {/* Your app components */}
      <YourAppContent />
    </ModalProvider>
  );
}

2. Create and Use Modal

import { createModal } from "@stainless-code/react-modal-manager";

// Create modal
export const myModal = createModal<{
  title: string;
  message: string;
}>(({ id, close, title, message }) => (
  <div className="modal-overlay">
    <div className="modal-content">
      <h2>{title}</h2>
      <p>{message}</p>
      <button onClick={close}>Close</button>
    </div>
  </div>
));

// Usage in a component
function MyComponent() {
  const handleOpenModal = () => {
    // Open modal with props
    const modalId = myModal.open({
      title: "Hello World",
      message: "This is a modal message!",
    });

    console.log("Modal opened with ID:", modalId);
  };

  return (
    <div>
      <button onClick={handleOpenModal}>Open Modal</button>
      <button onClick={myModal.close}>Close Last Modal</button>
    </div>
  );
}

3. Advanced Usage with TypeScript

import { createModal } from "@stainless-code/react-modal-manager";
import { useState } from "react";

// Create a more complex modal
export const userModal = createModal<{
  user: {
    id: number;
    name: string;
    email: string;
  };
  onSave: (user: any) => void;
}>(({ id, close, user, onSave }) => {
  const [editedUser, setEditedUser] = useState(user);

  function handleSave() {
    onSave(editedUser);
    close(); // Close modal after saving
  }

  return (
    <div className="modal-overlay">
      <div className="modal-content">
        <h2>Edit User</h2>
        <input
          value={editedUser.name}
          onChange={(e) =>
            setEditedUser({ ...editedUser, name: e.target.value })
          }
        />
        <button onClick={handleSave}>Save</button>
        <button onClick={close}>Cancel</button>
      </div>
    </div>
  );
});

// Usage - TypeScript will require the correct props
userModal.open({
  user: {
    id: 1,
    name: "John",
    email: "[email protected]",
  },
  onSave: (user) => console.log("User saved:", user),
});

4. Simple Modal Without Props

// Modal that doesn't require any props
export const confirmModal = createModal(({ close }) => (
  <div className="modal-overlay">
    <div className="modal-content">
      <h2>Are you sure?</h2>
      <p>This action cannot be undone.</p>
      <button onClick={close}>Cancel</button>
      <button
        onClick={() => {
          console.log("Confirmed!");
          close();
        }}
      >
        Confirm
      </button>
    </div>
  </div>
));

// Usage - no props needed
confirmModal.open();

Type Safety

The library provides full TypeScript support with intelligent type inference:

// Define modal with typed props
const myModal = createModal<{
  name: string;
  age: number;
}>(({ close, name, age }) => (
  <div>
    <p>
      Hello {name}, you are {age} years old!
    </p>
    <button onClick={close}>Close</button>
  </div>
));

// ✅ Correct usage - TypeScript enforces required props
myModal.open({ name: "John", age: 30 });

// ❌ TypeScript error - missing required props
myModal.open({ name: "John" }); // Error: Property 'age' is missing

// ❌ TypeScript error - wrong prop types
myModal.open({ name: "John", age: "30" }); // Error: Type 'string' is not assignable to type 'number'

// For modals without props, no type parameter needed
const simpleModal = createModal(({ close }) => (
  <div>
    <p>Simple modal content</p>
    <button onClick={close}>Close</button>
  </div>
));
simpleModal.open(); // ✅ Correct - no props needed

API

ModalProvider

Provider component that manages modal state and rendering. Must wrap your application.

function ModalProvider({ children }: React.PropsWithChildren): JSX.Element;

createModal<TProps>()

Creates a modal instance with open/close methods.

function createModal<TProps = Record<string, unknown>>(
  component: ModalComponent<TProps>,
): CreatedModal<TProps>;
Parameter Type Description
component ModalComponent<TProps> The modal component to be managed

Returns

CreatedModal<TProps> object with:

  • open(props?: TProps): string - Opens the modal and returns its ID
  • close(): void - Closes the most recently opened modal of this type

ModalProps

Props automatically injected into your modal components:

interface ModalProps {
  id: string; // Unique modal identifier
  close: () => void; // Function to close this specific modal
}

ModalComponent<TProps>

Type definition for modal components:

type ModalComponent<TProps = Record<string, unknown>> = React.ComponentType<
  ModalProps & TProps
>;

Your modal components should accept ModalProps combined with your custom props.

useModalStore

Direct access to the modal store (advanced usage):

const { modals, openModal, closeModal } = useModalStore();

Contributing

Feel free to submit issues or pull requests to improve the library. Every bit of help is appreciated. 💖

Read the contribution guidelines.

License

MIT

About

A powerful, type-safe modal management system for React applications

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Contributors 2

  •  
  •