diff --git a/docs/data/toolpad/core/components/use-dialogs/CustomDialogWithPayloadAdvanced.js b/docs/data/toolpad/core/components/use-dialogs/CustomDialogWithPayloadAdvanced.js
new file mode 100644
index 00000000000..65260bb3c12
--- /dev/null
+++ b/docs/data/toolpad/core/components/use-dialogs/CustomDialogWithPayloadAdvanced.js
@@ -0,0 +1,235 @@
+import * as React from 'react';
+import PropTypes from 'prop-types';
+import { DialogsProvider, useDialogs } from '@toolpad/core/useDialogs';
+import Button from '@mui/material/Button';
+import LoadingButton from '@mui/lab/LoadingButton';
+import Dialog from '@mui/material/Dialog';
+import DialogTitle from '@mui/material/DialogTitle';
+import DialogContent from '@mui/material/DialogContent';
+import DialogActions from '@mui/material/DialogActions';
+import TextField from '@mui/material/TextField';
+import Stack from '@mui/material/Stack';
+import MenuItem from '@mui/material/MenuItem';
+import { FormContext, useFormContext } from './TransferFormContext';
+
+function mockTransfer(formData) {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ console.log('FormData', formData);
+ const uuid = crypto.randomUUID();
+ resolve(uuid);
+ }, 1000);
+ });
+}
+
+function TransactionDialog({ payload, open, onClose }) {
+ const [loading, setLoading] = React.useState(false);
+ const { formData } = useFormContext();
+
+ const isValidCsrf = React.useMemo(() => {
+ if (payload.data) {
+ return true;
+ }
+ return false;
+ }, [payload.data]);
+
+ return (
+
+ );
+}
+
+TransactionDialog.propTypes = {
+ /**
+ * A function to call when the dialog should be closed. If the dialog has a return
+ * value, it should be passed as an argument to this function. You should use the promise
+ * that is returned to show a loading state while the dialog is performing async actions
+ * on close.
+ * @param result The result to return from the dialog.
+ * @returns A promise that resolves when the dialog can be fully closed.
+ */
+ onClose: PropTypes.func.isRequired,
+ /**
+ * Whether the dialog is open.
+ */
+ open: PropTypes.bool.isRequired,
+ /**
+ * The payload that was passed when the dialog was opened.
+ */
+ payload: PropTypes.shape({
+ component: PropTypes.node,
+ data: PropTypes.string.isRequired,
+ }).isRequired,
+};
+
+function PayloadIndia() {
+ const { formData, setFormData } = useFormContext();
+
+ return (
+
+
+ setFormData({ ...formData, amount: event.target.value })
+ }
+ placeholder="Enter amount in rupees"
+ slotProps={{
+ input: {
+ endAdornment: '₹',
+ },
+ }}
+ />
+
+ setFormData({ ...formData, ifscCode: event.target.value })
+ }
+ placeholder="Enter 11-character IFSC code"
+ helperText="Bank branch identifier code (e.g. HDFC0001234)"
+ />
+
+ setFormData({ ...formData, accountNumber: event.target.value })
+ }
+ placeholder="Enter bank account number"
+ helperText="Please verify the account number carefully"
+ />
+
+ );
+}
+
+function PayloadUSA() {
+ const { formData, setFormData } = useFormContext();
+
+ return (
+
+
+ setFormData({ ...formData, amount: event.target.value })
+ }
+ placeholder="Enter amount in dollars"
+ slotProps={{
+ input: {
+ endAdornment: '$',
+ },
+ }}
+ />
+
+ setFormData({ ...formData, routingNumber: event.target.value })
+ }
+ placeholder="123456789"
+ helperText="ABA routing transit number (e.g. 021000021)"
+ />
+
+ setFormData({ ...formData, accountNumber: event.target.value })
+ }
+ placeholder="Enter 10-12 digit account number"
+ helperText="US bank account number (typically 10-12 digits)"
+ />
+ {
+ console.log('changing', event.target.value);
+ setFormData({
+ ...formData,
+ accountType: event.target.value,
+ });
+ }}
+ defaultValue="checking"
+ placeholder="Select account type"
+ >
+
+
+
+
+ );
+}
+
+function DemoContent() {
+ const dialogs = useDialogs();
+ const [country, setCountry] = React.useState('usa');
+ const csrfToken = crypto.randomUUID();
+
+ return (
+
+ setCountry(event.target.value)}
+ sx={{ minWidth: 200 }}
+ >
+
+
+
+
+
+
+ );
+}
+
+export default function CustomDialogWithPayloadAdvanced() {
+ const [formData, setFormData] = React.useState({
+ amount: '',
+ accountNumber: '',
+ });
+
+ const contextValue = React.useMemo(() => ({ formData, setFormData }), [formData]);
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/docs/data/toolpad/core/components/use-dialogs/CustomDialogWithPayloadAdvanced.tsx b/docs/data/toolpad/core/components/use-dialogs/CustomDialogWithPayloadAdvanced.tsx
new file mode 100644
index 00000000000..1f6688f5cfc
--- /dev/null
+++ b/docs/data/toolpad/core/components/use-dialogs/CustomDialogWithPayloadAdvanced.tsx
@@ -0,0 +1,219 @@
+import * as React from 'react';
+import { DialogsProvider, useDialogs, DialogProps } from '@toolpad/core/useDialogs';
+import Button from '@mui/material/Button';
+import LoadingButton from '@mui/lab/LoadingButton';
+import Dialog from '@mui/material/Dialog';
+import DialogTitle from '@mui/material/DialogTitle';
+import DialogContent from '@mui/material/DialogContent';
+import DialogActions from '@mui/material/DialogActions';
+import TextField from '@mui/material/TextField';
+import Stack from '@mui/material/Stack';
+import MenuItem from '@mui/material/MenuItem';
+import {
+ FormContext,
+ useFormContext,
+ type TransferFormData,
+} from './TransferFormContext';
+
+function mockTransfer(formData: TransferFormData): Promise {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ console.log('FormData', formData);
+ const uuid = crypto.randomUUID();
+ resolve(uuid);
+ }, 1000);
+ });
+}
+
+function TransactionDialog({
+ payload,
+ open,
+ onClose,
+}: DialogProps<{ component: React.ReactNode; data: string }, string | null>) {
+ const [loading, setLoading] = React.useState(false);
+ const { formData } = useFormContext();
+
+ const isValidCsrf = React.useMemo(() => {
+ if (payload.data) {
+ return true;
+ }
+ return false;
+ }, [payload.data]);
+
+ return (
+
+ );
+}
+
+function PayloadIndia() {
+ const { formData, setFormData } = useFormContext();
+
+ return (
+
+
+ setFormData({ ...formData, amount: event.target.value })
+ }
+ placeholder="Enter amount in rupees"
+ slotProps={{
+ input: {
+ endAdornment: '₹',
+ },
+ }}
+ />
+
+ setFormData({ ...formData, ifscCode: event.target.value })
+ }
+ placeholder="Enter 11-character IFSC code"
+ helperText="Bank branch identifier code (e.g. HDFC0001234)"
+ />
+
+ setFormData({ ...formData, accountNumber: event.target.value })
+ }
+ placeholder="Enter bank account number"
+ helperText="Please verify the account number carefully"
+ />
+
+ );
+}
+
+function PayloadUSA() {
+ const { formData, setFormData } = useFormContext();
+
+ return (
+
+
+ setFormData({ ...formData, amount: event.target.value })
+ }
+ placeholder="Enter amount in dollars"
+ slotProps={{
+ input: {
+ endAdornment: '$',
+ },
+ }}
+ />
+
+ setFormData({ ...formData, routingNumber: event.target.value })
+ }
+ placeholder="123456789"
+ helperText="ABA routing transit number (e.g. 021000021)"
+ />
+
+ setFormData({ ...formData, accountNumber: event.target.value })
+ }
+ placeholder="Enter 10-12 digit account number"
+ helperText="US bank account number (typically 10-12 digits)"
+ />
+ {
+ console.log('changing', event.target.value);
+ setFormData({
+ ...formData,
+ accountType: event.target.value as 'checking' | 'savings',
+ });
+ }}
+ defaultValue="checking"
+ placeholder="Select account type"
+ >
+
+
+
+
+ );
+}
+
+function DemoContent() {
+ const dialogs = useDialogs();
+ const [country, setCountry] = React.useState('usa');
+ const csrfToken = crypto.randomUUID();
+
+ return (
+
+ setCountry(event.target.value)}
+ sx={{ minWidth: 200 }}
+ >
+
+
+
+
+
+
+ );
+}
+
+export default function CustomDialogWithPayloadAdvanced() {
+ const [formData, setFormData] = React.useState({
+ amount: '',
+ accountNumber: '',
+ });
+
+ const contextValue = React.useMemo(() => ({ formData, setFormData }), [formData]);
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/docs/data/toolpad/core/components/use-dialogs/CustomDialogWithPayloadAdvanced.tsx.preview b/docs/data/toolpad/core/components/use-dialogs/CustomDialogWithPayloadAdvanced.tsx.preview
new file mode 100644
index 00000000000..fc942d7a7db
--- /dev/null
+++ b/docs/data/toolpad/core/components/use-dialogs/CustomDialogWithPayloadAdvanced.tsx.preview
@@ -0,0 +1,4 @@
+const uuid = await dialogs.open(TransactionDialog, {
+ component: country === 'usa' ? : ,
+ data: csrfToken,
+});
\ No newline at end of file
diff --git a/docs/data/toolpad/core/components/use-dialogs/TransferFormContext.js b/docs/data/toolpad/core/components/use-dialogs/TransferFormContext.js
new file mode 100644
index 00000000000..172d1c9d9f5
--- /dev/null
+++ b/docs/data/toolpad/core/components/use-dialogs/TransferFormContext.js
@@ -0,0 +1,13 @@
+import * as React from 'react';
+
+// Create context with initial value
+export const FormContext = React.createContext(null);
+
+// Custom hook to use the form context
+export function useFormContext() {
+ const context = React.useContext(FormContext);
+ if (!context) {
+ throw new Error('useFormContext must be used within a FormProvider');
+ }
+ return context;
+}
diff --git a/docs/data/toolpad/core/components/use-dialogs/TransferFormContext.tsx b/docs/data/toolpad/core/components/use-dialogs/TransferFormContext.tsx
new file mode 100644
index 00000000000..c9979355a6d
--- /dev/null
+++ b/docs/data/toolpad/core/components/use-dialogs/TransferFormContext.tsx
@@ -0,0 +1,26 @@
+import * as React from 'react';
+
+export interface TransferFormData {
+ amount: string;
+ accountNumber: string;
+ // USA specific
+ routingNumber?: string;
+ accountType?: 'checking' | 'savings';
+ // India specific
+ ifscCode?: string;
+}
+
+// Create context with initial value
+export const FormContext = React.createContext<{
+ formData: TransferFormData;
+ setFormData: (data: TransferFormData) => void;
+} | null>(null);
+
+// Custom hook to use the form context
+export function useFormContext() {
+ const context = React.useContext(FormContext);
+ if (!context) {
+ throw new Error('useFormContext must be used within a FormProvider');
+ }
+ return context;
+}
diff --git a/docs/data/toolpad/core/components/use-dialogs/use-dialogs.md b/docs/data/toolpad/core/components/use-dialogs/use-dialogs.md
index 58504d097fd..4e04a4350cc 100644
--- a/docs/data/toolpad/core/components/use-dialogs/use-dialogs.md
+++ b/docs/data/toolpad/core/components/use-dialogs/use-dialogs.md
@@ -103,6 +103,14 @@ Analog to [`window.prompt`](https://developer.mozilla.org/en-US/docs/Web/API/Win
{{"demo": "PromptDialog.js"}}
+## Advanced Examples
+
+### Complex payload
+
+The `payload` can be an object which contains anything - including a React Component. This allows you to pass arbitrary data and components to your dialog. For instance, to render a form with location-dependent fields inside a dialog:
+
+{{"demo": "CustomDialogWithPayloadAdvanced.js"}}
+
## Hook API
- [`useDialogs()`](/toolpad/core/react-use-dialogs/api/)