Getting Started

Installation

npm install better-modal

Setup

Create a file that initializes Better Modal and exports the type-safe helper functions to create modals and registries.

Import

Import the betterModal function from better-modal.

modals/init.ts
import { betterModal } from "better-modal";

Define your variants

import { ShadcnDialog } from "@/components/shadcn-dialog";

const m = betterModal({
  variants: {
    dialog: ShadcnDialog,
  },
});

You can read more about variants in the variants section.

Export the helper functions

Feel free to name them however you want.

export const modal = m.modal;
export const registry = m.registry;

Define your modals

Don't define your modals or registries within the same file as the initialization to prevent circular dependencies.

Create a modal

Use the modal function to create a modal by simply passing a component and selecting a variant.

modals/registry.ts
import { modal } from "./init";

const invoiceModal = modal(AddInvoiceForm, "dialog");

Add default values to your modal by using the withDefaults function, so you no longer have to provide them when e.g. opening the modal.

import { AddInvoiceForm } from "@/components/AddInvoiceForm";

const addInvoiceModal = m.modal(AddInvoiceForm, "dialog").withDefaults({
  variant: {
    title: "Add Invoice",
    description: "Add a new invoice",
  },
});

Importing all components in one file might impact your bundle size. We recommend using the lazy function to load your components dynamically. You can read more about it in the lazy loading section.

Create your registry

Combine all your modals into a single registry.

import { registry } from "./init";

export const modals = registry({
  invoice: addInvoiceModal,
});

Nest your modals to group related domains together.

export const modals = registry({
  invoice: {
    add: addInvoiceModal,
  },
});

Usage

Create Provider & Hooks

Create a file that creates a provider and a hook to manage your modals.

modals/react.ts
"use client";

import { createBetterModalReact } from "better-modal/react";
import { modals } from "./registry";

export const { useBetterModal, BetterModalProvider } =
  createBetterModalReact(modals);

Mount the provider

Mount the provider at the root of your app. (e.g. Next.js Root Layout)

app/layout.tsx
import { BetterModalProvider } from "@/modals/react";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html>
      <body>
        <BetterModalProvider>{children}</BetterModalProvider>
      </body>
    </html>
  );
}

Use the hook

"use client";

export function MyButton() {
  const bm = useBetterModal();
  return <button onClick={() => bm.invoice.add.open()}>Open Modal</button>;
}