FileDropzone: expose id to underlying input, fix story a11y violations (#113042)

* expose inputId to underlying input, add field to story

* just use id instead of inputId
This commit is contained in:
Ashley Harrison
2025-10-28 09:22:09 +00:00
committed by GitHub
parent d4d8b2562e
commit 92fb6872f0
3 changed files with 26 additions and 10 deletions
-5
View File
@@ -671,11 +671,6 @@
"count": 1
}
},
"packages/grafana-ui/src/components/FileDropzone/FileDropzone.story.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"packages/grafana-ui/src/components/FormField/FormField.tsx": {
"no-restricted-syntax": {
"count": 1
@@ -1,4 +1,7 @@
import { Meta, StoryFn } from '@storybook/react';
import { useId } from 'react';
import { Field } from '../Forms/Field';
import { FileDropzone } from './FileDropzone';
import mdx from './FileDropzone.mdx';
@@ -10,12 +13,17 @@ const meta: Meta<typeof FileDropzone> = {
docs: {
page: mdx,
},
// TODO fix a11y issue in story and remove this
a11y: { test: 'off' },
},
};
const Template: StoryFn<typeof FileDropzone> = (args) => <FileDropzone {...args} />;
const Template: StoryFn<typeof FileDropzone> = (args) => {
const inputId = useId();
return (
<Field label="Test JSON file">
<FileDropzone {...args} id={inputId} />
</Field>
);
};
export const Basic = Template.bind({});
@@ -47,6 +47,11 @@ export interface FileDropzoneProps {
*/
fileListRenderer?: (file: DropzoneFile, removeFile: (file: DropzoneFile) => void) => ReactNode;
onFileRemove?: (file: DropzoneFile) => void;
/**
* Optional id attribute for the underlying input element
* Use to link a label to the input for accessibility
*/
id?: string;
}
export interface DropzoneFile {
@@ -58,7 +63,15 @@ export interface DropzoneFile {
retryUpload?: () => void;
}
export function FileDropzone({ options, children, readAs, onLoad, fileListRenderer, onFileRemove }: FileDropzoneProps) {
export function FileDropzone({
options,
children,
readAs,
onLoad,
fileListRenderer,
onFileRemove,
id,
}: FileDropzoneProps) {
const [files, setFiles] = useState<DropzoneFile[]>([]);
const [fileErrors, setErrorMessages] = useState<FileError[]>([]);
@@ -218,7 +231,7 @@ export function FileDropzone({ options, children, readAs, onLoad, fileListRender
return (
<div className={styles.container}>
<div data-testid="dropzone" {...getRootProps({ className: styles.dropzone })}>
<input {...getInputProps()} />
<input {...getInputProps()} id={id} />
{children ?? <FileDropzoneDefaultChildren primaryText={getPrimaryText(files, options)} />}
</div>
{fileErrors.length > 0 && renderErrorMessages(fileErrors)}