or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

basic-modals.mdconfirm-modals.mdcontext-modals.mdhook-usage.mdindex.mdprovider-setup.md

context-modals.mddocs/

0

# Context Modals

1

2

Predefined reusable modal components registered with the provider for consistent modal experiences.

3

4

## Capabilities

5

6

### Open Context Modal

7

8

Opens a predefined modal component by key with custom properties.

9

10

```typescript { .api }

11

/**

12

* Opens a predefined context modal by key

13

* @param payload - Modal key, configuration, and inner props

14

* @returns Modal ID for future reference

15

*/

16

function openContextModal<TKey extends MantineModal>(

17

payload: OpenContextModal<Parameters<MantineModals[TKey]>[0]['innerProps']> & { modal: TKey }

18

): string;

19

20

interface OpenContextModal<CustomProps extends Record<string, any> = {}> extends ModalSettings {

21

/** Custom props passed to the modal component */

22

innerProps: CustomProps;

23

}

24

```

25

26

**Usage Examples:**

27

28

```typescript

29

import { openContextModal } from "@mantine/modals";

30

31

// Open registered context modal

32

openContextModal({

33

modal: "userProfile",

34

title: "User Profile",

35

innerProps: {

36

userId: "123",

37

editable: true,

38

},

39

});

40

41

// Context modal with custom modal properties

42

openContextModal({

43

modal: "deleteConfirmation",

44

title: "Delete Item",

45

size: "sm",

46

centered: true,

47

innerProps: {

48

itemName: "Important Document",

49

itemType: "document",

50

onConfirm: () => deleteDocument("doc-123"),

51

},

52

});

53

```

54

55

### Update Context Modal

56

57

Updates properties of an existing context modal.

58

59

```typescript { .api }

60

/**

61

* Updates properties of an existing context modal

62

* @param payload - Modal ID and updated properties

63

*/

64

function updateContextModal(

65

payload: { modalId: string } & Partial<OpenContextModal<any>>

66

): void;

67

```

68

69

**Usage Examples:**

70

71

```typescript

72

import { openContextModal, updateContextModal } from "@mantine/modals";

73

74

// Open context modal

75

const modalId = openContextModal({

76

modal: "dataEditor",

77

modalId: "editor-1",

78

title: "Edit Data",

79

innerProps: {

80

data: initialData,

81

readOnly: false,

82

},

83

});

84

85

// Update inner props

86

updateContextModal({

87

modalId: "editor-1",

88

innerProps: {

89

data: updatedData,

90

readOnly: true, // Make read-only

91

},

92

});

93

94

// Update modal properties

95

updateContextModal({

96

modalId: "editor-1",

97

title: "View Data (Read Only)",

98

size: "lg",

99

});

100

```

101

102

### Context Modal Component

103

104

Interface for creating context modal components.

105

106

```typescript { .api }

107

/**

108

* Props interface for context modal components

109

*/

110

interface ContextModalProps<T extends Record<string, any> = {}> {

111

/** Modal context providing access to modal methods */

112

context: ModalsContextProps;

113

/** Custom props passed when opening the modal */

114

innerProps: T;

115

/** Unique modal instance ID */

116

id: string;

117

}

118

```

119

120

**Creating Context Modals:**

121

122

```typescript

123

import { ContextModalProps } from "@mantine/modals";

124

import { Button, Text, TextInput, Stack } from "@mantine/core";

125

126

// User profile modal component

127

interface UserProfileProps {

128

userId: string;

129

editable?: boolean;

130

onSave?: (data: any) => void;

131

}

132

133

const UserProfileModal: React.FC<ContextModalProps<UserProfileProps>> = ({

134

context,

135

id,

136

innerProps,

137

}) => {

138

const [userData, setUserData] = useState(null);

139

const [loading, setLoading] = useState(true);

140

141

useEffect(() => {

142

// Load user data

143

loadUser(innerProps.userId).then((data) => {

144

setUserData(data);

145

setLoading(false);

146

});

147

}, [innerProps.userId]);

148

149

const handleSave = async () => {

150

if (innerProps.onSave) {

151

await innerProps.onSave(userData);

152

}

153

context.closeModal(id);

154

};

155

156

if (loading) {

157

return <Text>Loading user profile...</Text>;

158

}

159

160

return (

161

<Stack>

162

<TextInput

163

label="Name"

164

value={userData.name}

165

disabled={!innerProps.editable}

166

onChange={(e) => setUserData({ ...userData, name: e.target.value })}

167

/>

168

<TextInput

169

label="Email"

170

value={userData.email}

171

disabled={!innerProps.editable}

172

onChange={(e) => setUserData({ ...userData, email: e.target.value })}

173

/>

174

175

{innerProps.editable && (

176

<Button.Group>

177

<Button variant="default" onClick={() => context.closeModal(id)}>

178

Cancel

179

</Button>

180

<Button onClick={handleSave}>

181

Save Changes

182

</Button>

183

</Button.Group>

184

)}

185

186

{!innerProps.editable && (

187

<Button onClick={() => context.closeModal(id)}>

188

Close

189

</Button>

190

)}

191

</Stack>

192

);

193

};

194

```

195

196

### Registration and Type Safety

197

198

Register context modals with the provider and ensure type safety.

199

200

**Provider Registration:**

201

202

```typescript

203

import { ModalsProvider } from "@mantine/modals";

204

205

// Register context modals

206

<ModalsProvider

207

modals={{

208

userProfile: UserProfileModal,

209

deleteConfirmation: DeleteConfirmationModal,

210

dataEditor: DataEditorModal,

211

}}

212

>

213

<App />

214

</ModalsProvider>

215

```

216

217

**Module Augmentation for Type Safety:**

218

219

```typescript

220

// types/modals.ts

221

import { ContextModalProps } from "@mantine/modals";

222

223

declare module "@mantine/modals" {

224

interface MantineModalsOverride {

225

modals: {

226

userProfile: ContextModalProps<{

227

userId: string;

228

editable?: boolean;

229

onSave?: (data: any) => void;

230

}>;

231

deleteConfirmation: ContextModalProps<{

232

itemName: string;

233

itemType: string;

234

onConfirm: () => void;

235

}>;

236

dataEditor: ContextModalProps<{

237

data: any;

238

readOnly?: boolean;

239

onSubmit?: (data: any) => void;

240

}>;

241

};

242

}

243

}

244

```

245

246

### Advanced Context Modal Patterns

247

248

Complex context modal usage patterns and techniques.

249

250

**Dynamic Modal Loading:**

251

252

```typescript

253

// Lazy-loaded context modal

254

const LazyFormModal = lazy(() => import("./FormModal"));

255

256

const DynamicFormModal: React.FC<ContextModalProps<{ formType: string }>> = (props) => {

257

return (

258

<Suspense fallback={<Text>Loading form...</Text>}>

259

<LazyFormModal {...props} />

260

</Suspense>

261

);

262

};

263

264

// Register dynamic modal

265

<ModalsProvider

266

modals={{

267

dynamicForm: DynamicFormModal,

268

}}

269

>

270

<App />

271

</ModalsProvider>

272

```

273

274

**Modal Communication:**

275

276

```typescript

277

// Modal that opens other modals

278

const ParentModal: React.FC<ContextModalProps<{ data: any }>> = ({

279

context,

280

id,

281

innerProps,

282

}) => {

283

const openChildModal = () => {

284

context.openContextModal("childModal", {

285

title: "Child Modal",

286

innerProps: {

287

parentId: id,

288

data: innerProps.data,

289

onComplete: (result) => {

290

// Handle child modal completion

291

updateContextModal({

292

modalId: id,

293

innerProps: {

294

...innerProps,

295

data: { ...innerProps.data, ...result },

296

},

297

});

298

},

299

},

300

});

301

};

302

303

return (

304

<div>

305

<Text>Parent Modal Content</Text>

306

<Button onClick={openChildModal}>Open Child Modal</Button>

307

<Button onClick={() => context.closeModal(id)}>Close</Button>

308

</div>

309

);

310

};

311

```

312

313

**Context Modal with State Synchronization:**

314

315

```typescript

316

// Modal that syncs with external state

317

const SyncedModal: React.FC<ContextModalProps<{

318

storeId: string;

319

onStateChange: (state: any) => void;

320

}>> = ({ context, id, innerProps }) => {

321

const [localState, setLocalState] = useState({});

322

323

// Sync changes back to parent

324

useEffect(() => {

325

innerProps.onStateChange?.(localState);

326

}, [localState]);

327

328

// Listen for external updates

329

useEffect(() => {

330

const unsubscribe = subscribeToStore(innerProps.storeId, (newState) => {

331

setLocalState(newState);

332

});

333

return unsubscribe;

334

}, [innerProps.storeId]);

335

336

return (

337

<div>

338

{/* Modal content that updates localState */}

339

</div>

340

);

341

};

342

```