@iress-oss/ids-mcp-server 0.0.1-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/LICENSE.txt +201 -0
  2. package/README.md +93 -0
  3. package/dist/componentHandlers.js +241 -0
  4. package/dist/componentHandlers.test.js +380 -0
  5. package/dist/config.js +16 -0
  6. package/dist/index.js +53 -0
  7. package/dist/iressHandlers.js +144 -0
  8. package/dist/iressHandlers.test.js +316 -0
  9. package/dist/resourceHandlers.js +67 -0
  10. package/dist/resourceHandlers.test.js +352 -0
  11. package/dist/searchHandlers.js +287 -0
  12. package/dist/searchHandlers.test.js +524 -0
  13. package/dist/toolHandler.js +31 -0
  14. package/dist/toolHandler.test.js +369 -0
  15. package/dist/tools.js +165 -0
  16. package/dist/types.js +4 -0
  17. package/dist/utils.js +59 -0
  18. package/dist/utils.test.js +286 -0
  19. package/generated/docs/components-alert-docs.md +130 -0
  20. package/generated/docs/components-autocomplete-docs.md +754 -0
  21. package/generated/docs/components-autocomplete-recipes-docs.md +104 -0
  22. package/generated/docs/components-badge-docs.md +148 -0
  23. package/generated/docs/components-button-docs.md +362 -0
  24. package/generated/docs/components-button-recipes-docs.md +76 -0
  25. package/generated/docs/components-buttongroup-docs.md +310 -0
  26. package/generated/docs/components-card-docs.md +494 -0
  27. package/generated/docs/components-card-recipes-docs.md +89 -0
  28. package/generated/docs/components-checkbox-docs.md +193 -0
  29. package/generated/docs/components-checkboxgroup-docs.md +692 -0
  30. package/generated/docs/components-checkboxgroup-recipes-docs.md +119 -0
  31. package/generated/docs/components-col-docs.md +466 -0
  32. package/generated/docs/components-combobox-docs.md +1016 -0
  33. package/generated/docs/components-container-docs.md +91 -0
  34. package/generated/docs/components-divider-docs.md +176 -0
  35. package/generated/docs/components-expander-docs.md +215 -0
  36. package/generated/docs/components-field-docs.md +675 -0
  37. package/generated/docs/components-filter-docs.md +1109 -0
  38. package/generated/docs/components-form-docs.md +2442 -0
  39. package/generated/docs/components-form-recipes-docs.md +892 -0
  40. package/generated/docs/components-hide-docs.md +265 -0
  41. package/generated/docs/components-icon-docs.md +553 -0
  42. package/generated/docs/components-inline-docs.md +868 -0
  43. package/generated/docs/components-input-docs.md +335 -0
  44. package/generated/docs/components-input-recipes-docs.md +140 -0
  45. package/generated/docs/components-inputcurrency-docs.md +157 -0
  46. package/generated/docs/components-inputcurrency-recipes-docs.md +116 -0
  47. package/generated/docs/components-label-docs.md +135 -0
  48. package/generated/docs/components-menu-docs.md +704 -0
  49. package/generated/docs/components-menu-menuitem-docs.md +193 -0
  50. package/generated/docs/components-modal-docs.md +587 -0
  51. package/generated/docs/components-navbar-docs.md +291 -0
  52. package/generated/docs/components-navbar-recipes-docs.md +413 -0
  53. package/generated/docs/components-panel-docs.md +380 -0
  54. package/generated/docs/components-placeholder-docs.md +27 -0
  55. package/generated/docs/components-popover-docs.md +464 -0
  56. package/generated/docs/components-popover-recipes-docs.md +245 -0
  57. package/generated/docs/components-progress-docs.md +104 -0
  58. package/generated/docs/components-radio-docs.md +107 -0
  59. package/generated/docs/components-radiogroup-docs.md +683 -0
  60. package/generated/docs/components-readonly-docs.md +89 -0
  61. package/generated/docs/components-richselect-docs.md +2433 -0
  62. package/generated/docs/components-row-docs.md +877 -0
  63. package/generated/docs/components-select-docs.md +456 -0
  64. package/generated/docs/components-skeleton-docs.md +214 -0
  65. package/generated/docs/components-skeleton-recipes-docs.md +76 -0
  66. package/generated/docs/components-skiplink-docs.md +66 -0
  67. package/generated/docs/components-slideout-docs.md +538 -0
  68. package/generated/docs/components-slider-docs.md +346 -0
  69. package/generated/docs/components-spinner-docs.md +59 -0
  70. package/generated/docs/components-stack-docs.md +265 -0
  71. package/generated/docs/components-table-ag-grid-docs.md +2666 -0
  72. package/generated/docs/components-table-docs.md +1305 -0
  73. package/generated/docs/components-tabset-docs.md +341 -0
  74. package/generated/docs/components-tabset-tab-docs.md +86 -0
  75. package/generated/docs/components-tag-docs.md +115 -0
  76. package/generated/docs/components-text-docs.md +394 -0
  77. package/generated/docs/components-toaster-docs.md +294 -0
  78. package/generated/docs/components-toaster-toast-docs.md +157 -0
  79. package/generated/docs/components-toggle-docs.md +158 -0
  80. package/generated/docs/components-tooltip-docs.md +311 -0
  81. package/generated/docs/components-validationmessage-docs.md +241 -0
  82. package/generated/docs/contact-us-docs.md +27 -0
  83. package/generated/docs/extensions-editor-docs.md +288 -0
  84. package/generated/docs/extensions-editor-recipes-docs.md +39 -0
  85. package/generated/docs/foundations-accessibility-docs.md +62 -0
  86. package/generated/docs/foundations-colours-docs.md +257 -0
  87. package/generated/docs/foundations-consistency-docs.md +52 -0
  88. package/generated/docs/foundations-content-docs.md +23 -0
  89. package/generated/docs/foundations-introduction-docs.md +17 -0
  90. package/generated/docs/foundations-principles-docs.md +70 -0
  91. package/generated/docs/foundations-typography-docs.md +191 -0
  92. package/generated/docs/foundations-user-experience-docs.md +63 -0
  93. package/generated/docs/foundations-visual-design-docs.md +46 -0
  94. package/generated/docs/frequently-asked-questions-docs.md +53 -0
  95. package/generated/docs/get-started-develop-docs.md +48 -0
  96. package/generated/docs/get-started-using-storybook-docs.md +68 -0
  97. package/generated/docs/guidelines.md +812 -0
  98. package/generated/docs/introduction-docs.md +43 -0
  99. package/generated/docs/patterns-loading-docs.md +1304 -0
  100. package/generated/docs/resources-changelog-docs.md +6 -0
  101. package/generated/docs/resources-code-katas-docs.md +29 -0
  102. package/generated/docs/resources-migration-guides-from-v4-to-v5-docs.md +437 -0
  103. package/generated/docs/themes-available-themes-docs.md +66 -0
  104. package/generated/docs/themes-introduction-docs.md +121 -0
  105. package/generated/docs/themes-tokens-docs.md +1200 -0
  106. package/generated/docs/versions-docs.md +17 -0
  107. package/package.json +81 -0
@@ -0,0 +1,587 @@
1
+ [](#modal)Modal
2
+ ===============
3
+
4
+ Overview
5
+ --------
6
+
7
+ Modals gather information, complete a subtask, or provide additional information without losing the context of an underlying page.
8
+
9
+ Read more
10
+
11
+ [](#use-a-modal-when)Use a modal when
12
+ -------------------------------------
13
+
14
+ * Providing supplemental tasks required by the underlying page
15
+ * Providing non-essential information related to the underlying page
16
+ * Content require full attention
17
+
18
+ [](#avoid-using-a-modal-when)Avoid using a modal when
19
+ -----------------------------------------------------
20
+
21
+ * Conveying brief messages about background processes or status changes. Instead use IressAlert or IressToast.
22
+ * The modal content can be incorporated into the page without complicating the page's intent
23
+
24
+ Show modal
25
+
26
+ Hide code
27
+
28
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
29
+
30
+ const Story \= () \=> {
31
+ const { showModal } \= useModal();
32
+ const MODAL\_ID \= 'storybook-modal';
33
+ return (
34
+ <\>
35
+ <IressButton onClick\={() \=> showModal(MODAL\_ID)}\>
36
+ Show modal </IressButton\>
37
+ <IressModal
38
+ footer\="Footer slot"
39
+ id\="storybook-modal"
40
+ \>
41
+ Modal content </IressModal\>
42
+ </\>
43
+ );
44
+ };
45
+
46
+ export const App \= () \=> (
47
+ <IressModalProvider\>
48
+ <Story />
49
+ </IressModalProvider\>
50
+ );
51
+
52
+ Copy
53
+
54
+ [](#controlling-the-modal)Controlling the modal
55
+ -----------------------------------------------
56
+
57
+ ### [](#using-the-show-property)Using the `show` property
58
+
59
+ You can use state to control the modal by setting the `show` property to `true` or `false`. To sync your state with the modal, you can use the `onShowChange` prop, which is normally passed the set function from `useState`.
60
+
61
+ Show modal using state
62
+
63
+ Hide code
64
+
65
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
66
+
67
+ import { IressButton, IressModal, IressModalProps } from '@iress-oss/ids-components';
68
+ import { useState } from 'react';
69
+ export const ModalUsingState \= () \=> {
70
+ const \[show, setShow\] \= useState(false);
71
+ return (
72
+ <\>
73
+ <IressButton onClick\={() \=> setShow(true)}\>
74
+ Show modal using state </IressButton\>
75
+ <IressModal
76
+ {...{
77
+ children: 'This modal was opened via state',
78
+ }}
79
+ show\={show}
80
+ onShowChange\={setShow}
81
+ footer\={<IressButton onClick\={() \=> setShow(false)}\>Close</IressButton\>}
82
+ />
83
+ </\>
84
+ );
85
+ };
86
+
87
+ Copy
88
+
89
+ ### [](#using-the-iressmodalprovider)Using the `IressModalProvider`
90
+
91
+ You can use the `IressModalProvider` to open and close modals from anywhere in your application, as long as the modal has a unique `id`. In this case you would use the `useModal` hook to open and close the modal.
92
+
93
+ To use, wrap your `<App/>` or the component that you want to use the `useModal` hook with `<IressModalProvider />`.
94
+
95
+ Show modal using provider
96
+
97
+ Hide code
98
+
99
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
100
+
101
+ import {
102
+ IressButton,
103
+ IressModal,
104
+ IressModalProps,
105
+ IressModalProvider,
106
+ useModal,
107
+ } from '@iress-oss/ids-components';
108
+ const MODAL\_ID \= 'storybook-modal';
109
+ export const App \= (modalProps: IressModalProps) \=> (
110
+ <IressModalProvider\>
111
+ <ModalWithTrigger {...modalProps} />
112
+ </IressModalProvider\>
113
+ );
114
+ const ModalWithTrigger \= ({
115
+ id \= MODAL\_ID,
116
+ ...modalProps
117
+ }: IressModalProps) \=> {
118
+ const { showModal } \= useModal();
119
+ return (
120
+ <\>
121
+ <IressButton onClick\={() \=> showModal(id)}\>
122
+ Show modal using provider </IressButton\>
123
+ <IressModal
124
+ {...modalProps}
125
+ id\={id}
126
+ footer\={
127
+ <IressButton onClick\={() \=> showModal(id, false)}\>Close</IressButton\>
128
+ }
129
+ \>
130
+ {modalProps.children ?? 'Modal content'}
131
+ </IressModal\>
132
+ </\>
133
+ );
134
+ };
135
+
136
+ Copy
137
+
138
+ [](#behaviour)Behaviour
139
+ -----------------------
140
+
141
+ * No other interaction on the main page can be accessed while a modal is active. A backdrop covers the content beneath so that the content beneath cannot be interacted with.
142
+ * Clicking on the the backdrop closes the modal and returns the focus to the triggering element.
143
+ * When the modal is active the body is set to overflow: hidden to stop any scrolling of the underlying page. Scrolling should then only be possible on the modal wrapper.
144
+ * By default there are 3 ways to dismiss the modal; click X in the header; press ESC on a keyboard; click anywhere on the backdrop. It is also recommended that consumers add a Cancel or Close button to the modal's footer slot if required.
145
+
146
+ [](#examples)Examples
147
+ ---------------------
148
+
149
+ ### [](#footer-slot)Footer slot
150
+
151
+ Content to appear underneath the main content. Usually used for extra controls like buttons etc.
152
+
153
+ Footer slot modal
154
+
155
+ Hide code
156
+
157
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
158
+
159
+ const Story \= () \=> {
160
+ const { showModal } \= useModal();
161
+ const MODAL\_ID \= 'storybook-modal';
162
+ return (
163
+ <\>
164
+ <IressButton onClick\={() \=> showModal(MODAL\_ID)}\>
165
+ Footer slot modal </IressButton\>
166
+ <IressModal
167
+ footer\={<IressButton\>Button in footer</IressButton\>}
168
+ id\="storybook-modal"
169
+ \>
170
+ Normal modal content </IressModal\>
171
+ </\>
172
+ );
173
+ };
174
+
175
+ export const App \= () \=> (
176
+ <IressModalProvider\>
177
+ <Story />
178
+ </IressModalProvider\>
179
+ );
180
+
181
+ Copy
182
+
183
+ ### [](#fixed-footer)Fixed footer
184
+
185
+ The `fixedFooter` prop can be used to set the footer to be fixed to the bottom of the modal. This is often useful when there is a lot of content in the main area that you would like to scroll underneath the footer content.
186
+
187
+ **Note:** Also works without footer content.
188
+
189
+ Using with popovers and tooltips
190
+ --------------------------------
191
+
192
+ The fixed footer variant of IressModal prevents content from overflowing the modal. This can cause layout issues when using with components that use popovers (for example IressCombobox), especially when these components sit at the end of the modal's content. If you encounter these issues, try using a modal without a fixed footer. Normal modals allow content to overflow, which should fix the issue.
193
+
194
+ Fixed footer modal
195
+
196
+ Hide code
197
+
198
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
199
+
200
+ const Story \= () \=> {
201
+ const { showModal } \= useModal();
202
+ const MODAL\_ID \= 'storybook-modal';
203
+ return (
204
+ <\>
205
+ <IressButton onClick\={() \=> showModal(MODAL\_ID)}\>
206
+ Fixed footer modal </IressButton\>
207
+ <IressModal
208
+ fixedFooter
209
+ footer\={<IressButton\>Button in footer</IressButton\>}
210
+ id\="storybook-modal"
211
+ \>
212
+ <React.Fragment key\=".0"\>
213
+ <IressText element\="h2"\>
214
+ Next Saturday night, we're sending you back to the future </IressText\>
215
+ <IressText\>
216
+ <p\>
217
+ I still don't understand, how am I supposed to go to the dance with her, if she's already going to the dance with you. Alright, okay Jennifer. What if I send in the tape and they don't like it. I mean, what if they say I'm no good. What if they say, 'Get out of here, kid, you got no future.' I mean, I just don't think I can take that kind of rejection. Jesus, I'm beginning to sound like my old man. Ahh. Alright, take it up, go. Doc. This is it. This is the answer. It says here that a bolt of lightning is gonna strike the clock tower precisely at 10:04 p.m. next Saturday night. If we could somehow harness this bolt of lightning, channel it into the flux capacitor, it just might work. Next Saturday night, we're sending you back to the future. </p\>
218
+ <p\>
219
+ Go. Yeah, it's in the back. The future, it's where you're going? Mother, with Marty's parents out of town, don't you think he oughta spend the night, after all, Dad almost killed him with the car. What's going on? Where have you been all week? </p\>
220
+ <p\>
221
+ But I can't go to the dance, I'll miss my favorite television program, Science Fiction Theater. Well uh, good, fine. Ahh. Ahh. Right, okay, so right around 9:00 she's gonna get very angry with me. That's right. </p\>
222
+ <h3\>
223
+ I just don't think I can take that kind of rejection </h3\>
224
+ <p\>
225
+ I still don't understand, how am I supposed to go to the dance with her, if she's already going to the dance with you. Alright, okay Jennifer. What if I send in the tape and they don't like it. I mean, what if they say I'm no good. What if they say, 'Get out of here, kid, you got no future.' I mean, I just don't think I can take that kind of rejection. Jesus, I'm beginning to sound like my old man. Ahh. Alright, take it up, go. Doc. This is it. This is the answer. It says here that a bolt of lightning is gonna strike the clock tower precisely at 10:04 p.m. next Saturday night. If we could somehow harness this bolt of lightning, channel it into the flux capacitor, it just might work. Next Saturday night, we're sending you back to the future. </p\>
226
+ <p\>
227
+ Go. Yeah, it's in the back. The future, it's where you're going? Mother, with Marty's parents out of town, don't you think he oughta spend the night, after all, Dad almost killed him with the car. What's going on? Where have you been all week? </p\>
228
+ <p\>
229
+ But I can't go to the dance, I'll miss my favorite television program, Science Fiction Theater. Well uh, good, fine. Ahh. Ahh. Right, okay, so right around 9:00 she's gonna get very angry with me. That's right. </p\>
230
+ <p\>
231
+ I still don't understand, how am I supposed to go to the dance with her, if she's already going to the dance with you. Alright, okay Jennifer. What if I send in the tape and they don't like it. I mean, what if they say I'm no good. What if they say, 'Get out of here, kid, you got no future.' I mean, I just don't think I can take that kind of rejection. Jesus, I'm beginning to sound like my old man. Ahh. Alright, take it up, go. Doc. This is it. This is the answer. It says here that a bolt of lightning is gonna strike the clock tower precisely at 10:04 p.m. next Saturday night. If we could somehow harness this bolt of lightning, channel it into the flux capacitor, it just might work. Next Saturday night, we're sending you back to the future. </p\>
232
+ <p\>
233
+ Go. Yeah, it's in the back. The future, it's where you're going? Mother, with Marty's parents out of town, don't you think he oughta spend the night, after all, Dad almost killed him with the car. What's going on? Where have you been all week? </p\>
234
+ <p\>
235
+ But I can't go to the dance, I'll miss my favorite television program, Science Fiction Theater. Well uh, good, fine. Ahh. Ahh. Right, okay, so right around 9:00 she's gonna get very angry with me. That's right. </p\>
236
+ <p\>
237
+ I still don't understand, how am I supposed to go to the dance with her, if she's already going to the dance with you. Alright, okay Jennifer. What if I send in the tape and they don't like it. I mean, what if they say I'm no good. What if they say, 'Get out of here, kid, you got no future.' I mean, I just don't think I can take that kind of rejection. Jesus, I'm beginning to sound like my old man. Ahh. Alright, take it up, go. Doc. This is it. This is the answer. It says here that a bolt of lightning is gonna strike the clock tower precisely at 10:04 p.m. next Saturday night. If we could somehow harness this bolt of lightning, channel it into the flux capacitor, it just might work. Next Saturday night, we're sending you back to the future. </p\>
238
+ </IressText\>
239
+ </React.Fragment\>
240
+ </IressModal\>
241
+ </\>
242
+ );
243
+ };
244
+
245
+ export const App \= () \=> (
246
+ <IressModalProvider\>
247
+ <Story />
248
+ </IressModalProvider\>
249
+ );
250
+
251
+ Copy
252
+
253
+ ### [](#size)Size
254
+
255
+ The `size` prop can be set to `sm`, `md`, `lg` or `fullpage`. It defaults to `md`.
256
+
257
+ smmdlgfullpage
258
+
259
+ Hide code
260
+
261
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
262
+
263
+ const ModalWithTrigger \= () \=> {
264
+ const { showModal } \= useModal();
265
+ return (
266
+ <IressInline gutter\="md"\>
267
+ {MODAL\_SIZES.map((size) \=> (
268
+ <\>
269
+ <IressButton onClick\={() \=> showModal(size)}\>{size}</IressButton\>
270
+ <IressModal id\={size} size\={size}\>
271
+ {size} modal </IressModal\>
272
+ </\>
273
+ ))}
274
+ </IressInline\>
275
+ );
276
+ };
277
+ export const ModalSizes \= () \=> (
278
+ <IressModalProvider\>
279
+ <ModalWithTrigger />
280
+ </IressModalProvider\>
281
+ );
282
+
283
+ Copy
284
+
285
+ ### [](#responsive-size)Responsive size
286
+
287
+ The `size` prop can take an object that takes five key/value pairs that correlate with the IDS breakpoints.
288
+
289
+ If you set a responsive `size`, the modal becomes full width on screens smaller than the value you specified. For example, if you want to create a large modal on medium screens and above:
290
+
291
+ \[data-radix-scroll-area-viewport\] {
292
+ scrollbar-width: none;
293
+ -ms-overflow-style: none;
294
+ -webkit-overflow-scrolling: touch;
295
+ }
296
+ \[data-radix-scroll-area-viewport\]::-webkit-scrollbar {
297
+ display: none;
298
+ }
299
+ :where(\[data-radix-scroll-area-viewport\]) {
300
+ display: flex;
301
+ flex-direction: column;
302
+ align-items: stretch;
303
+ }
304
+ :where(\[data-radix-scroll-area-content\]) {
305
+ flex-grow: 1;
306
+ }
307
+
308
+ <IressModal size\={{ md: IressModal.Size.Lg }}\>
309
+
310
+ Copy
311
+
312
+ The modal will be full width on extra-small and small screens, and large width on medium, large and extra-large screens. This is the same as setting:
313
+
314
+ \[data-radix-scroll-area-viewport\] {
315
+ scrollbar-width: none;
316
+ -ms-overflow-style: none;
317
+ -webkit-overflow-scrolling: touch;
318
+ }
319
+ \[data-radix-scroll-area-viewport\]::-webkit-scrollbar {
320
+ display: none;
321
+ }
322
+ :where(\[data-radix-scroll-area-viewport\]) {
323
+ display: flex;
324
+ flex-direction: column;
325
+ align-items: stretch;
326
+ }
327
+ :where(\[data-radix-scroll-area-content\]) {
328
+ flex-grow: 1;
329
+ }
330
+
331
+ <IressModal size\={{ xs: IressModal.Size.Fullpage, md: IressModal.Size.Lg }}\>
332
+
333
+ Copy
334
+
335
+ You can override this behaviour by specifying a value for `xs` in your size object:
336
+
337
+ \[data-radix-scroll-area-viewport\] {
338
+ scrollbar-width: none;
339
+ -ms-overflow-style: none;
340
+ -webkit-overflow-scrolling: touch;
341
+ }
342
+ \[data-radix-scroll-area-viewport\]::-webkit-scrollbar {
343
+ display: none;
344
+ }
345
+ :where(\[data-radix-scroll-area-viewport\]) {
346
+ display: flex;
347
+ flex-direction: column;
348
+ align-items: stretch;
349
+ }
350
+ :where(\[data-radix-scroll-area-content\]) {
351
+ flex-grow: 1;
352
+ }
353
+
354
+ <IressModal size\={{ xs: IressModal.Size.Sm, md: IressModal.Size.Lg }}\>
355
+
356
+ Copy
357
+
358
+ Responsive modal
359
+
360
+ Hide code
361
+
362
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
363
+
364
+ const Story \= () \=> {
365
+ const { showModal } \= useModal();
366
+ const MODAL\_ID \= 'storybook-modal';
367
+ return (
368
+ <\>
369
+ <IressButton onClick\={() \=> showModal(MODAL\_ID)}\>
370
+ Responsive modal </IressButton\>
371
+ <IressModal
372
+ footer\=""
373
+ id\="storybook-modal"
374
+ size\={{
375
+ lg: 'md',
376
+ md: 'sm',
377
+ xl: 'lg'
378
+ }}
379
+ \>
380
+ <CurrentBreakpoint />
381
+ </IressModal\>
382
+ </\>
383
+ );
384
+ };
385
+
386
+ export const App \= () \=> (
387
+ <IressModalProvider\>
388
+ <Story />
389
+ </IressModalProvider\>
390
+ );
391
+
392
+ Copy
393
+
394
+ ### [](#padding)Padding
395
+
396
+ The `padding` prop can be set to either `none`, `sm`, `md` or `lg`. It defaults to `md`.
397
+
398
+ none paddingsm paddingmd paddinglg padding
399
+
400
+ Hide code
401
+
402
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
403
+
404
+ const ModalWithTrigger \= () \=> {
405
+ const { showModal } \= useModal();
406
+ return (
407
+ <IressInline gutter\="md"\>
408
+ {PADDING\_SIZES.map((size) \=> (
409
+ <\>
410
+ <IressButton onClick\={() \=> showModal(size)}\>
411
+ {size} padding </IressButton\>
412
+ <IressModal id\={size} padding\={size}\>
413
+ {size} padded modal </IressModal\>
414
+ </\>
415
+ ))}
416
+ </IressInline\>
417
+ );
418
+ };
419
+ export const ModalPaddings \= () \=> (
420
+ <IressModalProvider\>
421
+ <ModalWithTrigger />
422
+ </IressModalProvider\>
423
+ );
424
+
425
+ Copy
426
+
427
+ ### [](#disable-closing)Disable closing
428
+
429
+ For instances where you require the user's full attention and you want to ensure they continue the current task before closing the modal, you can disable the backdrop and escape key using `disableBackdropClick` and/or hide the close button using `noCloseButton`.
430
+
431
+ **Note:** As these options remove the default handling of the closing the modal, please ensure you provide a clear way for the user to close the modal.
432
+
433
+ Disable backdrop clickNo close button (please provide one, if you decide to hide the close button)Both (If you hide the close button, ensure you provide another way to close the modal)
434
+
435
+ Hide code
436
+
437
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
438
+
439
+ const Story \= () \=> {
440
+ const { showModal } \= useModal();
441
+ const MODAL\_ID \= 'storybook-modal';
442
+ return (
443
+ <IressStack gutter\="md"\>
444
+ <IressButton
445
+ fluid
446
+ onClick\={() \=> showModal("disable-backdrop-click")}
447
+ \>
448
+ Disable backdrop click </IressButton\>
449
+ <IressModal
450
+ disableBackdropClick
451
+ footer\="Footer slot"
452
+ id\="disable-backdrop-click"
453
+ \>
454
+ Modal content </IressModal\>
455
+ <IressButton
456
+ fluid
457
+ onClick\={() \=> showModal("no-close-button")}
458
+ \>
459
+ No close button (please provide one, if you decide to hide the close button) </IressButton\>
460
+ <IressModal
461
+ footer\={<IressButton onClick\={() \=> showModal("no-close-button", false)}\>Close</IressButton\>}
462
+ id\="no-close-button"
463
+ noCloseButton
464
+ \>
465
+ Modal content </IressModal\>
466
+ <IressButton
467
+ fluid
468
+ onClick\={() \=> showModal("both")}
469
+ \>
470
+ Both (If you hide the close button, ensure you provide another way to close the modal) </IressButton\>
471
+ <IressModal
472
+ disableBackdropClick
473
+ footer\={<IressButton onClick\={() \=> showModal("both", false)}\>Close</IressButton\>}
474
+ id\="both"
475
+ noCloseButton
476
+ \>
477
+ Modal content </IressModal\>
478
+ </IressStack\>
479
+ );
480
+ };
481
+
482
+ export const App \= () \=> (
483
+ <IressModalProvider\>
484
+ <Story />
485
+ </IressModalProvider\>
486
+ );
487
+
488
+ Copy
489
+
490
+ [](#migrating-to-version-5)Migrating to version 5
491
+ -------------------------------------------------
492
+
493
+ ### [](#adding-the-provider)Adding the provider
494
+
495
+ For your components to work as previously, you will need to set up the `IressModalProvider` at the root of your application. This will allow you to use the `useModal` hook to open and close modals from anywhere in your application using the ID of the modal.
496
+
497
+ \[data-radix-scroll-area-viewport\] {
498
+ scrollbar-width: none;
499
+ -ms-overflow-style: none;
500
+ -webkit-overflow-scrolling: touch;
501
+ }
502
+ \[data-radix-scroll-area-viewport\]::-webkit-scrollbar {
503
+ display: none;
504
+ }
505
+ :where(\[data-radix-scroll-area-viewport\]) {
506
+ display: flex;
507
+ flex-direction: column;
508
+ align-items: stretch;
509
+ }
510
+ :where(\[data-radix-scroll-area-content\]) {
511
+ flex-grow: 1;
512
+ }
513
+
514
+ const App \= () \=> <IressModalProvider\>Rest of app here</IressModalProvider\>;
515
+
516
+ Copy
517
+
518
+ ### [](#testing)Testing
519
+
520
+ In version 5, modals are rendered conditionally, meaning they will not be available in the DOM until they are shown. This means that you will need to update your tests to account for this, as you cannot interact with its contents until it is shown, unlike in version 4.
521
+
522
+ See below for an example in version 4 and version 5.
523
+
524
+ Mode
525
+
526
+ DiffOldNew
527
+
528
+ <table class="css-1n5o7vh-diff-container"><tbody><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text">import { render, waitFor, screen } from '@testing-library/react';</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text">import { render, screen, waitForElementToBeRemoved } from '@testing-library/react';</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text">import { idsFireEvent, componentLoad } from '@iress/ids-react-test-utils';</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text">import { userEvent } from '@testing-library/user-event';</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text">test('opening and closing a modal', async () =&gt; {</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> await componentLoad([</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> const trigger = screen.getByRole('button', { name: /open modal/i });</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> 'modal-trigger',</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> 'modal',</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> // activate modal</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> ]);</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> await userEvent.click(trigger);</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> const modal = await screen.findByRole('dialog');</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> const trigger = screen.getByTestId('modal-trigger');</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> const modal = screen.getByTestId('modal');</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> // In version 5, you can only interact with the modal once it has been loaded here.</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-10regm7-empty-line"><pre></pre></td><td class="css-vl0irh-content css-10regm7-empty-line"><pre class="css-o1u8iu-content-text"></pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-10regm7-empty-line"><pre></pre></td><td class="css-vl0irh-content css-10regm7-empty-line"><pre class="css-o1u8iu-content-text"></pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> // In version 4, you can already interact with the modal here as its in the DOM at this stage.</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> // activate modal</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> idsFireEvent.click(trigger);</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> await waitFor(() =&gt; expect(modal).toBeVisible());</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> // close modal</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> const closeButton = screen.getByTestId('modal__close-button');</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> const closeButton = screen.getByRole('button', { name: /close/i });</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> idsFireEvent.click(closeButton);</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> await userEvent.click(closeButton);</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> await waitFor(() =&gt; expect(modal).not.toBeVisible());</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> await waitForElementToBeRemoved(modal);</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text">});</pre></td></tr></tbody></table>
529
+
530
+ ### [](#speed-up-tests)Speed up tests
531
+
532
+ You can speed up tests by wrapping your tests in a provider that overrides the theme tokens for animations.
533
+
534
+ \[data-radix-scroll-area-viewport\] {
535
+ scrollbar-width: none;
536
+ -ms-overflow-style: none;
537
+ -webkit-overflow-scrolling: touch;
538
+ }
539
+ \[data-radix-scroll-area-viewport\]::-webkit-scrollbar {
540
+ display: none;
541
+ }
542
+ :where(\[data-radix-scroll-area-viewport\]) {
543
+ display: flex;
544
+ flex-direction: column;
545
+ align-items: stretch;
546
+ }
547
+ :where(\[data-radix-scroll-area-content\]) {
548
+ flex-grow: 1;
549
+ }
550
+
551
+ const themeOverrides: Record<string, string\> \= {
552
+ '--iress-backdrop-transition-duration': '0s',
553
+ };
554
+ export const TestAppProvider \= ({ children }: PropsWithChildren) \=> {
555
+ const containerRef \= useRef<HTMLDivElement\>(null);
556
+ return (
557
+ <IressModalProvider container\={containerRef}\>
558
+ <div style\={themeOverrides} ref\={containerRef}\>
559
+ {children}
560
+ </div\>
561
+ </IressModalProvider\>
562
+ );
563
+ };
564
+
565
+ Copy
566
+
567
+ On this page
568
+
569
+ * [Overview](#overview)
570
+ * [Use a modal when](#use-a-modal-when)
571
+ * [Avoid using a modal when](#avoid-using-a-modal-when)
572
+ * [Props](#props)
573
+ * [Controlling the modal](#controlling-the-modal)
574
+ * [Using the show property](#using-the-show-property)
575
+ * [Using the IressModalProvider](#using-the-iressmodalprovider)
576
+ * [Behaviour](#behaviour)
577
+ * [Examples](#examples)
578
+ * [Footer slot](#footer-slot)
579
+ * [Fixed footer](#fixed-footer)
580
+ * [Size](#size)
581
+ * [Responsive size](#responsive-size)
582
+ * [Padding](#padding)
583
+ * [Disable closing](#disable-closing)
584
+ * [Migrating to version 5](#migrating-to-version-5)
585
+ * [Adding the provider](#adding-the-provider)
586
+ * [Testing](#testing)
587
+ * [Speed up tests](#speed-up-tests)