@@ -54,6 +54,36 @@ export interface FileUploadProps<Document> {
54
54
accept ?: string ;
55
55
}
56
56
57
+ /**
58
+ * The FileUpload component provides a drag-and-drop zone and a button for uploading files.
59
+ * Note: File state must be maintained outside this component. The component is stateless
60
+ * and will only trigger callbacks when files are selected, dropped, or deleted.
61
+ *
62
+ * @example
63
+ * ```jsx
64
+ * const [files, setFiles] = useState({});
65
+ *
66
+ * const handleFilesSelected = (fileList) => {
67
+ * // Process files and update state
68
+ * };
69
+ *
70
+ * return (
71
+ * <FileUpload
72
+ * id="file-upload"
73
+ * title="Upload files"
74
+ * label="Choose files"
75
+ * files={files}
76
+ * onFilesSelected={handleFilesSelected}
77
+ * onFilesDropped={handleFilesSelected}
78
+ * onFileDeleted={handleFileDeleted}
79
+ * infoText="Drop files here or"
80
+ * uploadTitle="Upload files"
81
+ * uploadMicroText="or"
82
+ * uploadSubText="Drag and drop files here"
83
+ * />
84
+ * );
85
+ * ```
86
+ */
57
87
export function FileUpload < Document > ( {
58
88
id,
59
89
label,
@@ -77,6 +107,13 @@ export function FileUpload<Document>({
77
107
const downloadIcon =
78
108
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iMjQiPjxwYXRoIGQ9Ik00ODAtMzQzLjUzOXEtNy4yMzEgMC0xMy40NjEtMi4zMDgtNi4yMzEtMi4zMDctMTEuODQ2LTcuOTIzTDMzMC4zMDktNDc4LjE1M3EtOC45MjMtOC45MjMtOC44MDctMjAuODg0LjExNS0xMS45NjEgOC44MDctMjEuMjY5IDkuMzA4LTkuMzA3IDIxLjM4NC05LjYxNSAxMi4wNzctLjMwOCAyMS4zODUgOWw3Ni45MjMgNzYuOTIzdi0zMDYuMDAxcTAtMTIuNzY5IDguNjE1LTIxLjM4NCA4LjYxNS04LjYxNiAyMS4zODQtOC42MTZ0MjEuMzg0IDguNjE2cTguNjE1IDguNjE1IDguNjE1IDIxLjM4NHYzMDYuMDAxbDc2LjkyMy03Ni45MjNxOC45MjMtOC45MjMgMjEuMTkyLTguODA4IDEyLjI2OS4xMTYgMjEuNTc3IDkuNDIzIDguNjkyIDkuMzA4IDguOTk5IDIxLjA3Ny4zMDggMTEuNzY5LTguOTk5IDIxLjA3Nkw1MDUuMzA3LTM1My43N3EtNS42MTUgNS42MTYtMTEuODQ2IDcuOTIzLTYuMjMgMi4zMDgtMTMuNDYxIDIuMzA4Wk0yNTIuMzA5LTE4MC4wMDFxLTMwLjMwOCAwLTUxLjMwOC0yMXQtMjEtNTEuMzA4di03OC40NjFxMC0xMi43NjkgOC42MTYtMjEuMzg0IDguNjE1LTguNjE1IDIxLjM4NC04LjYxNXQyMS4zODQgOC42MTVRMjQwLTM0My41MzkgMjQwLTMzMC43N3Y3OC40NjFxMCA0LjYxNiAzLjg0NiA4LjQ2MyAzLjg0NyAzLjg0NiA4LjQ2MyAzLjg0Nmg0NTUuMzgycTQuNjE2IDAgOC40NjMtMy44NDYgMy44NDYtMy44NDcgMy44NDYtOC40NjN2LTc4LjQ2MXEwLTEyLjc2OSA4LjYxNS0yMS4zODR0MjEuMzg0LTguNjE1cTEyLjc2OSAwIDIxLjM4NCA4LjYxNSA4LjYxNiA4LjYxNSA4LjYxNiAyMS4zODR2NzguNDYxcTAgMzAuMzA4LTIxIDUxLjMwOHQtNTEuMzA4IDIxSDI1Mi4zMDlaIi8+PC9zdmc+' ;
79
109
110
+ const handleKeyDown = ( event : React . KeyboardEvent < HTMLDivElement > ) => {
111
+ if ( event . key === 'Enter' || event . key === ' ' ) {
112
+ event . preventDefault ( ) ;
113
+ triggerUploadFileNativeHandler ( ) ;
114
+ }
115
+ } ;
116
+
80
117
const handleFilesDropped = ( event : React . DragEvent < HTMLDivElement > ) => {
81
118
event . preventDefault ( ) ;
82
119
setIsHover ( false ) ;
@@ -88,7 +125,6 @@ export function FileUpload<Document>({
88
125
} ;
89
126
90
127
const triggerUploadFileNativeHandler = ( ) => {
91
- // clear file input to trigger onChange when uploading same filename
92
128
if ( fileInputElement . current ) {
93
129
fileInputElement . current . value = '' ;
94
130
fileInputElement . current . click ( ) ;
@@ -124,7 +160,6 @@ export function FileUpload<Document>({
124
160
</ div >
125
161
</ div >
126
162
) }
127
- { /* eslint-disable-next-line jsx-a11y/no-static-element-interactions */ }
128
163
< div
129
164
className = "ffe-file-upload__upload-section"
130
165
onDrop = { handleFilesDropped }
@@ -133,6 +168,10 @@ export function FileUpload<Document>({
133
168
setIsHover ( true ) ;
134
169
} }
135
170
onDragLeave = { ( ) => setIsHover ( false ) }
171
+ role = "button"
172
+ tabIndex = { 0 }
173
+ onKeyDown = { handleKeyDown }
174
+ aria-label = { label }
136
175
>
137
176
< div
138
177
className = { classNames (
0 commit comments