@splunk/react-ui 5.7.0 → 5.8.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 (138) hide show
  1. package/Accordion.js +6 -6
  2. package/Box.js +83 -34
  3. package/CHANGELOG.md +34 -0
  4. package/CollapsiblePanel.js +11 -11
  5. package/ComboBox.js +31 -27
  6. package/ControlGroup.js +92 -91
  7. package/DefinitionList.js +9 -9
  8. package/Drawer.d.ts +2 -0
  9. package/Drawer.js +679 -0
  10. package/DualListbox.js +1 -1
  11. package/JSONTree.js +73 -72
  12. package/Link.js +2 -2
  13. package/MIGRATION.md +10 -0
  14. package/Menu.js +338 -240
  15. package/Modal.js +127 -109
  16. package/Multiselect.js +437 -351
  17. package/Paginator.js +14 -12
  18. package/Popover.js +4 -1
  19. package/README.md +11 -0
  20. package/RadioBar.js +1 -1
  21. package/Search.js +103 -88
  22. package/Select.js +42 -40
  23. package/SelectBase.js +374 -328
  24. package/SidePanel.js +346 -167
  25. package/SlidingPanels.js +11 -11
  26. package/StepBar.js +7 -7
  27. package/Switch.js +5 -5
  28. package/Text.js +24 -24
  29. package/TextArea.js +7 -7
  30. package/TransitionOpen.js +204 -185
  31. package/docs-llm/Accordion.md +267 -0
  32. package/docs-llm/Anchor Menu.md +115 -0
  33. package/docs-llm/Anchor.md +54 -0
  34. package/docs-llm/AnimationToggle.md +254 -0
  35. package/docs-llm/Avatar.md +298 -0
  36. package/docs-llm/Badge.md +212 -0
  37. package/docs-llm/Breadcrumbs.md +306 -0
  38. package/docs-llm/Button Group.md +53 -0
  39. package/docs-llm/Button.md +361 -0
  40. package/docs-llm/Card Layout.md +286 -0
  41. package/docs-llm/Card.md +619 -0
  42. package/docs-llm/Checkbox.md +218 -0
  43. package/docs-llm/Chip.md +291 -0
  44. package/docs-llm/Clickable.md +160 -0
  45. package/docs-llm/Code.md +292 -0
  46. package/docs-llm/Collapsible Panel.md +744 -0
  47. package/docs-llm/Color.md +253 -0
  48. package/docs-llm/Column Layout.md +391 -0
  49. package/docs-llm/Combo Box.md +540 -0
  50. package/docs-llm/Control Group.md +594 -0
  51. package/docs-llm/Date.md +270 -0
  52. package/docs-llm/Definition List.md +278 -0
  53. package/docs-llm/Divider.md +216 -0
  54. package/docs-llm/Drawer.md +414 -0
  55. package/docs-llm/Dropdown.md +472 -0
  56. package/docs-llm/Dual Listbox.md +325 -0
  57. package/docs-llm/File.md +653 -0
  58. package/docs-llm/Form Rows.md +374 -0
  59. package/docs-llm/Heading.md +179 -0
  60. package/docs-llm/Image.md +109 -0
  61. package/docs-llm/JSON Tree.md +260 -0
  62. package/docs-llm/Layer.md +74 -0
  63. package/docs-llm/Layout.md +50 -0
  64. package/docs-llm/Link.md +318 -0
  65. package/docs-llm/List.md +189 -0
  66. package/docs-llm/Markdown.md +179 -0
  67. package/docs-llm/Menu.md +735 -0
  68. package/docs-llm/Message Bar.md +236 -0
  69. package/docs-llm/Message.md +248 -0
  70. package/docs-llm/Modal.md +443 -0
  71. package/docs-llm/Monogram.md +159 -0
  72. package/docs-llm/Multiselect.md +937 -0
  73. package/docs-llm/Number.md +298 -0
  74. package/docs-llm/Paginator.md +395 -0
  75. package/docs-llm/Paragraph.md +148 -0
  76. package/docs-llm/Phone Number.md +254 -0
  77. package/docs-llm/Popover.md +166 -0
  78. package/docs-llm/Progress.md +141 -0
  79. package/docs-llm/Radio Bar.md +303 -0
  80. package/docs-llm/Radio List.md +350 -0
  81. package/docs-llm/Resize.md +362 -0
  82. package/docs-llm/Screen Reader Content.md +73 -0
  83. package/docs-llm/Scroll Container Context.md +155 -0
  84. package/docs-llm/Scroll.md +152 -0
  85. package/docs-llm/Search.md +381 -0
  86. package/docs-llm/Select.md +985 -0
  87. package/docs-llm/Side Panel.md +777 -0
  88. package/docs-llm/Slider.md +339 -0
  89. package/docs-llm/Sliding Panels.md +340 -0
  90. package/docs-llm/Split Button.md +295 -0
  91. package/docs-llm/Static Content.md +90 -0
  92. package/docs-llm/Step Bar.md +292 -0
  93. package/docs-llm/Switch.md +268 -0
  94. package/docs-llm/Tab Bar.md +439 -0
  95. package/docs-llm/Tab Layout.md +398 -0
  96. package/docs-llm/Table.md +2642 -0
  97. package/docs-llm/Text Area.md +253 -0
  98. package/docs-llm/Text.md +339 -0
  99. package/docs-llm/Tooltip.md +325 -0
  100. package/docs-llm/Transition Open.md +406 -0
  101. package/docs-llm/Tree.md +586 -0
  102. package/docs-llm/Typography.md +125 -0
  103. package/docs-llm/Wait Spinner.md +121 -0
  104. package/docs-llm/llms.txt +97 -0
  105. package/package.json +6 -5
  106. package/types/src/Box/Box.d.ts +2 -10
  107. package/types/src/Drawer/Body.d.ts +17 -0
  108. package/types/src/Drawer/Drawer.d.ts +114 -0
  109. package/types/src/Drawer/DrawerContext.d.ts +11 -0
  110. package/types/src/Drawer/Footer.d.ts +25 -0
  111. package/types/src/Drawer/Header.d.ts +41 -0
  112. package/types/src/Drawer/docs/examples/Basic.d.ts +6 -0
  113. package/types/src/Drawer/docs/examples/ContainerPosition.d.ts +7 -0
  114. package/types/src/Drawer/docs/examples/InitialFocus.d.ts +9 -0
  115. package/types/src/Drawer/docs/examples/InlinePosition.d.ts +7 -0
  116. package/types/src/Drawer/docs/examples/PagePosition.d.ts +7 -0
  117. package/types/src/Drawer/index.d.ts +2 -0
  118. package/types/src/JSONTree/JSONTree.d.ts +12 -5
  119. package/types/src/JSONTree/renderTreeItems.d.ts +2 -1
  120. package/types/src/Menu/Item.d.ts +2 -1
  121. package/types/src/Menu/docs/examples/SelectableCheckbox.d.ts +7 -0
  122. package/types/src/Modal/Modal.d.ts +1 -2
  123. package/types/src/Select/Option.d.ts +6 -3
  124. package/types/src/Select/Select.d.ts +8 -5
  125. package/types/src/Select/docs/examples/Dimmed.d.ts +7 -0
  126. package/types/src/SelectBase/OptionBase.d.ts +6 -3
  127. package/types/src/SelectBase/SelectBase.d.ts +8 -3
  128. package/types/src/SidePanel/SidePanel.d.ts +43 -2
  129. package/types/src/SidePanel/docs/examples/DockLayout.d.ts +17 -0
  130. package/types/src/SidePanel/docs/examples/InitialFocus.d.ts +9 -0
  131. package/types/src/TransitionOpen/TransitionOpen.d.ts +29 -4
  132. package/types/src/useKeyPress/index.d.ts +9 -2
  133. package/types/src/useOnClickOutside/index.d.ts +2 -0
  134. package/types/src/useOnClickOutside/useOnClickOutside.d.ts +4 -0
  135. package/useKeyPress.js +23 -18
  136. package/useOnClickOutside.d.ts +2 -0
  137. package/useOnClickOutside.js +79 -0
  138. package/types/src/RadioList/docs/examples/Row.d.ts +0 -6
@@ -0,0 +1,653 @@
1
+ # File
2
+
3
+ ## Overview
4
+
5
+
6
+ > Image: Illustration of a File component.
7
+
8
+
9
+ ## When to use this component
10
+ - When users are required to upload one or more files.
11
+ - When file type or size needs to be enforced at upload.
12
+
13
+ ## When to use another component
14
+ - If the user needs to provide information that is not a file, use the appropriate data entry components instead.
15
+
16
+ ## Usage
17
+
18
+ ### Labels and attributes
19
+ Use clear labels and include a supporting message specifying accepted file types.
20
+
21
+ > Image: In the first example with a heart eyes emoji, the File component includes a supporting message providing further context to the user. In the second example with a grimacing emoji, no supporting message is included in the File component.
22
+
23
+
24
+ ### Progress
25
+ Whenever possible, display progress on the File.Item to avoid frustration.
26
+
27
+ > Image: In the first example with a heart eyes emoji, the upload status of the File is visible to the user. In the second example with a grimacing emoji, the upload status is not visible to the user.
28
+
29
+
30
+ ### Error messaging
31
+ Offer clear, actionable error messages to help users understand and fix the issue.
32
+
33
+ Use when file upload is a required field.
34
+ > Image: In the first example with a heart eyes emoji, the user is given additional context on the error, that is, no file was uploaded. In the second example with a grimacing emoji, no further context is provided.
35
+
36
+
37
+ Use when the type of file uploaded is not accepted.
38
+ > Image: In the first example with a heart eyes emoji, the user is given additional context on the error, that is, the uploaded file type was not accepted. In the second example with a grimacing emoji, no further context is provided.
39
+
40
+
41
+ ## Examples
42
+
43
+
44
+ ### Single File
45
+
46
+ Here, selecting a new file will replace the existing file.
47
+
48
+ ```typescript
49
+ import React, { Component } from 'react';
50
+
51
+ import File, { FileRequestAddHandler } from '@splunk/react-ui/File';
52
+
53
+
54
+ class Single extends Component<object, { filename?: string }> {
55
+ private fileReader: FileReader;
56
+
57
+ constructor(props: object) {
58
+ super(props);
59
+
60
+ this.state = {};
61
+
62
+ this.fileReader = new FileReader();
63
+ }
64
+
65
+ handleAddFiles: FileRequestAddHandler = (files) => {
66
+ if (files.length > 0) {
67
+ const file = files[0];
68
+
69
+ if (this.fileReader.readyState === 1) {
70
+ this.fileReader.abort();
71
+ }
72
+
73
+ this.fileReader.onload = () => {
74
+ // can access this.fileReader.result
75
+ this.setState({ filename: file.name });
76
+ };
77
+
78
+ this.fileReader.readAsDataURL(file);
79
+ }
80
+ };
81
+
82
+ handleRemoveFile = () => {
83
+ if (this.fileReader.readyState === 1) {
84
+ this.fileReader.abort();
85
+ }
86
+
87
+ this.setState({ filename: undefined });
88
+ };
89
+
90
+ render() {
91
+ return (
92
+ <div style={{ maxWidth: 300 }}>
93
+ <File onRequestAdd={this.handleAddFiles} onRequestRemove={this.handleRemoveFile}>
94
+ {this.state.filename && <File.Item name={this.state.filename} />}
95
+ </File>
96
+ </div>
97
+ );
98
+ }
99
+ }
100
+
101
+ export default Single;
102
+ ```
103
+
104
+
105
+
106
+ ### Disabled
107
+
108
+ ```typescript
109
+ import React, { Component } from 'react';
110
+
111
+ import File, { FileRequestAddHandler } from '@splunk/react-ui/File';
112
+
113
+
114
+ class Disabled extends Component<object, { filename?: string }> {
115
+ private fileReader: FileReader;
116
+
117
+ constructor(props: object) {
118
+ super(props);
119
+
120
+ this.state = {};
121
+
122
+ this.fileReader = new FileReader();
123
+ }
124
+
125
+ handleAddFiles: FileRequestAddHandler = (files) => {
126
+ const file = files[0];
127
+
128
+ if (this.fileReader.readyState === 1) {
129
+ this.fileReader.abort();
130
+ }
131
+
132
+ this.fileReader.onload = () => {
133
+ // can access this.fileReader.result
134
+ this.setState({ filename: file.name });
135
+ };
136
+
137
+ this.fileReader.readAsDataURL(file);
138
+ };
139
+
140
+ handleRemoveFile = () => {
141
+ if (this.fileReader.readyState === 1) {
142
+ this.fileReader.abort();
143
+ }
144
+
145
+ this.setState({ filename: undefined });
146
+ };
147
+
148
+ render() {
149
+ return (
150
+ <div style={{ width: 300 }}>
151
+ <File
152
+ help="This is some help content suggesting a max size of 2MB."
153
+ onRequestAdd={this.handleAddFiles}
154
+ onRequestRemove={this.handleRemoveFile}
155
+ disabled
156
+ >
157
+ {this.state.filename && <File.Item name={this.state.filename} />}
158
+ </File>
159
+ <File
160
+ help="This is some help content suggesting a max size of 2MB."
161
+ onRequestAdd={this.handleAddFiles}
162
+ onRequestRemove={this.handleRemoveFile}
163
+ disabled
164
+ >
165
+ <File.Item name="Apple" />
166
+ <File.Item name="Cupcake" />
167
+ <File.Item name="Banana" />
168
+ <File.Item name="Orange" />
169
+ </File>
170
+ </div>
171
+ );
172
+ }
173
+ }
174
+
175
+ export default Disabled;
176
+ ```
177
+
178
+
179
+
180
+ ### Multifile
181
+
182
+ By storing an array of items, multiple files can be supported.
183
+
184
+ ```typescript
185
+ import React, { Component } from 'react';
186
+
187
+ import File, { FileRequestAddHandler, FileRequestRemoveHandler } from '@splunk/react-ui/File';
188
+
189
+ interface FileItem {
190
+ name: string;
191
+ value?: string | ArrayBuffer | null;
192
+ }
193
+
194
+
195
+ class Multi extends Component<object, { files: FileItem[] }> {
196
+ static loadFile(file: globalThis.File) {
197
+ const fileItem: FileItem = { name: file.name };
198
+
199
+ const fileReader = new FileReader();
200
+ fileReader.onload = () => {
201
+ fileItem.value = fileReader.result;
202
+ };
203
+ fileReader.readAsDataURL(file);
204
+
205
+ return fileItem;
206
+ }
207
+
208
+ constructor(props: object) {
209
+ super(props);
210
+
211
+ this.state = {
212
+ files: [],
213
+ };
214
+ }
215
+
216
+ handleAddFiles: FileRequestAddHandler = (files) => {
217
+ const newItems = files.map(Multi.loadFile);
218
+
219
+ this.setState((state) => ({
220
+ files: [...state.files, ...newItems],
221
+ }));
222
+ };
223
+
224
+ handleRemoveFile: FileRequestRemoveHandler = ({ index }) => {
225
+ this.setState((state) => {
226
+ const files = state.files.slice(0);
227
+ files.splice(index, 1);
228
+ return { files };
229
+ });
230
+ };
231
+
232
+ render() {
233
+ const children = this.state.files.map((item) => (
234
+ <File.Item itemId={item.name} name={item.name} key={item.name} />
235
+ ));
236
+
237
+ return (
238
+ <div style={{ width: 300 }}>
239
+ <File
240
+ onRequestAdd={this.handleAddFiles}
241
+ onRequestRemove={this.handleRemoveFile}
242
+ allowMultiple
243
+ >
244
+ {children}
245
+ </File>
246
+ </div>
247
+ );
248
+ }
249
+ }
250
+
251
+ export default Multi;
252
+ ```
253
+
254
+
255
+
256
+ ### Customized supports message and help
257
+
258
+ The default supports message can be customized. A help message can also be added.
259
+
260
+ ```typescript
261
+ import React from 'react';
262
+
263
+ import { noop } from 'lodash';
264
+
265
+ import File from '@splunk/react-ui/File';
266
+ import Link from '@splunk/react-ui/Link';
267
+
268
+
269
+ export default function CustomizedMessages() {
270
+ return (
271
+ <div style={{ width: 300 }}>
272
+ <File
273
+ accept="image/*"
274
+ onRequestAdd={noop}
275
+ onRequestRemove={noop}
276
+ supportsMessage={<>Supports image file types: e.g. .jpg, .gif, or .png</>}
277
+ help={
278
+ <>
279
+ Learn more about <Link>supported image formats</Link>.
280
+ </>
281
+ }
282
+ >
283
+ <File.Item name="Cupcake" uploadPercentage={40} />
284
+ </File>
285
+ </div>
286
+ );
287
+ }
288
+ ```
289
+
290
+
291
+
292
+ ### Progress
293
+
294
+ The File.Item can display its upload progress.
295
+
296
+ ```typescript
297
+ import React from 'react';
298
+
299
+ import { noop } from 'lodash';
300
+
301
+ import File from '@splunk/react-ui/File';
302
+
303
+
304
+ export default function Progress() {
305
+ return (
306
+ <div style={{ width: 300 }}>
307
+ <File onRequestAdd={noop} onRequestRemove={noop}>
308
+ <File.Item name="Cupcake" uploadPercentage={40} />
309
+ </File>
310
+ </div>
311
+ );
312
+ }
313
+ ```
314
+
315
+
316
+
317
+ ### Drop Anywhere
318
+
319
+ The File.Item can be dropped anywhere on the page. This example must open in a modal since the drop zone is the entire page and affects the other Files on this page.
320
+
321
+ ```typescript
322
+ import React, { Component } from 'react';
323
+
324
+ import Button from '@splunk/react-ui/Button';
325
+ import File, { FileRequestAddHandler } from '@splunk/react-ui/File';
326
+
327
+
328
+ class DropAnywhere extends Component<object, { filename?: string; open: boolean }> {
329
+ private fileReader: FileReader;
330
+
331
+ constructor(props: object) {
332
+ super(props);
333
+
334
+ this.state = {
335
+ open: false,
336
+ };
337
+
338
+ this.fileReader = new FileReader();
339
+ }
340
+
341
+ handleAddFiles: FileRequestAddHandler = (files) => {
342
+ if (files.length > 0) {
343
+ const file = files[0];
344
+
345
+ if (this.fileReader.readyState === 1) {
346
+ this.fileReader.abort();
347
+ }
348
+
349
+ this.fileReader.onload = () => {
350
+ // can access this.fileReader.result
351
+ this.setState({ filename: file.name });
352
+ };
353
+
354
+ this.fileReader.readAsDataURL(file);
355
+ }
356
+ };
357
+
358
+ handleRemoveFile = () => {
359
+ if (this.fileReader.readyState === 1) {
360
+ this.fileReader.abort();
361
+ }
362
+
363
+ this.setState({ filename: undefined });
364
+ };
365
+
366
+ handleOpen = () => {
367
+ this.setState({
368
+ open: true,
369
+ });
370
+ };
371
+
372
+ handleClose = () => {
373
+ this.setState({
374
+ open: false,
375
+ });
376
+ };
377
+
378
+ render() {
379
+ const modalStyles: React.CSSProperties = {
380
+ position: 'relative',
381
+ top: 0,
382
+ right: 0,
383
+ bottom: 0,
384
+ left: 0,
385
+ zIndex: 100,
386
+ padding: 10,
387
+ margin: '0 -10px 4px',
388
+ height: 140,
389
+ };
390
+
391
+ const closeStyles: React.CSSProperties = {
392
+ position: 'relative',
393
+ left: 'calc(50% - 60px)',
394
+ marginTop: 10,
395
+ };
396
+
397
+ return (
398
+ <div>
399
+ <Button onClick={this.handleOpen} label="Show drop anywhere example" />
400
+
401
+ {this.state.open && (
402
+ <div style={modalStyles}>
403
+ <File
404
+ dropAnywhere
405
+ help="This is some help content suggesting a max size of 2MB."
406
+ onRequestAdd={this.handleAddFiles}
407
+ onRequestRemove={this.handleRemoveFile}
408
+ >
409
+ {this.state.filename && <File.Item name={this.state.filename} />}
410
+ </File>
411
+
412
+ <Button
413
+ onClick={this.handleClose}
414
+ label="Close example"
415
+ style={closeStyles}
416
+ />
417
+ </div>
418
+ )}
419
+ </div>
420
+ );
421
+ }
422
+ }
423
+
424
+ export default DropAnywhere;
425
+ ```
426
+
427
+
428
+
429
+ ### Full Screen
430
+
431
+ ```typescript
432
+ import React, { useRef, useState } from 'react';
433
+
434
+ import styled from 'styled-components';
435
+
436
+ import Button from '@splunk/react-ui/Button';
437
+ import File, { FileRequestAddHandler } from '@splunk/react-ui/File';
438
+ import { variables } from '@splunk/themes';
439
+
440
+ const StyledFullscreenOverlay = styled.div`
441
+ position: fixed;
442
+ top: 0;
443
+ right: 0;
444
+ bottom: 0;
445
+ left: 0;
446
+ z-index: ${variables.zindexModal};
447
+ background-color: ${variables.backgroundColorPage};
448
+ display: flex;
449
+ justify-content: center;
450
+ align-items: center;
451
+ `;
452
+
453
+ const StyledButton = styled(Button)`
454
+ position: absolute;
455
+ bottom: 20px;
456
+ left: 50%;
457
+ transform: translateX(-50%);
458
+ `;
459
+
460
+
461
+ function Fullscreen() {
462
+ const fileReader = useRef(new FileReader());
463
+ const fullscreenToggle = useRef<HTMLButtonElement | null>(null);
464
+ const [open, setOpen] = useState<boolean>(false);
465
+ const [fileName, setFileName] = useState<string | undefined>(undefined);
466
+
467
+ const handleAddFiles: FileRequestAddHandler = (files) => {
468
+ const currentFileReader = fileReader.current;
469
+ if (files.length > 0) {
470
+ const file = files[0];
471
+
472
+ if (currentFileReader.readyState === 1) {
473
+ currentFileReader.abort();
474
+ }
475
+
476
+ currentFileReader.onload = () => {
477
+ // can access this.fileReader.result
478
+ setFileName(file.name);
479
+ };
480
+
481
+ currentFileReader.readAsDataURL(file);
482
+ }
483
+ };
484
+
485
+ const handleRemoveFile = () => {
486
+ const currentFileReader = fileReader.current;
487
+ if (currentFileReader.readyState === 1) {
488
+ currentFileReader.abort();
489
+ }
490
+
491
+ setFileName(undefined);
492
+ };
493
+
494
+ const handleOpen = () => {
495
+ setOpen(true);
496
+ };
497
+
498
+ const handleClose = () => {
499
+ fullscreenToggle.current?.focus();
500
+ setOpen(false);
501
+ };
502
+
503
+ return (
504
+ <div style={{ width: 300 }}>
505
+ <Button
506
+ elementRef={fullscreenToggle}
507
+ onClick={handleOpen}
508
+ label="Open full screen file example"
509
+ />
510
+
511
+ {open && (
512
+ <StyledFullscreenOverlay>
513
+ <File
514
+ fullscreen
515
+ help="This is some help content suggesting a max size of 2MB."
516
+ onRequestAdd={handleAddFiles}
517
+ onRequestRemove={handleRemoveFile}
518
+ >
519
+ {fileName && <File.Item name={fileName} />}
520
+ </File>
521
+
522
+ <StyledButton onClick={handleClose} label="Close example" />
523
+ </StyledFullscreenOverlay>
524
+ )}
525
+ </div>
526
+ );
527
+ }
528
+
529
+ export default Fullscreen;
530
+ ```
531
+
532
+
533
+
534
+ ### Error
535
+
536
+ The File and File.Item have separate error states. Generally, they should not be used together. Either the File is in error (for example, required field), or an Item is in error (for example, incorrect file type).
537
+
538
+ ```typescript
539
+ import React from 'react';
540
+
541
+ import { noop } from 'lodash';
542
+
543
+ import File from '@splunk/react-ui/File';
544
+
545
+
546
+ export default function FileErrors() {
547
+ return (
548
+ <div style={{ width: 300 }}>
549
+ <File onRequestAdd={noop} onRequestRemove={noop} error />
550
+ <br />
551
+ <br />
552
+ <File onRequestAdd={noop} onRequestRemove={noop} onRequestRetry={noop}>
553
+ <File.Item name="Apple" />
554
+ <File.Item name="Cupcake" error />
555
+ <File.Item name="Banana" />
556
+ <File.Item name="Orange" />
557
+ </File>
558
+ </div>
559
+ );
560
+ }
561
+ ```
562
+
563
+
564
+
565
+
566
+ ## API
567
+
568
+
569
+ ### File API
570
+
571
+ File provides the ability to accept files and present uploaded files. It does not provide
572
+ file readers, only a reference to the file. This can be used to post binary content, or
573
+ upload using an array buffer.
574
+
575
+ #### Props
576
+
577
+ | Name | Type | Required | Default | Description |
578
+ |------|------|------|------|------|
579
+ | accept | string | no | | The accept attribute for the file browser. This does not filter dropped items, which must be filtered manually. File will create a default "supports" message based on this value. |
580
+ | allowMultiple | boolean | no | | Allow the user to upload multiple files. |
581
+ | children | React.ReactNode | no | | |
582
+ | disabled | boolean | no | | Prevents user from dropping files. |
583
+ | dropAnywhere | boolean | no | | File can be dropped anywhere on the page. |
584
+ | elementRef | React.Ref<HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts, and null when it unmounts. |
585
+ | error | boolean | no | | Show the component in an error state. This has no effect on the full-screen File. Note: File.Item has a separate error property. |
586
+ | fullscreen | boolean | no | | There can only be one File component on the page as it will take all files dropped on the page. |
587
+ | help | React.ReactNode | no | | Show help text. |
588
+ | inputId | string | no | | An id for the input, which may be necessary for accessibility, such as for aria attributes. |
589
+ | name | string | no | | The name is returned with onRequestAdd and onRequestRemove events, which can be used to identify the control when multiple controls share an onChange callback. |
590
+ | onRequestAdd | FileRequestAddHandler | no | | A callback for when the user selects one or more files. The function is passed a file reference, which can then be used to read the file. This may be used to enforce file constraints or upload the file. |
591
+ | onRequestRemove | FileRequestRemoveHandler | no | | A callback for when the user requests to remove a file. The function is passed the event and an object with the Item's index and name: `(event, {index, name})`. |
592
+ | onRequestRetry | (data: { event: { itemId?: string; name: string }; filename: string; index: number; itemId?: string; name?: string; }) => void | no | | A callback for when the user requests to retry the upload after upload resulted in error. The function is passed the event and an object with the Item's index and name: `(event, {index, name})`. |
593
+ | supportsMessage | React.ReactNode | no | | |
594
+
595
+ #### Types
596
+
597
+ | Name | Type | Description |
598
+ |------|------|------|
599
+ | FileRequestAddHandler | (files: globalThis.File[], data: { name?: string }) => void | |
600
+ | FileRequestRemoveHandler | (data: { event: { itemId?: string; name: string; }; filename: string; index: number; itemId?: string; name?: string; }) => void | |
601
+
602
+
603
+
604
+ ### File.Item API
605
+
606
+ #### Props
607
+
608
+ | Name | Type | Required | Default | Description |
609
+ |------|------|------|------|------|
610
+ | disabled | boolean | no | | |
611
+ | elementRef | React.Ref<HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts and null when it unmounts. |
612
+ | error | boolean | no | false | Show the Item in an error state. |
613
+ | itemId | string | no | | A unique for this file. |
614
+ | name | string | yes | | The name is displayed on the item. |
615
+ | uploadPercentage | number | no | | If the uploadPercentage is 0, the item is assumed to be queued. If the upload is complete or not applicable, uploadPercentage must be undefined. |
616
+
617
+
618
+
619
+
620
+
621
+ ## Accessibility
622
+
623
+ ## Visual Design
624
+ - Color contrast ratio **MUST** be:
625
+ - &gt=4.5:1 for [SC 1.4.3][1]:
626
+ - Any text (static, link, etc.) to background color
627
+ - &gt=3:1 for [SC 1.4.11][2]
628
+ - Drop-area (usually a dotted line) to background color
629
+ - Any functional icon (refresh, close, delete) to background color
630
+
631
+ ## Content
632
+ - **SHOULD** have a descriptive button, such as "Browse Files" or "Upload File"; avoid verb-only phrases such as "Browse".
633
+
634
+ ## States
635
+ - Feedback mechanism **MUST** be provided for upload:
636
+ - In progress
637
+ - Success
638
+ - Error
639
+ - Single file
640
+ - One or more files in multi-upload
641
+
642
+ ## Interaction Model
643
+ - **MUST** have keyboard navigation [SC 2.1][3]:
644
+ - <kbd>Tab</kbd> and <kbd>Shift+Tab</kbd>: focuses button to upload file and any icons associated with uploaded files, regardless of state.
645
+
646
+ ## Implementation
647
+ - When more than one file is uploaded, screen reader **MUST** announce file count, i.e. "1 of n" [SC 4.1.2][4]
648
+
649
+ [1]: https://www.w3.org/TR/WCAG21/#contrast-minimum
650
+ [2]: https://www.w3.org/TR/WCAG21/#non-text-contrast
651
+ [3]: https://www.w3.org/TR/WCAG21/#keyboard-accessible
652
+ [4]: https://www.w3.org/TR/WCAG21/#name-role-value
653
+