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
Predefined reusable modal components registered with the provider for consistent modal experiences.
Opens a predefined modal component by key with custom properties.
/**
* Opens a predefined context modal by key
* @param payload - Modal key, configuration, and inner props
* @returns Modal ID for future reference
*/
function openContextModal<TKey extends MantineModal>(
payload: OpenContextModal<Parameters<MantineModals[TKey]>[0]['innerProps']> & { modal: TKey }
): string;
interface OpenContextModal<CustomProps extends Record<string, any> = {}> extends ModalSettings {
/** Custom props passed to the modal component */
innerProps: CustomProps;
}Usage Examples:
import { openContextModal } from "@mantine/modals";
// Open registered context modal
openContextModal({
modal: "userProfile",
title: "User Profile",
innerProps: {
userId: "123",
editable: true,
},
});
// Context modal with custom modal properties
openContextModal({
modal: "deleteConfirmation",
title: "Delete Item",
size: "sm",
centered: true,
innerProps: {
itemName: "Important Document",
itemType: "document",
onConfirm: () => deleteDocument("doc-123"),
},
});Updates properties of an existing context modal.
/**
* Updates properties of an existing context modal
* @param payload - Modal ID and updated properties
*/
function updateContextModal(
payload: { modalId: string } & Partial<OpenContextModal<any>>
): void;Usage Examples:
import { openContextModal, updateContextModal } from "@mantine/modals";
// Open context modal
const modalId = openContextModal({
modal: "dataEditor",
modalId: "editor-1",
title: "Edit Data",
innerProps: {
data: initialData,
readOnly: false,
},
});
// Update inner props
updateContextModal({
modalId: "editor-1",
innerProps: {
data: updatedData,
readOnly: true, // Make read-only
},
});
// Update modal properties
updateContextModal({
modalId: "editor-1",
title: "View Data (Read Only)",
size: "lg",
});Interface for creating context modal components.
/**
* Props interface for context modal components
*/
interface ContextModalProps<T extends Record<string, any> = {}> {
/** Modal context providing access to modal methods */
context: ModalsContextProps;
/** Custom props passed when opening the modal */
innerProps: T;
/** Unique modal instance ID */
id: string;
}Creating Context Modals:
import { ContextModalProps } from "@mantine/modals";
import { Button, Text, TextInput, Stack } from "@mantine/core";
// User profile modal component
interface UserProfileProps {
userId: string;
editable?: boolean;
onSave?: (data: any) => void;
}
const UserProfileModal: React.FC<ContextModalProps<UserProfileProps>> = ({
context,
id,
innerProps,
}) => {
const [userData, setUserData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Load user data
loadUser(innerProps.userId).then((data) => {
setUserData(data);
setLoading(false);
});
}, [innerProps.userId]);
const handleSave = async () => {
if (innerProps.onSave) {
await innerProps.onSave(userData);
}
context.closeModal(id);
};
if (loading) {
return <Text>Loading user profile...</Text>;
}
return (
<Stack>
<TextInput
label="Name"
value={userData.name}
disabled={!innerProps.editable}
onChange={(e) => setUserData({ ...userData, name: e.target.value })}
/>
<TextInput
label="Email"
value={userData.email}
disabled={!innerProps.editable}
onChange={(e) => setUserData({ ...userData, email: e.target.value })}
/>
{innerProps.editable && (
<Button.Group>
<Button variant="default" onClick={() => context.closeModal(id)}>
Cancel
</Button>
<Button onClick={handleSave}>
Save Changes
</Button>
</Button.Group>
)}
{!innerProps.editable && (
<Button onClick={() => context.closeModal(id)}>
Close
</Button>
)}
</Stack>
);
};Register context modals with the provider and ensure type safety.
Provider Registration:
import { ModalsProvider } from "@mantine/modals";
// Register context modals
<ModalsProvider
modals={{
userProfile: UserProfileModal,
deleteConfirmation: DeleteConfirmationModal,
dataEditor: DataEditorModal,
}}
>
<App />
</ModalsProvider>Module Augmentation for Type Safety:
// types/modals.ts
import { ContextModalProps } from "@mantine/modals";
declare module "@mantine/modals" {
interface MantineModalsOverride {
modals: {
userProfile: ContextModalProps<{
userId: string;
editable?: boolean;
onSave?: (data: any) => void;
}>;
deleteConfirmation: ContextModalProps<{
itemName: string;
itemType: string;
onConfirm: () => void;
}>;
dataEditor: ContextModalProps<{
data: any;
readOnly?: boolean;
onSubmit?: (data: any) => void;
}>;
};
}
}Complex context modal usage patterns and techniques.
Dynamic Modal Loading:
// Lazy-loaded context modal
const LazyFormModal = lazy(() => import("./FormModal"));
const DynamicFormModal: React.FC<ContextModalProps<{ formType: string }>> = (props) => {
return (
<Suspense fallback={<Text>Loading form...</Text>}>
<LazyFormModal {...props} />
</Suspense>
);
};
// Register dynamic modal
<ModalsProvider
modals={{
dynamicForm: DynamicFormModal,
}}
>
<App />
</ModalsProvider>Modal Communication:
// Modal that opens other modals
const ParentModal: React.FC<ContextModalProps<{ data: any }>> = ({
context,
id,
innerProps,
}) => {
const openChildModal = () => {
context.openContextModal("childModal", {
title: "Child Modal",
innerProps: {
parentId: id,
data: innerProps.data,
onComplete: (result) => {
// Handle child modal completion
updateContextModal({
modalId: id,
innerProps: {
...innerProps,
data: { ...innerProps.data, ...result },
},
});
},
},
});
};
return (
<div>
<Text>Parent Modal Content</Text>
<Button onClick={openChildModal}>Open Child Modal</Button>
<Button onClick={() => context.closeModal(id)}>Close</Button>
</div>
);
};Context Modal with State Synchronization:
// Modal that syncs with external state
const SyncedModal: React.FC<ContextModalProps<{
storeId: string;
onStateChange: (state: any) => void;
}>> = ({ context, id, innerProps }) => {
const [localState, setLocalState] = useState({});
// Sync changes back to parent
useEffect(() => {
innerProps.onStateChange?.(localState);
}, [localState]);
// Listen for external updates
useEffect(() => {
const unsubscribe = subscribeToStore(innerProps.storeId, (newState) => {
setLocalState(newState);
});
return unsubscribe;
}, [innerProps.storeId]);
return (
<div>
{/* Modal content that updates localState */}
</div>
);
};