From 603341d18e3f9a077bf99519a7b4f52935e4a44f Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 20 Dec 2021 09:53:10 +0000 Subject: [PATCH] [LoadingButton] Label progressbar by the LoadingButton (#30002) --- .../loading-button/loading-button.json | 2 +- .../src/LoadingButton/LoadingButton.d.ts | 2 ++ .../src/LoadingButton/LoadingButton.js | 19 +++++++++++++++---- .../src/LoadingButton/LoadingButton.test.js | 10 +++++++++- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/docs/translations/api-docs/loading-button/loading-button.json b/docs/translations/api-docs/loading-button/loading-button.json index 46ebe3d8a39927..c657729a1863ea 100644 --- a/docs/translations/api-docs/loading-button/loading-button.json +++ b/docs/translations/api-docs/loading-button/loading-button.json @@ -5,7 +5,7 @@ "classes": "Override or extend the styles applied to the component. See CSS API below for more details.", "disabled": "If true, the component is disabled.", "loading": "If true, the loading indicator is shown.", - "loadingIndicator": "Element placed before the children if the button is in loading state.", + "loadingIndicator": "Element placed before the children if the button is in loading state. The node should contain an element with role="progressbar" with an accessible name. By default we render a CircularProgress that is labelled by the button itself.", "loadingPosition": "The loading indicator can be positioned on the start, end, or the center of the button.", "sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the `sx` page for more details.", "variant": "The variant to use." diff --git a/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts b/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts index 5852347413ee79..0bfab98740b6b5 100644 --- a/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts +++ b/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts @@ -36,6 +36,8 @@ export type LoadingButtonTypeMap< loading?: boolean; /** * Element placed before the children if the button is in loading state. + * The node should contain an element with `role="progressbar"` with an accessible name. + * By default we render a `CircularProgress` that is labelled by the button itself. * @default */ loadingIndicator?: React.ReactNode; diff --git a/packages/mui-lab/src/LoadingButton/LoadingButton.js b/packages/mui-lab/src/LoadingButton/LoadingButton.js index b5bf0b7e880aa8..0a7616f608c9d6 100644 --- a/packages/mui-lab/src/LoadingButton/LoadingButton.js +++ b/packages/mui-lab/src/LoadingButton/LoadingButton.js @@ -1,7 +1,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { chainPropTypes } from '@mui/utils'; -import { capitalize } from '@mui/material/utils'; +import { capitalize, unstable_useId as useId } from '@mui/material/utils'; import { unstable_composeClasses as composeClasses } from '@mui/base'; import { styled, useThemeProps } from '@mui/material/styles'; import Button from '@mui/material/Button'; @@ -134,20 +134,24 @@ const LoadingButtonLoadingIndicator = styled('div', { }), })); -const LoadingIndicator = ; - const LoadingButton = React.forwardRef(function LoadingButton(inProps, ref) { const props = useThemeProps({ props: inProps, name: 'MuiLoadingButton' }); const { children, disabled = false, + id: idProp, loading = false, - loadingIndicator = LoadingIndicator, + loadingIndicator: loadingIndicatorProp, loadingPosition = 'center', variant = 'text', ...other } = props; + const id = useId(idProp); + const loadingIndicator = loadingIndicatorProp ?? ( + + ); + const ownerState = { ...props, disabled, @@ -162,6 +166,7 @@ const LoadingButton = React.forwardRef(function LoadingButton(inProps, ref) { return ( */ loadingIndicator: PropTypes.node, diff --git a/packages/mui-lab/src/LoadingButton/LoadingButton.test.js b/packages/mui-lab/src/LoadingButton/LoadingButton.test.js index 1132e7db790e87..3064dc1c3f1499 100644 --- a/packages/mui-lab/src/LoadingButton/LoadingButton.test.js +++ b/packages/mui-lab/src/LoadingButton/LoadingButton.test.js @@ -1,5 +1,5 @@ import * as React from 'react'; -import { createRenderer, describeConformance, screen } from 'test/utils'; +import { createRenderer, describeConformance, screen, within } from 'test/utils'; import { expect } from 'chai'; import Button from '@mui/material/Button'; import LoadingButton, { loadingButtonClasses as classes } from '@mui/lab/LoadingButton'; @@ -45,6 +45,14 @@ describe('', () => { expect(screen.getByRole('button')).to.have.property('disabled', true); }); + + it('renders a progressbar that is labelled by the button', () => { + render(Submit); + + const button = screen.getByRole('button'); + const progressbar = within(button).getByRole('progressbar'); + expect(progressbar).toHaveAccessibleName('Submit'); + }); }); describe('prop: loadingIndicator', () => {