@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,286 @@
1
+ /**
2
+ * Tests for utility functions
3
+ */
4
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
5
+ import * as fs from 'fs';
6
+ import { getMarkdownFiles, mapIressComponentToFile, extractIressComponents, readFileContent, fileExists, } from './utils.js';
7
+ // Mock fs module
8
+ vi.mock('fs');
9
+ vi.mock('./config.js', () => ({
10
+ DOCS_DIR: '/mock/docs/dir',
11
+ }));
12
+ const mockedFs = vi.mocked(fs);
13
+ // Test helper functions and types
14
+ const createComponentMapping = (componentName, filePath) => ({
15
+ componentName,
16
+ filePath,
17
+ });
18
+ const mockFileList = [
19
+ 'components-button-docs.md',
20
+ 'components-input-docs.md',
21
+ 'components-card-docs.md',
22
+ ];
23
+ // Type for fs.readdirSync return value to avoid repetitive eslint-disable comments
24
+ const createMockFileArray = (...files) => files.filter((file) => file != null);
25
+ describe('utils', () => {
26
+ beforeEach(() => {
27
+ vi.clearAllMocks();
28
+ });
29
+ afterEach(() => {
30
+ vi.restoreAllMocks();
31
+ });
32
+ describe('getMarkdownFiles', () => {
33
+ it('should return empty array when docs directory does not exist', () => {
34
+ mockedFs.existsSync.mockReturnValue(false);
35
+ const result = getMarkdownFiles();
36
+ expect(result).toEqual([]);
37
+ expect(fs.existsSync).toHaveBeenCalledWith('/mock/docs/dir');
38
+ });
39
+ it('should return markdown files when directory exists', () => {
40
+ mockedFs.existsSync.mockReturnValue(true);
41
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-button-docs.md', 'components-input-docs.md', 'other-file.txt', 'nested/components-card-docs.md', Buffer.from('buffer-file')));
42
+ const result = getMarkdownFiles();
43
+ expect(result).toEqual([
44
+ 'components-button-docs.md',
45
+ 'components-input-docs.md',
46
+ 'nested/components-card-docs.md',
47
+ ]);
48
+ expect(fs.readdirSync).toHaveBeenCalledWith('/mock/docs/dir', {
49
+ recursive: true,
50
+ });
51
+ });
52
+ it('should handle errors gracefully', () => {
53
+ mockedFs.existsSync.mockReturnValue(true);
54
+ mockedFs.readdirSync.mockImplementation(() => {
55
+ throw new Error('Read error');
56
+ });
57
+ const consoleSpy = vi
58
+ .spyOn(console, 'error')
59
+ .mockImplementation(() => { });
60
+ const result = getMarkdownFiles();
61
+ expect(result).toEqual([]);
62
+ expect(consoleSpy).toHaveBeenCalledWith('Error reading docs directory:', expect.any(Error));
63
+ });
64
+ it('should filter out non-string entries from directory listing', () => {
65
+ mockedFs.existsSync.mockReturnValue(true);
66
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('file1.md', Buffer.from('buffer'), 'file2.md', null, undefined, 'file3.txt'));
67
+ const result = getMarkdownFiles();
68
+ expect(result).toEqual(['file1.md', 'file2.md']);
69
+ });
70
+ });
71
+ describe('mapIressComponentToFile', () => {
72
+ beforeEach(() => {
73
+ mockedFs.existsSync.mockReturnValue(true);
74
+ });
75
+ it('should find exact match for component', () => {
76
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray(...mockFileList));
77
+ const mapping = createComponentMapping('IressButton', 'components-button-docs.md');
78
+ const result = mapIressComponentToFile(mapping.componentName);
79
+ expect(result).toBe(mapping.filePath);
80
+ });
81
+ it('should find partial match when exact match is not available', () => {
82
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-button-advanced-docs.md', 'components-input-docs.md'));
83
+ const mapping = createComponentMapping('IressButton', 'components-button-advanced-docs.md');
84
+ const result = mapIressComponentToFile(mapping.componentName);
85
+ expect(result).toBe(mapping.filePath);
86
+ });
87
+ it('should find fuzzy match when exact and partial matches are not available', () => {
88
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-custom-button-docs.md', 'components-input-docs.md'));
89
+ const mapping = createComponentMapping('IressButton', 'components-custom-button-docs.md');
90
+ const result = mapIressComponentToFile(mapping.componentName);
91
+ expect(result).toBe(mapping.filePath);
92
+ });
93
+ it('should return null when no match is found', () => {
94
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-input-docs.md', 'components-card-docs.md'));
95
+ const mapping = createComponentMapping('IressButton', null);
96
+ const result = mapIressComponentToFile(mapping.componentName);
97
+ expect(result).toBe(mapping.filePath);
98
+ });
99
+ it('should handle component names without Iress prefix', () => {
100
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-button-docs.md'));
101
+ const mapping = createComponentMapping('Button', 'components-button-docs.md');
102
+ const result = mapIressComponentToFile(mapping.componentName);
103
+ expect(result).toBe(mapping.filePath);
104
+ });
105
+ it('should handle camelCase to lowercase conversion correctly', () => {
106
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-datepicker-docs.md'));
107
+ const mapping = createComponentMapping('IressDatePicker', 'components-datepicker-docs.md');
108
+ const result = mapIressComponentToFile(mapping.componentName);
109
+ expect(result).toBe(mapping.filePath);
110
+ });
111
+ it('should prioritize exact match over partial match', () => {
112
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-button-docs.md', 'components-button-advanced-docs.md'));
113
+ const mapping = createComponentMapping('IressButton', 'components-button-docs.md');
114
+ const result = mapIressComponentToFile(mapping.componentName);
115
+ expect(result).toBe(mapping.filePath);
116
+ });
117
+ it('should prioritize partial match over fuzzy match', () => {
118
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-custom-button-docs.md', 'components-button-advanced-docs.md'));
119
+ const mapping = createComponentMapping('IressButton', 'components-button-advanced-docs.md');
120
+ const result = mapIressComponentToFile(mapping.componentName);
121
+ expect(result).toBe(mapping.filePath);
122
+ });
123
+ });
124
+ describe('extractIressComponents', () => {
125
+ it('should extract Iress component names from text', () => {
126
+ const text = `
127
+ Use IressButton for actions and IressInput for text entry.
128
+ You can also use IressCard to display content.
129
+ `;
130
+ const result = extractIressComponents(text);
131
+ expect(result).toEqual(['IressButton', 'IressInput', 'IressCard']);
132
+ });
133
+ it('should handle empty text', () => {
134
+ const result = extractIressComponents('');
135
+ expect(result).toEqual([]);
136
+ });
137
+ it('should handle text without Iress components', () => {
138
+ const text = 'This is just regular text with no components.';
139
+ const result = extractIressComponents(text);
140
+ expect(result).toEqual([]);
141
+ });
142
+ it('should remove duplicate component names', () => {
143
+ const text = `
144
+ Use IressButton here and IressButton there.
145
+ Also use IressInput and IressButton again.
146
+ `;
147
+ const result = extractIressComponents(text);
148
+ expect(result).toEqual(['IressButton', 'IressInput']);
149
+ });
150
+ it('should match component names with various cases', () => {
151
+ const text = `
152
+ IressA, IressB, IressC, IressABC, IressXYZ,
153
+ IressCamelCase, IressPascalCase
154
+ `;
155
+ const result = extractIressComponents(text);
156
+ expect(result).toEqual([
157
+ 'IressA',
158
+ 'IressB',
159
+ 'IressC',
160
+ 'IressABC',
161
+ 'IressXYZ',
162
+ 'IressCamelCase',
163
+ 'IressPascalCase',
164
+ ]);
165
+ });
166
+ it('should match component names according to current implementation', () => {
167
+ const text = 'ThisIressButtonIsNotValid and IressButton is valid';
168
+ const result = extractIressComponents(text);
169
+ // Current implementation matches any "Iress" followed by capital letter and additional letters
170
+ // This includes compound words like "IressButtonIsNotValid"
171
+ expect(result).toEqual(['IressButtonIsNotValid', 'IressButton']);
172
+ });
173
+ it('should handle special characters and boundaries', () => {
174
+ const text = `
175
+ <IressButton>Click me</IressButton>
176
+ {IressInput}
177
+ IressCard.
178
+ IressModal,
179
+ IressDialog;
180
+ IressTooltip!
181
+ IressForm?
182
+ `;
183
+ const result = extractIressComponents(text);
184
+ expect(result).toEqual([
185
+ 'IressButton',
186
+ 'IressInput',
187
+ 'IressCard',
188
+ 'IressModal',
189
+ 'IressDialog',
190
+ 'IressTooltip',
191
+ 'IressForm',
192
+ ]);
193
+ });
194
+ });
195
+ describe('readFileContent', () => {
196
+ it('should read file content successfully', () => {
197
+ const mockContent = 'Mock file content';
198
+ mockedFs.readFileSync.mockReturnValue(mockContent);
199
+ const result = readFileContent('/path/to/file.txt');
200
+ expect(result).toBe(mockContent);
201
+ expect(fs.readFileSync).toHaveBeenCalledWith('/path/to/file.txt', 'utf-8');
202
+ });
203
+ it('should propagate file system errors', () => {
204
+ const error = new Error('File not found');
205
+ mockedFs.readFileSync.mockImplementation(() => {
206
+ throw error;
207
+ });
208
+ expect(() => readFileContent('/nonexistent/file.txt')).toThrow('File not found');
209
+ });
210
+ it('should handle different file paths', () => {
211
+ mockedFs.readFileSync.mockReturnValue('content');
212
+ readFileContent('/absolute/path/file.txt');
213
+ expect(fs.readFileSync).toHaveBeenCalledWith('/absolute/path/file.txt', 'utf-8');
214
+ readFileContent('relative/path/file.txt');
215
+ expect(fs.readFileSync).toHaveBeenCalledWith('relative/path/file.txt', 'utf-8');
216
+ });
217
+ });
218
+ describe('fileExists', () => {
219
+ it('should return true when file exists', () => {
220
+ mockedFs.existsSync.mockReturnValue(true);
221
+ const result = fileExists('/path/to/file.txt');
222
+ expect(result).toBe(true);
223
+ expect(fs.existsSync).toHaveBeenCalledWith('/path/to/file.txt');
224
+ });
225
+ it('should return false when file does not exist', () => {
226
+ mockedFs.existsSync.mockReturnValue(false);
227
+ const result = fileExists('/nonexistent/file.txt');
228
+ expect(result).toBe(false);
229
+ expect(fs.existsSync).toHaveBeenCalledWith('/nonexistent/file.txt');
230
+ });
231
+ it('should handle different file paths', () => {
232
+ mockedFs.existsSync.mockReturnValue(true);
233
+ fileExists('/absolute/path/file.txt');
234
+ expect(fs.existsSync).toHaveBeenCalledWith('/absolute/path/file.txt');
235
+ fileExists('relative/path/file.txt');
236
+ expect(fs.existsSync).toHaveBeenCalledWith('relative/path/file.txt');
237
+ });
238
+ it('should handle edge cases', () => {
239
+ mockedFs.existsSync.mockReturnValue(false);
240
+ expect(fileExists('')).toBe(false);
241
+ expect(fileExists(' ')).toBe(false);
242
+ expect(fileExists('.')).toBe(false);
243
+ expect(fileExists('..')).toBe(false);
244
+ });
245
+ });
246
+ describe('type safety and helper functions', () => {
247
+ it('should create valid ComponentMapping objects', () => {
248
+ const validMapping = createComponentMapping('IressButton', 'components-button-docs.md');
249
+ const nullMapping = createComponentMapping('IressNonExistent', null);
250
+ expect(validMapping).toEqual({
251
+ componentName: 'IressButton',
252
+ filePath: 'components-button-docs.md',
253
+ });
254
+ expect(nullMapping).toEqual({
255
+ componentName: 'IressNonExistent',
256
+ filePath: null,
257
+ });
258
+ });
259
+ it('should work with mock file list type', () => {
260
+ const mockFile = 'components-button-docs.md';
261
+ expect(mockFileList).toContain(mockFile);
262
+ // Type checking ensures we can only use valid file names
263
+ expect(typeof mockFile).toBe('string');
264
+ expect(mockFile.endsWith('.md')).toBe(true);
265
+ });
266
+ it('should demonstrate type-safe component mapping workflow', () => {
267
+ mockedFs.existsSync.mockReturnValue(true);
268
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray(...mockFileList));
269
+ const componentMappings = [
270
+ createComponentMapping('IressButton', null),
271
+ createComponentMapping('IressInput', null),
272
+ createComponentMapping('IressCard', null),
273
+ ];
274
+ // Test that all components get properly mapped
275
+ const results = componentMappings.map((mapping) => ({
276
+ ...mapping,
277
+ filePath: mapIressComponentToFile(mapping.componentName),
278
+ }));
279
+ expect(results).toEqual([
280
+ { componentName: 'IressButton', filePath: 'components-button-docs.md' },
281
+ { componentName: 'IressInput', filePath: 'components-input-docs.md' },
282
+ { componentName: 'IressCard', filePath: 'components-card-docs.md' },
283
+ ]);
284
+ });
285
+ });
286
+ });
@@ -0,0 +1,130 @@
1
+ [](#alert)Alert
2
+ ===============
3
+
4
+ Overview
5
+ --------
6
+
7
+ An alert displays a short, important message in a way that attracts the user's attention without interrupting the user's task.
8
+
9
+ This is a simple info alert
10
+
11
+ Hide code
12
+
13
+ \[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; }
14
+
15
+ <IressAlert
16
+ footer\=""
17
+ heading\=""
18
+ status\="info"
19
+ \>
20
+ This is a simple info alert
21
+ </IressAlert\>
22
+
23
+ Copy
24
+
25
+ [](#examples)Examples
26
+ ---------------------
27
+
28
+ ### [](#status)Status
29
+
30
+ The alert offers four statuses that set a distinctive colour and icon. They can be set using the `status` prop. Their different use cases are described here.
31
+
32
+ This is a simple danger alert. It is used for errors and malfunctions that must be resolved before moving forward, such as a summary of errors to correct in a Form.
33
+
34
+ This is a simple info alert. It is used to provide context around a situation, such as rules around creating a compliant password, or a link to feature documentation or onboarding tips.
35
+
36
+ This is a simple success alert. It is used to communicate that an action has been successfully completed, such as saving changes in a Form.
37
+
38
+ This is a simple warning alert. It is used for a message requiring attention but not resolution in order to continue, such as noting data is not current or your password is about to expire.
39
+
40
+ Hide code
41
+
42
+ \[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; }
43
+
44
+ <div className\="iress-u-stack iress--gutter--md"\>
45
+ <IressAlert
46
+ footer\=""
47
+ heading\=""
48
+ status\="danger"
49
+ \>
50
+ This is a simple danger alert. It is used for errors and malfunctions that must be resolved before moving forward, such as a summary of errors to correct in a Form. </IressAlert\>
51
+ <IressAlert
52
+ footer\=""
53
+ heading\=""
54
+ status\="info"
55
+ \>
56
+ This is a simple info alert. It is used to provide context around a situation, such as rules around creating a compliant password, or a link to feature documentation or onboarding tips. </IressAlert\>
57
+ <IressAlert
58
+ footer\=""
59
+ heading\=""
60
+ status\="success"
61
+ \>
62
+ This is a simple success alert. It is used to communicate that an action has been successfully completed, such as saving changes in a Form. </IressAlert\>
63
+ <IressAlert
64
+ footer\=""
65
+ heading\=""
66
+ status\="warning"
67
+ \>
68
+ This is a simple warning alert. It is used for a message requiring attention but not resolution in order to continue, such as noting data is not current or your password is about to expire. </IressAlert\>
69
+ </div\>
70
+
71
+ Copy
72
+
73
+ ### [](#heading)Heading
74
+
75
+ An alert can be displayed with a heading. This is controlled by the `heading` prop. If provided a string, it will display a `<h2 />` element with the string as its content. If provided a React element, it will display that element directly.
76
+
77
+ **Note**: The `heading` prop replaces the `headingText` and `headingLevel` props from previous versions of IDS. These prop are now deprecated and will be removed in a future version.
78
+
79
+ Alert heading
80
+ -------------
81
+
82
+ This is a simple info alert
83
+
84
+ Hide code
85
+
86
+ \[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; }
87
+
88
+ <IressAlert
89
+ footer\=""
90
+ heading\="Alert heading"
91
+ status\="info"
92
+ \>
93
+ This is a simple info alert
94
+ </IressAlert\>
95
+
96
+ Copy
97
+
98
+ ### [](#footer)Footer
99
+
100
+ The `footer` prop allows for content to be placed below the header and body of the alert. This can be useful for displaying call to actions.
101
+
102
+ Alert heading
103
+ -------------
104
+
105
+ Here is the warning
106
+
107
+ Close
108
+
109
+ Hide code
110
+
111
+ \[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; }
112
+
113
+ <IressAlert
114
+ footer\={<IressButton\>Close</IressButton\>}
115
+ heading\="Alert heading"
116
+ \>
117
+ <IressText\>
118
+ Here is the warning </IressText\>
119
+ </IressAlert\>
120
+
121
+ Copy
122
+
123
+ On this page
124
+
125
+ * [Overview](#overview)
126
+ * [Props](#props)
127
+ * [Examples](#examples)
128
+ * [Status](#status)
129
+ * [Heading](#heading)
130
+ * [Footer](#footer)