Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/data/material/components/alert/alert.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ This component is no longer documented in the [Material Design guidelines](https

A key trait of the alert pattern is that [it should not interrupt the user's experience](https://www.w3.org/WAI/ARIA/apg/patterns/alert/) of the app.
Alerts should not be confused with alert _dialogs_ ([ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/)), which _are_ intended to interrupt the user to obtain a response.
Use the Material UI [Dialog](/material-ui/react-dialog/) component if you need this behavior.
Use the Material UI Dialog component (see the [alert dialog](/material-ui/react-dialog/#alerts) example) if you need this behavior.

## Basics

Expand Down Expand Up @@ -121,6 +121,7 @@ Here are some factors to consider to ensure that your Alert is accessible:
- Because alerts are not intended to interfere with the use of the app, your Alert component should _never_ affect the keyboard focus.
- If an alert contains an action, that action must have a `tabindex` of `0` so it can be reached by keyboard-only users.
- Essential alerts should not disappear automatically—[timed interactions](https://www.w3.org/TR/UNDERSTANDING-WCAG20/time-limits-no-exceptions.html) can make your app inaccessible to users who need extra time to understand or locate the alert.
- By default, the Alert renders an element with the `role="alert"`, which is the same as using `aria-live="assertive"` and `aria-atomic="true"`. This assumes the message requires the user's immediate attention. Less urgent messages should use a less aggressive method, such as passing `aria-live="polite"` or overriding the default role with a `role="status"`. Check this [alert role page](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/alert_role) for more information.
Comment thread
ZeeshanTamboli marked this conversation as resolved.
Outdated
- Alerts that occur too frequently can [inhibit the usability](https://www.w3.org/TR/UNDERSTANDING-WCAG20/time-limits-postponed.html) of your app.
- Dynamically rendered alerts are announced by screen readers; alerts that are already present on the page when it loads are _not_ announced.
- Color does not add meaning to the UI for users who require assistive technology. You must ensure that any information conveyed through color is also denoted in other ways, such as within the text of the alert itself, or with additional hidden text that's read by screen readers.
Expand Down
5 changes: 3 additions & 2 deletions docs/data/material/components/dialogs/AlertDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default function AlertDialog() {
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
role="alertdialog"
>
<DialogTitle id="alert-dialog-title">
{"Use Google's location service?"}
Expand All @@ -38,10 +39,10 @@ export default function AlertDialog() {
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Disagree</Button>
<Button onClick={handleClose} autoFocus>
Agree
Disagree
</Button>
<Button onClick={handleClose}>Agree</Button>
</DialogActions>
</Dialog>
</React.Fragment>
Expand Down
5 changes: 3 additions & 2 deletions docs/data/material/components/dialogs/AlertDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default function AlertDialog() {
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
role="alertdialog"
>
<DialogTitle id="alert-dialog-title">
{"Use Google's location service?"}
Expand All @@ -38,10 +39,10 @@ export default function AlertDialog() {
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Disagree</Button>
<Button onClick={handleClose} autoFocus>
Agree
Disagree
</Button>
<Button onClick={handleClose}>Agree</Button>
</DialogActions>
</Dialog>
</React.Fragment>
Expand Down
5 changes: 4 additions & 1 deletion docs/data/material/components/dialogs/AlertDialogSlide.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default function AlertDialogSlide() {
keepMounted
onClose={handleClose}
aria-describedby="alert-dialog-slide-description"
role="alertdialog"
>
<DialogTitle>{"Use Google's location service?"}</DialogTitle>
<DialogContent>
Expand All @@ -44,7 +45,9 @@ export default function AlertDialogSlide() {
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Disagree</Button>
<Button onClick={handleClose} autoFocus>
Disagree
</Button>
<Button onClick={handleClose}>Agree</Button>
</DialogActions>
</Dialog>
Expand Down
5 changes: 4 additions & 1 deletion docs/data/material/components/dialogs/AlertDialogSlide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export default function AlertDialogSlide() {
keepMounted
onClose={handleClose}
aria-describedby="alert-dialog-slide-description"
role="alertdialog"
>
<DialogTitle>{"Use Google's location service?"}</DialogTitle>
<DialogContent>
Expand All @@ -50,7 +51,9 @@ export default function AlertDialogSlide() {
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Disagree</Button>
<Button onClick={handleClose} autoFocus>
Disagree
</Button>
<Button onClick={handleClose}>Agree</Button>
</DialogActions>
</Dialog>
Expand Down
2 changes: 2 additions & 0 deletions docs/data/material/components/dialogs/dialogs.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import DialogTitle from '@mui/material/DialogTitle';

Alerts are urgent interruptions, requiring acknowledgement, that inform the user about a situation.

Use `role="alertdialog"` to create an Alert Dialog. This provides assistive technologies the correct purpose of the Dialog.

Most alerts don't need titles.
They summarize a decision in a sentence or two by either:

Expand Down
4 changes: 4 additions & 0 deletions docs/pages/material-ui/api/dialog.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
}
},
"PaperComponent": { "type": { "name": "elementType" }, "default": "Paper" },
"role": {
"type": { "name": "enum", "description": "'alertdialog'<br>&#124;&nbsp;'dialog'" },
"default": "'dialog'"
},
"scroll": {
"type": { "name": "enum", "description": "'body'<br>&#124;&nbsp;'paper'" },
"default": "'paper'"
Expand Down
3 changes: 3 additions & 0 deletions docs/translations/api-docs/dialog/dialog.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
},
"open": { "description": "If <code>true</code>, the component is shown." },
"PaperComponent": { "description": "The component used to render the body of the dialog." },
"role": {
"description": "The ARIA role for the dialog element. The main dialog role is <code>dialog</code>, but <code>alertdialog</code> can be used if the content of the dialog requires immediate attention. See <a href=\"https://www.w3.org/TR/wai-aria-1.2/#dialog\">https://www.w3.org/TR/wai-aria-1.2/#dialog</a> and <a href=\"https://www.w3.org/TR/wai-aria-1.2/#alertdialog\">https://www.w3.org/TR/wai-aria-1.2/#alertdialog</a> for more details."
},
"scroll": { "description": "Determine the container for scrolling the dialog." },
"slotProps": { "description": "The props used for each slot inside." },
"slots": { "description": "The components used for each slot inside." },
Expand Down
7 changes: 7 additions & 0 deletions packages/mui-material/src/Dialog/Dialog.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ export interface DialogProps
* If `true`, the component is shown.
*/
open: ModalProps['open'];
/**
* The ARIA role for the dialog element.
* The main dialog role is `dialog`, but `alertdialog` can be used if the content of the dialog requires immediate attention.
* See https://www.w3.org/TR/wai-aria-1.2/#dialog and https://www.w3.org/TR/wai-aria-1.2/#alertdialog for more details.
* @default 'dialog'
*/
role?: 'dialog' | 'alertdialog' | undefined;
/**
* The component used to render the body of the dialog.
* @default Paper
Expand Down
10 changes: 9 additions & 1 deletion packages/mui-material/src/Dialog/Dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ const Dialog = React.forwardRef(function Dialog(inProps, ref) {
onClose,
open,
PaperComponent = Paper,
role = 'dialog',
scroll = 'paper',
slots = {},
slotProps = {},
Expand Down Expand Up @@ -356,7 +357,7 @@ const Dialog = React.forwardRef(function Dialog(inProps, ref) {
<PaperSlot
as={PaperComponent}
elevation={24}
role="dialog"
role={role}
aria-describedby={ariaDescribedby}
aria-labelledby={ariaLabelledby}
aria-modal={ariaModal}
Expand Down Expand Up @@ -443,6 +444,13 @@ Dialog.propTypes /* remove-proptypes */ = {
* @default Paper
*/
PaperComponent: PropTypes.elementType,
/**
* The ARIA role for the dialog element.
* The main dialog role is `dialog`, but `alertdialog` can be used if the content of the dialog requires immediate attention.
* See https://www.w3.org/TR/wai-aria-1.2/#dialog and https://www.w3.org/TR/wai-aria-1.2/#alertdialog for more details.
* @default 'dialog'
*/
role: PropTypes.oneOf(['alertdialog', 'dialog']),
/**
* Determine the container for scrolling the dialog.
* @default 'paper'
Expand Down
4 changes: 4 additions & 0 deletions packages/mui-material/src/Dialog/Dialog.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ function Test() {
);
}

function DialogWithAlertRole() {
return <Dialog open role="alertdialog" />;
}

function Custom(props: DialogProps) {
const { slotProps, ...other } = props;
return (
Expand Down
18 changes: 18 additions & 0 deletions packages/mui-material/src/Dialog/Dialog.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,18 @@ describe('<Dialog />', () => {
expect(label).to.have.text('Choose either one');
});

it('should be described by another element', () => {
render(
<Dialog open aria-describedby="dialog-description">
<h1>Choose either one</h1>
<div id="dialog-description">Actually no</div>
</Dialog>,
);

const dialog = screen.getByRole('dialog');
expect(dialog).to.have.attr('aria-describedby', 'dialog-description');
});

it('should add the aria-modal="true" by default', function test() {
render(<Dialog open />);

Expand All @@ -393,6 +405,12 @@ describe('<Dialog />', () => {
const dialog = screen.getByRole('dialog');
expect(dialog).to.have.attr('aria-modal', 'false');
});

it('should override the role if provided', function test() {
render(<Dialog role="alertdialog" open />);

expect(screen.getByRole('alertdialog')).not.to.equal(null);
Comment thread
silviuaavram marked this conversation as resolved.
});
});

describe('prop: transitionDuration', () => {
Expand Down
7 changes: 7 additions & 0 deletions packages/mui-material/src/DialogTitle/DialogTitle.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ describe('<DialogTitle />', () => {
screen.getByText('Hello');
});

it('should render the title as an h2 by default', () => {
render(<DialogTitle>foo</DialogTitle>);

const title = screen.getByRole('heading', { name: 'foo', level: 2 });
expect(title.tagName).to.equal('H2');
});
Comment thread
ZeeshanTamboli marked this conversation as resolved.

describe('prop: id', () => {
it('should apply the id attribute provided to the Dialog title', () => {
render(
Expand Down
Loading