Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dialog] DialogTitle should use h1 instead of h2 #34250

Open
paulschreiber opened this issue Sep 9, 2022 · 12 comments · May be fixed by #34251
Open

[Dialog] DialogTitle should use h1 instead of h2 #34250

paulschreiber opened this issue Sep 9, 2022 · 12 comments · May be fixed by #34251
Assignees
Labels
accessibility a11y component: dialog This is the name of the generic UI component, not the React module! discussion

Comments

@paulschreiber
Copy link
Contributor

paulschreiber commented Sep 9, 2022

Current behavior 😯

Dialog and DialogTitle generates this HTML

<div class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation24 MuiDialog-paper MuiDialog-paperScrollPaper MuiDialog-paperWidthSm css-1t1j96h-MuiPaper-root-MuiDialog-paper" role="dialog" aria-labelledby=":r3:">
   <h2 class="MuiTypography-root MuiTypography-h6 MuiDialogTitle-root css-bdhsul-MuiTypography-root-MuiDialogTitle-root" id=":r3:">Title</h2>
</div>

Expected behavior 🤔

<div class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation24 MuiDialog-paper MuiDialog-paperScrollPaper MuiDialog-paperWidthSm css-1t1j96h-MuiPaper-root-MuiDialog-paper" role="dialog" aria-labelledby=":r3:">
   <h1 class="MuiTypography-root MuiTypography-h6 MuiDialogTitle-root css-bdhsul-MuiTypography-root-MuiDialogTitle-root" id=":r3:">Title</h1>
</div>

Steps to reproduce 🕹

import React from "react";
import { Dialog, DialogTitle } from "@mui/material";

export default function App() {
  return (
    <>
      <Dialog open={true}>
        <DialogTitle>Title</DialogTitle>
      </Dialog>
    </>
  );
}

Context 🔦

Dialogs should have their owner heading hierarchy, starting with h1. This is important for screen readers.

Your environment 🌎

npx @mui/envinfo
  System:
    OS: macOS 12.5.1
  Binaries:
    Node: 18.7.0 - /opt/homebrew/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 8.15.0 - /opt/homebrew/bin/npm
  Browsers:
    Chrome: 105.0.5195.102
    Edge: Not Found
    Firefox: 104.0.1
    Safari: 15.6.1
  npmPackages:
    @emotion/react: ^11.10.0 => 11.9.3 
    @emotion/styled: ^11.10.0 => 11.9.3 
    @mui/base:  5.0.0-alpha.96 
    @mui/codemod:  5.10.4 
    @mui/core-downloads-tracker:  5.10.4 
    @mui/docs:  5.10.3 
    @mui/envinfo:  2.0.6 
    @mui/icons-material:  5.10.3 
    @mui/joy:  5.0.0-alpha.44 
    @mui/lab:  5.0.0-alpha.98 
    @mui/markdown:  5.0.0 
    @mui/material:  5.10.4 
    @mui/material-next:  6.0.0-alpha.52 
    @mui/private-theming:  5.10.3 
    @mui/styled-engine:  5.10.4 
    @mui/styled-engine-sc:  5.10.3 
    @mui/styles:  5.10.3 
    @mui/system:  5.10.4 
    @mui/types:  7.2.0 
    @mui/utils:  5.10.3 
    @mui/x-data-grid:  5.15.2 
    @mui/x-data-grid-generator:  5.15.2 
    @mui/x-data-grid-premium:  5.15.2 
    @mui/x-data-grid-pro:  5.15.2 
    @mui/x-date-pickers:  5.0.0-beta.5 
    @mui/x-date-pickers-pro:  5.0.0-beta.5 
    @mui/x-license-pro:  5.15.0 
    @types/react: ^18.0.17 => 18.0.14 
    react: ^18.2.0 => 18.2.0 
    react-dom: ^18.2.0 => 18.2.0 
    styled-components:  5.3.5 
    typescript: ^4.8.2 => 4.6.4 
@paulschreiber paulschreiber added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Sep 9, 2022
@hbjORbj hbjORbj added design: material This is about Material Design, please involve a visual or UX designer in the process component: dialog This is the name of the generic UI component, not the React module! labels Sep 9, 2022
@hbjORbj hbjORbj changed the title Dialog titles use h2 (should use h1) [Dialog] DialogTitle should use h1 instead of h2 Sep 9, 2022
@paulschreiber
Copy link
Contributor Author

@hbjORbj please tag with accessibility.

@paulschreiber paulschreiber linked a pull request Sep 9, 2022 that will close this issue
1 task
@danilo-leal danilo-leal added accessibility a11y and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Sep 9, 2022
@danilo-leal
Copy link
Contributor

danilo-leal commented Sep 9, 2022

Thanks for the heads up @paulschreiber! I wonder if we really should do this, though. If the dialog's title is an h1, wouldn't that confuse users leaning on screen readers, given that it could give the impression that they have navigated to a different page altogether, which is not totally the case? A few benchmarks I've collected quickly:

@oliviertassinari
Copy link
Member

oliviertassinari commented Sep 9, 2022

IMHO, this issue is a duplicate of #16569.

Also, +1 to keep h2 until a supporting material is provided to justify why h1 would be better.

@oliviertassinari oliviertassinari removed the design: material This is about Material Design, please involve a visual or UX designer in the process label Sep 9, 2022
@jscholes
Copy link

Hello all; for context I represent PAC, the team of accessibility consultants who recommended that this change be made within a product managed by @paulschreiber. Hopefully I can shine a light on this suggestion.

A modal dialog is considered to be a distinct area from the main page, and hence the heading hierarchy can and should be reset. An h2 is not the most appropriate choice, because:

  • While trapped within a modal, there is no parent heading that a screen reader user can reach.
  • The main h1 on the outer page cannot logically be considered to be the parent of the h2 within the modal, because modals can be invoked from anywhere (including headers/footers/etc.).
  • It deprives developers and designers of a heading level, of which there are already only a limited choice.

To address the specific question by @danilo-leal:

If the dialog's title is an h1, wouldn't that confuse users leaning on screen readers, given that it could give the impression that they have navigated to a different page altogether ...

I really appreciate the attention to detail and user experience implied by this query. However, screen readers will convey the fact that the user's new context is a modal dialog (assuming that everything else about the dialog is coded correctly). These announcements are quite distinct from those triggered by a page load, and hence there should be no confusion.

In terms of resources, you can observe this recommended approach within a Simple Dialog example from Deque, an Accessible Modal Dialog example by Paul J. Adam, the A11y Dialog library by @KittyGiraudel, among others. The WAI-ARIA Authoring Practices (APG) linked earlier in this thread is not a spec or published standard; they've chosen to be opinionated about the use of an h2 without providing documented justification, and that aspect of their example is not something I agree with.

Hope this helps.

@danilo-leal
Copy link
Contributor

Thanks, @jscholes, appreciate the thorough answer! All of that makes sense to me and seems enough to allow the change to move forward. @oliviertassinari any objections or thoughts? We might want to enrich documentation about this, I think, given that it has come up again.

@oliviertassinari
Copy link
Member

oliviertassinari commented Sep 12, 2022

I had a look at why it's an h2 in https://www.w3.org/WAI/ARIA/apg/example-index/dialog-modal/dialog.html see w3c/aria-practices#551

Because they are a child window, I have usually recommended a level lower than 1. The lack of a level 1 could actually help some people understand they are not on the main page.

But, I don't think there is any hard and fast rule here. It is one of those subjective calls where there is rationale that could probably justify either approach or a variety of others as well.

I think both can work, I have no specific recommendations.

@siriwatknp
Copy link
Member

I think we should have a valid evidence that h1 is better than h2 (maybe a comparison with screen readers), otherwise I don't see why we need to change.

@oliviertassinari
Copy link
Member

oliviertassinari commented Sep 18, 2022

I asked @xurxe for some perspective on this issue during our last call. It seems that there are use cases for both, so I suspect that updating https://mui.com/base/react-modal/#accessibility with guidelines could be enough to close this issue.

@xurxe
Copy link

xurxe commented Sep 18, 2022

Hi everyone! I just wanted to hop into this very interesting discussion and add my two cents, as a web developer and IAAP-certified accessibility specialist (CPACC, WAS, CPWA).

TL;DR

  • I believe that h2 is the most sensible default level for the DialogTitle component.
  • It could be advantageous to let developers customize the level, but that probably goes beyond the scope of this discussion.
  • There are some problems with the implementation and documentation of the Dialog component, but this again probably goes beyond the scope of this discussion.

Definitions and background

As @jscholes mentioned, we should refer to the applicable spec or standard, which is in this case is ARIA 1.1. There's three key definitions we should look at.

  1. The dialog role

A dialog is a descendant window of the primary window of a web application. [...] Dialogs are most often used to prompt the user to enter or respond to information. A dialog that is designed to interrupt workflow is usually modal.

  1. The window role (since a dialog is a type of window)

Elements with this role have a window-like behavior in a graphical user interface (GUI) context, regardless of whether they are implemented as a native window in the operating system, or merely as a section of the document styled to look like a window.

  1. The aria-modal property

The aria-modal attribute is used to indicate that the presence of a "modal" element precludes usage of other content on the page. For example, when a modal dialog is displayed, it is expected that the user's interaction is limited to the contents of the dialog, until the modal dialog loses focus or is no longer displayed.

In the context of HTML, a dialog is a nested, secondary window that opens up within the page. A dialog can be modal or non-modal i.e. modeless.

A modal dialog or window launches a special mode of operation, during which the user must interact with it in one of the "approved" ways before being allowed to return to the primary window. Such approved ways may or may not include: activating a Close button, entering text into an input field and activating an OK button, etc, depending on the situation.

A non-modal dialog or window does not launch a special mode of operation, and users are free to switch between it and the primary window. These are not so commonly used in web applications, but could be something like... a color utility in an online design application (as long as it actually follows the non-modal dialog pattern, rather that being implemented as a tooltip or something else).

I also want to point out that there is conflation / confusion between dialogs and modal dialogs, both in this discussion and in the MUI Dialog documentation. Additionally, the MUI Modal documentation has some inaccuracies as well. Addressing these issues goes beyond the scope of this discussion, but in spite of that I'd like to say that the MUI Dialog component constitutes a fairly successful implementation of the modal dialog pattern.

My take on the heading level

After much consideration, I do think that h2 is the most appropriate default level for DialogTitle. Here's why:

  • As a rule of thumb, the h1 should either be identical or fairly similar to the title of the page. Encountering a new h1 is typically an indication that the page has changed. For fully blind users, a change in h1 paired with a change in browsing context (which happens when we programmatically move focus to the dialog) could be quite disorienting when it's not actually a change of page (and features such as the browser's Back button don't work as expected).

  • There should only be one h1 per page. Technically speaking, we're allowed to "reset" the heading levels when introducing a sectioning element (article, section, aside, or nav). This is discouraged for many reasons, including the fact that many assistive technologies are not able to parse this kind of structure correctly. Still, if you really wanted to start a dialog with an h1, when you should use something like a section element to wrap the contents of the dialog.

  • A dialog is a secondary window within the main web page / window / application. As such, it makes sense that it's part of its heading hierarchy, and h2 is the most sensible level in most situations. However, it could be advantageous to let developers override this level manually, in case it makes more sense to use h3, etc in a specific situation.

  • As for the issue of depriving developers of a heading level: it's quite rare that we make it all the way down to h6 without skipping levels, but if the need truly arises, it's possible to use aria-level to create the equivalents of h7, h8, etc.

@jscholes
Copy link

@xurxe Thank you for taking the time to write this out. Unfortunately, the conclusions seem to revolve around assertions which themselves are not standardised or evidence-based, rather than on the nuances of end-user and developer experience. Specifically:

A dialog is a descendant window
...
Elements with this role have a window-like behavior in a graphical user interface (GUI) context
...
The aria-modal attribute is used to indicate that the presence of a "modal" element precludes usage of other content on the page.

In other words: what we have is a window on top of some other content, which precludes access to that content, and should be treated as a separate bounded context. The window is a descendant, but this is mostly a technical concern, and only relevant to users from a wayfinding perspective as they navigate into and out of the dialog. Note that I'm only considering modal dialogs here; non-modal dialogs are a completely separate topic and not in scope.

However, you then assert that:

There should only be one h1 per page.

For the purposes of usability and structured understanding, there should only be a single h1 per user-addressable area of a web application. When a dialog is modal, that should be the sole area of the page that the user is able to reach, and hence the presence of multiple h1s is irrelevant.

This is also why each dialog doesn't need to have a uniquely named "Close" button, for example, because the user should never be interacting with multiple modals at once. Suggesting that every modal dialog must participate in the same constraints as the parent page is not scalable nor user-friendly.

A dialog is a secondary window within the main web page / window / application. As such, it makes sense that it's part of its heading hierarchy, and h2 is the most sensible level in most situations.

I've already covered why I believe the first part of this statement, about the participation of the modal content within the parent page's constraints, to be suboptimal. However, I want to call out the following suggestion:

... h2 is the most sensible level in most situations

... as something which I don't understand. When developing a heading hierarchy that truly reflects the structure of the underlying content architecture, the most sensible heading level will differ based on context. There is no such thing as a heading level which is the "most sensible level in most situations".

To follow this logic through to its conclusion, though: if a modal dialog does need to participate in the page's overall hierarchy, why is hardcoding an h2 appropriate? Should the dialog title not use a heading level that causes it to slot into the parent section that invoked it? For example, if there is a section headed at level 3, and a button in that section invokes a modal, h4 is the most logical level, not h2.

To be clear, I'm not suggesting that this should be the case; I think I've been pretty unambiguous up to this point about my support for an h1. But it's important to explore the reasoning behind nobody following this seemingly logical pattern that I've outlined, and that's because the outcome is a confusing one for users and developers alike. It would act as an extremely limiting factor given that there are only six heading levels available, and again, would be confusing for users because they couldn't locate the parent headings anyway.

So, with that in mind, I'm struggling to see h2 as more appropriate than h1, rather than just an arbitrary choice.

Encountering a new h1 is typically an indication that the page has changed.

I'm not sure what you're basing this on, but the primary indication that the page has changed is a new page title, which in a standard multi-page app is announced by a screen reader automatically. The h1 is often a way down the page, at the start of the main content, and hence is not spoken automatically right away (if at all).

Similarly, when a dialog is invoked, and focus is placed e.g. on the "Close" button, a screen reader will inform the user of that context. They will know that they are inside a dialog, assuming that it is named and marked up correctly, and the h1 should then match the accessible name on the modal dialog container.

if the need truly arises, it's possible to use aria-level to create the equivalents of h7, h8, etc.

In theory, yes. In reality, most screen reader/browser combinations don't support this approach, and will either fall back to h6 or h2 when aria-level=">7" is encountered. Even if they do convey the heading level as 7 or above, there are no quick navigation keystrokes to jump to those heading levels specifically, and hence this approach must never be suggested, let alone encouraged.

I don't think it should make any difference as to whether or not my advice is taken on board. But for what it's worth, I speak not only as an accessibility professional, but a screen reader user myself.

I've enumerated my reasoning twice at this point, but in essence we have a 50/50 split between two people working in the accessibility industry. I will continue to advise clients to use an h1 for their dialog titles, including in the specific case that caused this bug to be filed, and I remain available to answer additional questions.

@xurxe
Copy link

xurxe commented Sep 18, 2022

Thanks @jscholes for your thoughtful reply!

What I understand from this conversation is that we both agree on our interpretation of ARIA 1.1 (side note: when I quoted the spec it was just for the benefit of the non-specialists reading, since I gathered you were already familiar with it), but we have different opinions regarding what's not directly said in the ARIA or HTML specs, especially in terms of how a modal dialog relates to the primary window / application. And it seems like we're not alone in that, judging by the different implementation examples that have been discussed in this thread.

I also wasn't very clear on what I meant by "h2 is the most sensible level in most situations" (thanks for pointing that out!). What I was trying to say that, in most instances of modal dialogs I've personally implemented or evaluated, I saw their content as something that is part of the main window, but at quite a high level (i.e. not deeply nested). Some examples:

  • A modal dialog containing a contact form, where the dialog is opened mainly through a button in the primary nav element, but in some pages also by a button that is part of the main element.
  • A modal dialog asking the user to take an extra step in order to confirm a sensitive or irreversible action.
  • A modal dialog containing important information regarding the outcome of a user action.

In most examples I could think of, if I was to use a heading element at all, I would have chosen h2.

I did however come up with some cases where I could see a lot of value in using h1 instead. One example would be a modal dialog requiring the user to confirm that they're over 18 in order to access, let's say, a gambling website. In that case, assuming that the dialog is automatically open when the user accesses the site for the first time and that the answer will be stored so that the dialog won't be shown in subsequent visits, it feels more intuitive to me that the heading on that modal would be h1.

I think a reasonable compromise would be to let developers customize the level of DialogTitle. Of course, a default level would still have to be chosen. I think the default should be h2, you think it should be h1; both options have their own logic that makes internal sense, and I ultimately don't think that either one would be incorrect :)

notlee added a commit to Financial-Times/origami that referenced this issue Oct 3, 2023
Typically one h1 on a page helps create a navigatable structure.
There Is No Document Outline Algorithm.
https://adrianroselli.com/2016/08/there-is-no-document-outline-algorithm.html#Update10

But I wasn't sure what the right answer is now we have `aria-modal` that can trap focus and mark other elements as inert, and went on a little side quest.

Turns out W3C's APG Task Force (ARIA Authoring Practices Guide) discussed this in a meeting a few years ago.
w3c/aria-practices#551 (comment)

They concluded:

- It is helpful if there is a consistent approach across dialogs in an application.
- There is not necessarily a need for the APG to prescribe a specific approach.

So, I guess provided you're in a modal either h1 or h2 is fine.

APG continue to use h2 in their example and Material UI are undecided, with some interesting back and fourth on when a h1 or h2 might be a better experience.
mui/material-ui#34250

Probably, it's not a big deal either way. If I had to pick a global rule based on the above and no access to direct user testing for this, I'd go with h2.

Here it is. A quick PR to switch to a h2.

This was prompted by a user question in the support Slack channel.
https://financialtimes.slack.com/archives/C02FU5ARJ/p1696242420071219
notlee added a commit to Financial-Times/origami that referenced this issue Oct 16, 2023
Typically one h1 on a page helps create a navigatable structure.
There Is No Document Outline Algorithm.
https://adrianroselli.com/2016/08/there-is-no-document-outline-algorithm.html#Update10

But I wasn't sure what the right answer is now we have `aria-modal` that can trap focus and mark other elements as inert, and went on a little side quest.

Turns out W3C's APG Task Force (ARIA Authoring Practices Guide) discussed this in a meeting a few years ago.
w3c/aria-practices#551 (comment)

They concluded:

- It is helpful if there is a consistent approach across dialogs in an application.
- There is not necessarily a need for the APG to prescribe a specific approach.

So, I guess provided you're in a modal either h1 or h2 is fine.

APG continue to use h2 in their example and Material UI are undecided, with some interesting back and fourth on when a h1 or h2 might be a better experience.
mui/material-ui#34250

Probably, it's not a big deal either way. If I had to pick a global rule based on the above and no access to direct user testing for this, I'd go with h2.

Here it is. A quick PR to switch to a h2.

This was prompted by a user question in the support Slack channel.
https://financialtimes.slack.com/archives/C02FU5ARJ/p1696242420071219
@abdermaiza
Copy link

Bootstrap had the same conversation, and the a11y expert (Patrick H. Lauke) said that a H1 for a modal title should be the best: "as modal dialogs create their own little world/document/structure, it would make sense that the title is the primary heading in this new "island" of content. particularly if the underlying page is hidden from AT"...

twbs/bootstrap#37179

Thanks!

@zannager zannager assigned siriwatknp and unassigned danilo-leal Feb 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accessibility a11y component: dialog This is the name of the generic UI component, not the React module! discussion
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants