Skip to content

Modals ​

Hewcode provides a simple API to quickly get started with modals/dialogs.

Using the Modal Hook ​

With the useModalManager hook you can easily display different types of modals from anywhere in your React component tree.

Confirmation Modals ​

Display confirmation dialogs and wait for user response:

jsx
import useModalManager from '@hewcode/react/hooks/use-modal-manager';

export default function PostActions({ post }) {
    const modal = useModalManager();

    const handleDelete = async () => {
        const confirmed = await modal.confirm({
            title: 'Delete Post',
            description: 'Are you sure you want to delete this post? This action cannot be undone.',
            confirmLabel: 'Delete',
            cancelLabel: 'Cancel',
            variant: 'danger',
        });

        if (confirmed) {
            router.delete(`/posts/${post.id}`);
        }
    };

    return (
        <Button onClick={handleDelete} variant="destructive">
            Delete
        </Button>
    );
}

The confirm() method returns a promise that resolves to true when the user confirms, or false when they cancel or close the modal.

Confirmation modal options:

  • title - Modal title
  • description - Modal body text
  • confirmLabel - Text for confirm button
  • cancelLabel - Text for cancel button
  • variant - Visual style: 'primary', 'danger', 'warning', 'success', 'info' (default: 'danger')
  • icon - Custom Lucide icon component (default: TriangleAlert)
  • onConfirm - Callback when user confirms
  • onCancel - Callback when user cancels
  • onClose - Callback when modal closes

Custom Modals ​

Display custom content in a modal:

tsx
const modal = useModalManager();

const handleShowDetails = async () => {
    await modal.custom({
        title: 'Post Details',
        size: 'xl',
        children: (
            <div className="space-y-4">
                <div>
                    <h3 className="font-semibold">Title</h3>
                    <p>{post.title}</p>
                </div>
                <div>
                    <h3 className="font-semibold">Content</h3>
                    <p>{post.content}</p>
                </div>
            </div>
        ),
        footer: (
            <Button onClick={() => modal.closeAll()}>Close</Button>
        ),
    });
};

Custom modal options:

  • title - Modal title
  • children - React content to display
  • size - Modal width: 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl', '6xl', '7xl' (default: 'lg')
  • footer - Footer content (usually buttons)
  • className - Additional CSS classes
  • showCloseButton - Show/hide the X close button (default: true)
  • onClose - Callback when modal closes

Component Modals ​

Render an entire component as a modal, giving you full control:

jsx
import useModalManager from '@hewcode/react/hooks/use-modal-manager';

const modal = useModalManager();

const handleEdit = async () => {
    await modal.component(EditPostModal, { post: currentPost });
};
tsx
import Modal from '@hewcode/react/components/modal';
import Button from '@hewcode/react/components/ui/button';
import Input from '@hewcode/react/components/ui/input';
import { useState } from 'react';
import useModalManager from '@hewcode/react/hooks/use-modal-manager';

const EditPostModal = ({ post, onClose }) => {
    const [title, setTitle] = useState(post.title);

    const handleSubmit = (e) => {
        e.preventDefault();
        router.put(`/posts/${post.id}`, { title });
        onClose();
    };

    return (
        <Modal
            title="Edit Post"
            size="lg"
            onClose={onClose}
            footer={
                <div className="flex gap-2">
                    <Button onClick={handleSubmit}>Save</Button>
                    <Button variant="outline" onClick={onClose}>Cancel</Button>
                </div>
            }
        >
            <form onSubmit={handleSubmit}>
                <Input
                    value={title}
                    onChange={(e) => setTitle(e.target.value)}
                    placeholder="Post title"
                />
            </form>
        </Modal>
    );
};

The component receives all props you pass, plus an onClose function.

The base Modal component accepts the following props:

PropTypeDefaultDescription
isOpenbooleantrueWhether the modal is open
onClosefunction-Callback when modal should close
titlestring-Modal title displayed in header
childrenReactNode-Modal content
footerReactNode-Footer content (usually buttons)
sizestring'lg'Width: 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl', '6xl', '7xl'
classNamestring-Additional CSS classes for the modal content
showCloseButtonbooleantrueShow/hide the X button in top right