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

Low Contrast in Filled Tonal Buttons and Segmented Controls Affects Accessibility #44808

Open
khsbory opened this issue Dec 18, 2024 · 9 comments
Assignees
Labels
accessibility a11y package: material-ui Specific to @mui/material status: waiting for author Issue with insufficient information support: question Community support but can be turned into an improvement

Comments

@khsbory
Copy link

khsbory commented Dec 18, 2024

Steps to reproduce

Hello,
I'm writing to report an accessibility issue regarding the contrast ratio of Filled Tonal Buttons and Segmented Controls in Material UI. I work as an accessibility consultant and frequently reference Material UI components due to their generally strong adherence to accessibility standards.
However, I've identified a significant concern regarding the contrast ratio of two specific components: Filled Tonal Buttons and Segmented Controls. According to WCAG 2.1 (Web Content Accessibility Guidelines), the minimum contrast ratio between foreground and background colors is 4.5:1 for normal text and 3:1 for large text. Large text is defined as 18pt (24px) or larger, or 14pt (18.66px) or larger if bold. Based on my tests, both the Filled Tonal Buttons and Segmented Controls fail to meet these requirements.
Filled Tonal Buttons
These buttons have a background behind the text, but the contrast between the text color and the background is too low. This makes it difficult for users with low vision to perceive these elements as interactive buttons. Instead, they may appear as plain text, which reduces usability and impedes interaction.
Segmented Controls
These components rely on a border to indicate the selected state. However, the contrast between the border and the background is insufficient, making it challenging for users with low vision to identify the currently selected option. This can lead to confusion and hinder navigation.
To demonstrate these issues, I've prepared a sample page:
http://khsbory.iptime.org:3000/time-management/
On this page, you will find examples of both components exhibiting low contrast problems.
I would appreciate it if you could review the contrast ratios and provide your feedback on the following points:

  1. Are you aware of the contrast issues in these components?
  2. Do you agree that these issues need to be addressed to comply with WCAG 2.1?
  3. What are your plans to improve the contrast ratios for these components?
  4. If you believe this is not a significant issue, could you elaborate on why and whether you recommend relying on assistive technologies like colour filters or contrast enhancement tools as an alternative?
    Accessibility and WCAG Compliance
    As per WCAG guidelines, sufficient contrast must be provided by default without requiring users to rely on assistive technologies. While tools like colour filters or contrast enhancement can support accessibility, they should not be considered primary solutions. Ensuring adequate contrast directly within the design benefits all users, including those with visual impairments.
    Material UI's reputation for accessibility has made it a trusted choice for many developers. Addressing this issue would further enhance its usability and inclusivity, benefiting a wide audience.
    Thank you for your attention to this matter. I look forward to your response.

Current behavior

No response

Expected behavior

No response

Context

No response

Your environment

npx @mui/envinfo
  Don't forget to mention which browser you used.
  Output from `npx @mui/envinfo` goes here.

Search keywords: accessibility, low contrast, filled tonal button, segmented control button

@khsbory khsbory added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Dec 18, 2024
@mj12albert
Copy link
Member

To demonstrate these issues, I've prepared a sample page:
http://khsbory.iptime.org:3000/time-management/

@khsbory Would you mind making a repro in codesandbox or stackblitz so the source is visible as well? Thanks ~

@mj12albert mj12albert added package: material-ui Specific to @mui/material status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Dec 18, 2024
@khsbory
Copy link
Author

khsbory commented Dec 19, 2024

Thank you for your response. I understand your request. I will zip my entire Next.js project and send it to you so that you can reproduce the issue. However, I am currently at work, and my server is at home. Therefore, I will compress the project into a zip file and upload it to my server tonight (Korean time). Once it's ready, I will provide you with the link.
Thank you for your understanding!

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Dec 19, 2024
@mj12albert
Copy link
Member

mj12albert commented Dec 19, 2024

I will zip my entire Next.js project and send it to you so that you can reproduce the issue.

@khsbory Please just make a minimal repro that just shows the color issue! There's no need for a whole project 😅

(Here are some tips: https://stackoverflow.com/help/minimal-reproducible-example)

Or if the issue is present in the default Material UI theme, maybe it's visible on our docs site as well?

@mj12albert mj12albert added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Dec 19, 2024
@khsbory
Copy link
Author

khsbory commented Dec 19, 2024

The code is quite straightforward since the link I sent you is actually a live sample page. It's already implemented as a working example, so the code has been kept concise and clear.
I'll send you the specific tsx file when I get home tonight.
Thank you.

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Dec 19, 2024
@mj12albert mj12albert added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Dec 19, 2024
@mnajdova
Copy link
Member

Filled Tonal Buttons and Segmented Controls

Just making sure I understand the issue. Material UI is still based on Material Design v2, we don't have filled tonal button - this is an MD3 (Material You) variant. The link you shared is showing a contained button, and the contrast ratio seems ok - https://www.siegemedia.com/contrast-ratio#%231976d2-on-white

@khsbory
Copy link
Author

khsbory commented Dec 19, 2024

Thank you for sharing your insights. I have a couple of follow-up questions:
1.
When you mentioned the “contained button,” were you referring to the refresh button on the sample site I sent? If so, could you please let me know the exact luminance contrast ratio that you measured? I’m asking because, during our tests with users who have low vision, we recorded a significantly lower contrast ratio.
2.
What are your thoughts on the segmented control button?
For your reference, I’ve included the code snippet below.

// Segmented control
'use client';

import { ToggleButtonGroup, ToggleButton } from '@mui/material';
import { useState } from 'react';

export default function TimeSegmentedButton({ onChange }) {
const [selected, setSelected] = useState('day');

const handleChange = (event, newValue) => {
if (newValue !== null) {
setSelected(newValue);
onChange?.(newValue);
}
};

return (
<ToggleButtonGroup
value={selected}
exclusive
onChange={handleChange}
aria-label="time period"
sx={{ m: 1 }}
>

Day


Week


Month


);
}

// Filled tonal button
'use client';

import { Button } from '@mui/material';

export default function TonalButton({ children, onClick }) {
return (
<Button
variant="filledTonal"
onClick={onClick}
sx={{ m: 1 }}
>
{children}

);
}

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Dec 19, 2024
@DiegoAndai
Copy link
Member

Hey @kshuiroy, thanks for the report!

May I ask you to provide a minimal reproduction? This would help a lot. A live example would be perfect. This StackBlitz sandbox template may be a good starting point.

If you are using a custom theme, please also add it to the sandbox. You also mention the "filled tonal" variant, but Material UI doesn't have that. If this is custom from your codebase, please add that as well.

Finally, please attach how you are measuring the a11y metrics you mention and what the scores are.

Without this information, this issue is not actionable on our side.

@DiegoAndai DiegoAndai added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Dec 19, 2024
@khsbory
Copy link
Author

khsbory commented Dec 21, 2024

Hi,

I've prepared a minimal Next.js project to demonstrate the issue I'm encountering. You can download it here: https://khsruru.com/material-ui-test.zip

Steps to Reproduce:

  1. Download the zip file from the link above.
  2. Extract the contents of the zip file.
  3. Open a terminal or command prompt in the extracted directory.
  4. Run npm install to install the necessary Node modules.
  5. Once the installation is complete, run npm run dev.
  6. This will start the project in development mode. You'll see a "Contrast Test" webpage initially.
  7. Navigate to the "Time Management" page by clicking on the menu. This is the page where I'm encountering contrast issues.

Specific Issues:

  • Segmented Buttons: On the "Time Management" page, the segmented buttons (Day, Week, Month) have an issue where the border of the selected button is difficult to see. This is because the contrast ratio is not high enough.
  • Tonal Button: The "Refresh" button (tonal button) is also difficult to distinguish as a button due to its low contrast.

Contrast Measurement and Accessibility:

The current issue is that the contrast ratio for both the Material Segmented Buttons and the Tonal Button does not meet the minimum requirement of 3:1 for graphical objects and user interface components, as outlined in WCAG 2.1 success criterion 1.4.11 Non-text Contrast.

  • How to measure contrast ratio
    • Download the Colour Contrast Analyser (CCA) from: https://www.tpgi.com/color-contrast-checker/
    • Use the CCA's color picker tool to sample the foreground color (e.g., the border color or button text color).
    • Use the color picker again to sample the background color.
    • The CCA will display the contrast ratio. It should be at least 3:1 for these UI elements.

Additional Information:

  • Feel free to ask if you have any questions about the code or need any clarification.

Thank you for your time and assistance! I appreciate any help you can provide in resolving this.

Best regards,

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Dec 21, 2024
@DiegoAndai DiegoAndai added support: question Community support but can be turned into an improvement and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Dec 24, 2024
@DiegoAndai
Copy link
Member

Thanks for the minimal reproduction @khsbory.

Segmented buttons

You can override the border color using the sx prop to comply to the a11y guidelines you want to meet. For example in the /src/app/components/TimeSegmentedButton.tsx file you could do:

-      <ToggleButton value="day" aria-label="day view">
+      <ToggleButton sx={{ borderColor: '#777' }} value="day" aria-label="day view">
        Day
      </ToggleButton>

You can also do this on the theme file, see https://mui.com/material-ui/customization/theme-components/#theme-style-overrides.

cc: @zanivan to check if there's something to fix in the library itself.

Tonal button issue

For this button, you're providing variant="filledTonal". This is not a valid variant. You can see the available variants here: https://mui.com/material-ui/api/button/#button-prop-variant. Because this is not a valid variant, the styles are broken.

@DiegoAndai DiegoAndai reopened this Dec 24, 2024
@DiegoAndai DiegoAndai added the status: waiting for author Issue with insufficient information label Dec 24, 2024
@mui mui deleted a comment from github-actions bot Dec 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accessibility a11y package: material-ui Specific to @mui/material status: waiting for author Issue with insufficient information support: question Community support but can be turned into an improvement
Projects
None yet
Development

No branches or pull requests

6 participants