Skip to content

Commit

Permalink
fix(form): FileInput correctly center the icon when children aren't p…
Browse files Browse the repository at this point in the history
…rovided
  • Loading branch information
mlaursen committed Jul 16, 2021
1 parent 7c123ef commit 3a6ab33
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 4 deletions.
25 changes: 22 additions & 3 deletions packages/form/src/file-input/FileInput.tsx
Expand Up @@ -38,7 +38,11 @@ export interface FileInputProps extends ButtonThemeProps, InputAttributes {
* Boolean if the children should not have some spacing between the icon and
* itself. The default behavior is to use the `<TextIconSpacing>` component
* for text styled input buttons, but this can be disabled if you want to use
* a screenreader only accessible label.
* a screen-reader only accessible label.
*
* Note: This will default to `false` if {@link children} are provided.
*
* @defaultValue `true`
*/
disableIconSpacing?: boolean;

Expand All @@ -48,6 +52,14 @@ export interface FileInputProps extends ButtonThemeProps, InputAttributes {
* selected.
*/
disableRepeatableFiles?: boolean;

/**
* Children should generally be provided when the {@link buttonType} is
* set to `"text"`. This defaults to a screen-reader only accessible text.
*
* @defaultValue `<SrOnly>Upload</SrOnly>`
*/
children?: ReactNode;
}

const block = bem("rmd-file-input");
Expand All @@ -63,12 +75,12 @@ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
className: propClassName,
icon: propIcon,
iconAfter = false,
children = <SrOnly>Upload</SrOnly>,
children: propChildren,
theme = "primary",
themeType = "contained",
buttonType = "icon",
multiple = false,
disableIconSpacing = false,
disableIconSpacing: propDisableIconSpacing,
disableRepeatableFiles = false,
onKeyDown,
onKeyUp,
Expand All @@ -86,6 +98,13 @@ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
) {
const { id, disabled } = props;
const icon = useIcon("download", propIcon);
const disableIconSpacing =
propDisableIconSpacing ?? typeof propChildren === "undefined";

let children = propChildren;
if (typeof propChildren === "undefined") {
children = <SrOnly>Upload</SrOnly>;
}

const { ripples, className, handlers } = useInteractionStates({
handlers: {
Expand Down
27 changes: 27 additions & 0 deletions packages/form/src/file-input/__tests__/FileInput.tsx
Expand Up @@ -20,4 +20,31 @@ describe("FileInput", () => {
);
expect(container).toMatchSnapshot();
});

it("should only render the screen-reader only accessible Upload text if there are no children", () => {
const props = { id: "file-input", onChange: () => {} };
const { container, getByText, rerender } = render(<FileInput {...props} />);
expect(() => getByText("Upload")).not.toThrow();
expect(container.querySelector(".rmd-icon--before")).toBe(null);
expect(container.querySelector(".rmd-icon--after")).toBe(null);

rerender(<FileInput {...props}>Custom Children</FileInput>);
expect(() => getByText("Upload")).toThrow();
expect(container.querySelector(".rmd-icon--before")).not.toBe(null);
expect(container.querySelector(".rmd-icon--after")).toBe(null);

rerender(
<FileInput {...props} icon={null}>
Custom Children
</FileInput>
);
expect(() => getByText("Upload")).toThrow();
expect(container.querySelector(".rmd-icon--before")).toBe(null);
expect(container.querySelector(".rmd-icon--after")).toBe(null);

rerender(<FileInput {...props} icon={null} />);
expect(() => getByText("Upload")).not.toThrow();
expect(container.querySelector(".rmd-icon--before")).toBe(null);
expect(container.querySelector(".rmd-icon--after")).toBe(null);
});
});
Expand Up @@ -14,7 +14,7 @@ exports[`FileInput should render correctly 1`] = `
>
<i
aria-hidden="true"
class="rmd-icon rmd-icon--font material-icons rmd-icon--before"
class="rmd-icon rmd-icon--font material-icons"
>
file_download
</i>
Expand Down

0 comments on commit 3a6ab33

Please sign in to comment.