Skip to content

Conversation

@ihardlight
Copy link

@ihardlight ihardlight commented Jun 10, 2025

Description

To improve accessibility and better support users with visual impairments, this PR introduces first-class support for high contrast themes. According to accessibility guidelines, high contrast modes are essential for many users, and making them easier to enable and manage significantly improves usability and inclusiveness.

Changes

  • Added a highContrast prop to the Theme components. When enabled, all nested elements automatically receive high contrast styling, removing the need to configure this individually on each component.
  • Added a high contrast toggle to ThemeToggle, making it easy to preview and switch high contrast mode during development or runtime.
  • When high contrast mode is active, the attribute [data-high-theme="true"] and the .high-contrast class are applied. This allows developers to check the contrast state in CSS or toggle it using external libraries—similar to the existing .light and .dark class mechanisms.

Testing steps

Open playground and try to toggle high contrast or copy theme
Critical moment: if you enable global high contrast you can not turn it off for individual component

Relates issues / PRs

Add the same functionality to next-themes pacocoursey/next-themes#360 to toggle contrast value using .high-contrast class in SSR-friendly way and including support prefers-contrast:more media query

In future step, after this PR will be merged I will update radix-ui docs to add info about this functional
After next-theme PR will be merged and released I will add an example how it works in playground

@vercel
Copy link

vercel bot commented Jun 10, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
themes-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 2, 2025 3:24pm

@ihardlight ihardlight marked this pull request as ready for review June 11, 2025 07:43
@ihardlight ihardlight changed the title Feat/theme high contrast feat: theme high contrast Jun 11, 2025
@ihardlight
Copy link
Author

@fauxparse Hi! Can you review this changes?

Copy link
Contributor

@lucasmotta lucasmotta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea, but can we keep only the :where([data-high-contrast="true"]) selector?
I see the .more-contrast may be provided by next-themes, but since that's not merged yet we can add this back later if needed.

@ihardlight
Copy link
Author

@lucasmotta I believe it’s a good idea to establish a consistent API for themes and contrasts from the beginning. Both can be accessed by modifying the class of the body tag.

Additionally, I’ve separated the next-contrast and next-themes. They’re still in the same repository but under different npm packages, allowing me to release them promptly without merging a PR.

In my opinion, it’s more practical to maintain the class toggle for contrast.

@lucasmotta
Copy link
Contributor

I hear you! The only part I'm not sure is to introduce another naming convention in our library: .more-contrast vs .high-contrast. If that's customizable from next-contrast, I would like to keep .high-contrast` in radix-themes to better align with the data attribute.

@ihardlight
Copy link
Author

@lucasmotta okay, I will change it to .high-contrast.
I chose .more-contrast because according to MDN documentation prefers-contrast returns 'more', 'less' or 'no-preference' so it was more semantically

@ihardlight
Copy link
Author

@lucasmotta I have resolved your issue. Would you like to proceed with merging PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants