Modals manager based on Mantine components providing context-based modal state management with confirmation, context, and content modals.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
React hook providing access to modal context methods for component-based modal management.
React hook that provides access to modal context and methods for imperative modal control within components.
/**
* Hook to access modal context and methods
* @returns Modal context with all modal management methods
* @throws Error if called outside ModalsProvider
*/
function useModals(): ModalsContextProps;
interface ModalsContextProps {
/** Default modal properties applied to all modals */
modalProps: ModalSettings;
/** Array of currently open modals */
modals: ModalState[];
/** Open a content modal */
openModal: (props: ModalSettings) => string;
/** Open a confirmation modal */
openConfirmModal: (props: OpenConfirmModal) => string;
/** Open a context modal */
openContextModal: <TKey extends MantineModal>(
modal: TKey,
props: OpenContextModal<Parameters<MantineModals[TKey]>[0]['innerProps']>
) => string;
/** Close a specific modal */
closeModal: (id: string, canceled?: boolean) => void;
/** Close a context modal */
closeContextModal: <TKey extends MantineModal>(id: TKey, canceled?: boolean) => void;
/** Close all modals */
closeAll: () => void;
/** Update modal properties */
updateModal: (payload: { modalId: string } & Partial<OpenConfirmModal>) => void;
/** Update context modal properties */
updateContextModal: (payload: { modalId: string } & Partial<OpenContextModal<any>>) => void;
}Basic Usage:
import { useModals } from "@mantine/modals";
import { Button, Text } from "@mantine/core";
function MyComponent() {
const modals = useModals();
const showInfoModal = () => {
modals.openModal({
title: "Information",
children: <Text>This is some important information.</Text>,
});
};
const showConfirmModal = () => {
modals.openConfirmModal({
title: "Confirm Action",
children: <Text>Are you sure you want to proceed?</Text>,
labels: { confirm: "Yes", cancel: "No" },
onConfirm: () => console.log("Confirmed"),
onCancel: () => console.log("Cancelled"),
});
};
return (
<div>
<Button onClick={showInfoModal}>Show Info</Button>
<Button onClick={showConfirmModal}>Show Confirm</Button>
</div>
);
}Access current modal state information through the hook.
/**
* Current modal state
*/
interface ModalState {
/** Unique modal ID */
id: string;
/** Modal properties */
props: ModalSettings | OpenConfirmModal | OpenContextModal;
/** Modal type */
type: 'content' | 'confirm' | 'context';
/** Context modal key (for context modals only) */
ctx?: string;
}Usage Examples:
import { useModals } from "@mantine/modals";
function ModalStatusComponent() {
const modals = useModals();
return (
<div>
<Text>Open modals: {modals.modals.length}</Text>
{modals.modals.length > 0 && (
<div>
<Text>Current modals:</Text>
{modals.modals.map((modal) => (
<Text key={modal.id} size="sm">
- {modal.id} ({modal.type})
</Text>
))}
<Button onClick={modals.closeAll}>Close All</Button>
</div>
)}
</div>
);
}Using the hook for complex modal workflows within components.
Form Modal Example:
import { useModals } from "@mantine/modals";
import { useState } from "react";
import { Button, TextInput, Stack } from "@mantine/core";
function EditUserComponent({ user }) {
const modals = useModals();
const [formData, setFormData] = useState(user);
const handleEdit = () => {
const modalId = modals.openModal({
title: "Edit User",
size: "md",
children: (
<UserEditForm
data={formData}
onSave={(data) => {
setFormData(data);
modals.closeModal(modalId);
saveUser(data);
}}
onCancel={() => modals.closeModal(modalId)}
/>
),
});
};
const handleDelete = () => {
modals.openConfirmModal({
title: "Delete User",
children: <Text>Are you sure you want to delete this user?</Text>,
labels: { confirm: "Delete", cancel: "Cancel" },
confirmProps: { color: "red" },
onConfirm: () => deleteUser(user.id),
});
};
return (
<div>
<Button onClick={handleEdit}>Edit</Button>
<Button color="red" onClick={handleDelete}>Delete</Button>
</div>
);
}Multi-Step Workflow:
import { useModals } from "@mantine/modals";
function MultiStepWorkflow() {
const modals = useModals();
const startWorkflow = () => {
// Step 1: Choose action
const step1Id = modals.openModal({
title: "Step 1: Choose Action",
children: (
<Stack>
<Text>What would you like to do?</Text>
<Button onClick={() => {
modals.closeModal(step1Id);
showStep2("create");
}}>
Create New
</Button>
<Button onClick={() => {
modals.closeModal(step1Id);
showStep2("import");
}}>
Import Existing
</Button>
</Stack>
),
});
};
const showStep2 = (action: string) => {
const step2Id = modals.openModal({
title: `Step 2: ${action === "create" ? "Create" : "Import"}`,
children: (
<Stack>
<Text>Configure your {action} settings:</Text>
{/* Form components based on action */}
<Button onClick={() => {
modals.closeModal(step2Id);
showStep3(action);
}}>
Next
</Button>
<Button variant="default" onClick={() => {
modals.closeModal(step2Id);
startWorkflow(); // Go back to step 1
}}>
Back
</Button>
</Stack>
),
});
};
const showStep3 = (action: string) => {
modals.openConfirmModal({
title: "Step 3: Confirm",
children: <Text>Ready to {action}? This action cannot be undone.</Text>,
labels: { confirm: "Proceed", cancel: "Cancel" },
onConfirm: () => performAction(action),
});
};
return <Button onClick={startWorkflow}>Start Workflow</Button>;
}Using the hook to dynamically update modals based on component state.
import { useModals } from "@mantine/modals";
import { useState, useEffect } from "react";
function DynamicModalComponent() {
const modals = useModals();
const [progress, setProgress] = useState(0);
const [modalId, setModalId] = useState<string | null>(null);
const startProcess = () => {
const id = modals.openModal({
title: "Processing...",
children: <Text>Starting process...</Text>,
closeOnClickOutside: false,
closeOnEscape: false,
});
setModalId(id);
setProgress(0);
};
// Update modal based on progress
useEffect(() => {
if (modalId && progress > 0) {
modals.updateModal({
modalId,
title: `Processing... ${progress}%`,
children: (
<div>
<Text>Progress: {progress}%</Text>
<div style={{
width: "100%",
height: "10px",
backgroundColor: "#f0f0f0",
borderRadius: "5px"
}}>
<div style={{
width: `${progress}%`,
height: "100%",
backgroundColor: "#007bff",
borderRadius: "5px",
transition: "width 0.3s ease",
}} />
</div>
</div>
),
});
if (progress >= 100) {
setTimeout(() => {
modals.updateModal({
modalId,
title: "Complete!",
children: (
<div>
<Text c="green">Process completed successfully!</Text>
<Button
mt="md"
onClick={() => {
modals.closeModal(modalId);
setModalId(null);
setProgress(0);
}}
>
Close
</Button>
</div>
),
});
}, 500);
}
}
}, [progress, modalId]);
// Simulate progress
useEffect(() => {
if (modalId && progress < 100) {
const timer = setTimeout(() => {
setProgress(prev => Math.min(prev + 10, 100));
}, 500);
return () => clearTimeout(timer);
}
}, [progress, modalId]);
return <Button onClick={startProcess}>Start Process</Button>;
}Proper error handling when using the hook.
import { useModals } from "@mantine/modals";
function SafeModalComponent() {
const modals = useModals();
const handleAsyncAction = async () => {
const modalId = modals.openModal({
title: "Loading...",
children: <Text>Please wait...</Text>,
});
try {
const result = await performAsyncOperation();
modals.updateModal({
modalId,
title: "Success",
children: (
<div>
<Text c="green">Operation completed successfully!</Text>
<Button mt="md" onClick={() => modals.closeModal(modalId)}>
OK
</Button>
</div>
),
});
} catch (error) {
modals.updateModal({
modalId,
title: "Error",
children: (
<div>
<Text c="red">Operation failed: {error.message}</Text>
<Button.Group mt="md">
<Button variant="default" onClick={() => modals.closeModal(modalId)}>
Cancel
</Button>
<Button onClick={() => {
modals.closeModal(modalId);
handleAsyncAction(); // Retry
}}>
Retry
</Button>
</Button.Group>
</div>
),
});
}
};
return <Button onClick={handleAsyncAction}>Start Async Action</Button>;
}
// Component that handles hook errors
function ModalProvider({ children }) {
try {
return (
<ModalsProvider>
{children}
</ModalsProvider>
);
} catch (error) {
console.error("Modal provider error:", error);
return <div>Modal system unavailable</div>;
}
}