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

@sentuh/react-bootstrap-modal

v1.0.2

Published

Lightweight and customizable React modal component styled with Bootstrap 5.

Readme

@sentuh/react-bootstrap-modal

Lightweight React modal component built on Bootstrap 5, easy to use, supporting:

  • size, centered, backdrop, scrollable, fullscreen
  • Custom modalClassName
  • ModalProvider for centralized state management
  • useModal and useActiveModal hooks for flexible modal control

Installation

npm install @sentuh/react-bootstrap-modal

Demo (live preview)

You can try a live demo with example code here: https://stackblitz.com/edit/react-bootstrap-modal

Usage Overview

1. Wrap Your App with ModalProvider

The ModalProvider manages all modal state in your app. Wrap it around your root component:

import { ModalProvider } from "@sentuh/react-bootstrap-modal";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";

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

2. Opening a Modal

There are two main ways to open a modal:

  1. Passing the component class/function (recommended for reusability and automatic props handling)
  2. Passing a JSX element directly (for quick one-off modals)
Method 1: Passing a Component (Recommended)
import { useModal } from "@sentuh/react-bootstrap-modal";
import { ExampleModal } from "./ExampleModal";

function App() {
  const modal = useModal();

  const handleOpen = () => {
    // Pass the component itself, modal will render it internally
    const result = await modal.open(ExampleModal);
    console.log(result);
  };

  return (
    <button className="btn btn-primary" onClick={handleOpen}>
      Open Modal
    </button>
  );
}

ExampleModal Example:

import type { ModalProps } from "@sentuh/react-bootstrap-modal";

interface Props extends ModalProps {}

export const ExampleModal = ({ onClose, onDismiss }: Props) => {
  return (
    <>
      <div className="modal-header">
        <h4>Example Modal Header</h4>
      </div>
      <div className="modal-body">
        <p>This is an example reusable modal component.</p>
      </div>
      <div className="modal-footer">
        <button className="btn btn-secondary" onClick={onDismiss}>
          Cancel
        </button>
        <button className="btn btn-primary" onClick={onClose}>
          Save
        </button>
      </div>
    </>
  );
};

Note: In this approach, useModal.open() will internally create and manage the modal instance.

You can pass dynamic data to your modal using the model argument:

const model = { id: 1, name: "Jane Doe" };
const result = await modal.open(ExampleModal, model);
console.log(result); // { name: 'John Doe'}

Inside ExampleModal, access the passed data via the model prop:

import type { ModalProps } from "@sentuh/react-bootstrap-modal";
import { useEffect } from "react";

interface InputProps {
  id: string;
  name: string;
}

interface OutputProps {
  name: string;
}

interface Props extends ModalProps<InputProps, OutputProps> {}

export const ExampleModal = ({ onClose, onDismiss, model }: Props) => {
  useEffect(() => {
    console.log(model); // input: { id: 1, name: 'Jane Doe'}
  }, []);

  const handleSave = () => {
    // return output to parent
    onClose({ name: "John Doe" });
  };

  return (
    <>
      <div className="modal-header">
        <h4>Example Modal Header</h4>
      </div>
      <div className="modal-body">
        <p>This is an example reusable modal component.</p>
      </div>
      <div className="modal-footer">
        <button className="btn btn-secondary" onClick={onDismiss}>
          Cancel
        </button>
        <button className="btn btn-primary" onClick={handleSave}>
          Save
        </button>
      </div>
    </>
  );
};
Method 2 — Passing JSX Element Directly
import { useModal } from "@sentuh/react-bootstrap-modal";
import { ExampleModal } from "./ExampleModal";

function App() {
  const modal = useModal();

  const handleChange = (result: { name: string }) => {
    console.log(result); // output: { name: 'John Doe' }
  }

  const handleOpen = () => {
    // Pass the JSX element directly
    modal.open(<ExampleModal onChange={handleChange}/>);
  };

  return (
    <button className="btn btn-primary" onClick={handleOpen}>
      Open Modal
    </button>
  );
}

Difference from Method 1: In this approach, you pass a JSX element instead of the component reference. This is convenient for quick, one-off modals with inline props, but it is less reusable.

⚠️ Important: When using this approach, you need to implement useActiveModal inside your modal component to manually control closing or other modal actions. See Point 3 – Advanced Usage with useActiveModal for implementation examples.

3. Advanced Usage with useActiveModal

useActiveModal allows the modal itself to control its lifecycle, such as closing itself.

import { useActiveModal } from "@sentuh/react-bootstrap-modal";

interface Props {
  onChange: (result: { name: string }) => void;
}

export const ExampleModal = ({ onChange }: Props) => {
  const activeModal = useActiveModal();

  const handleSave = () => {
    activeModal.dismiss();
    onChange({ name: "John Doe" });
  };

  return (
    <>
      <div className="modal-header">
        <h4>Example Modal Header</h4>
      </div>
      <div className="modal-body">
        <p>This is an example reusable modal component.</p>
      </div>
      <div className="modal-footer">
        <button className="btn btn-secondary" onClick={activeModal.dismiss}>
          Cancel
        </button>
        <button className="btn btn-primary" onClick={handleSave}>
          Save
        </button>
      </div>
    </>
  );
};

This approach is ideal for reusable modal components that need to self-manage close actions.

4. Shaking Animation for Static Modals

To provide visual feedback when a user clicks the backdrop of a static modal (where clicking outside does not close it), you can add a custom animation to your global CSS file.

The library automatically applies the .modal-static-shake class when a static backdrop is clicked.

.modal-static-shake {
  animation: shake 0.3s ease-in-out;
}

@keyframes shake {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.02);
  }
}

Note: The CSS above is just a reference for the default behavior. You can override the .modal-static-shake class with any custom transition or animation you prefer.

API Reference

This section provides detailed information about the props and configuration options available for the Modal system.

1. The useModal Hook

The useModal hook returns an object containing methods to control the modal stack programmatically.

| Prop | Type | Description | | -------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------- | | open | (component: ModalComponentType, model?: any, options?: ModalOptionsProps) => Promise<any> | Opens a modal. Resolves with data passed from the modal. | | close | (result?: any) => void | Close current active modal | | dismissAll() | () => void | Close all active modals. |

2. Open Parameters

When calling modal.open(), you can pass the following arguments to define what to render and how it behaves.

| Prop | Type | Description | | --------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- | | component | JSX.Element or ((props: any) => JSX.Element) | The modal component to render. Can be a JSX element or a component function. | | model | any | Optional data passed to the modal component as props. Useful for pre-filling forms or passing contextual info. | | options | ModalOptionsProps | Optional modal configuration (size, backdrop, centered, scrollable, fullscreen, custom class). |

3. Modal Options (options)

The options object is the third argument of the open() method. It allows you to customize the behavior and appearance of each specific modal instance.

| Prop | Type | Default | Description | | -------------- | ------------------------------ | ------- | ------------------------------------------------------------------------ | | backdrop | boolean or static | true | Whether a backdrop is shown. "static" disables closing on click outside. | | keyboard | boolean | false | Allow ESC key to close modal. | | size | sm, lg, xl, fullscreen | md | Sets the modal size. | | centered | boolean | false | Vertically center the modal. | | scrollable | boolean | false | Enable scrolling within modal body. | | modalClassName | string | "" | Add custom CSS class to the modal container |

4. The useActiveModal Hook

This hook is intended for use inside the component being rendered as a modal (the child component). It provides access to the current modal instance's lifecycle controls.

| Prop | Type | Description | | ------------ | ------------------------ | ------------------------------------------------------------------------------------------------------------ | | close() | (result?: any) => void | Closes the modal and returns a success result to the caller. Use this for "Submit," "Save," or "OK" actions. | | dismiss() | () => void | Closes the modal without a result, typically triggering a cancel or rejection. Use this for "Cancel" buttons |