Repository navigation
OpenConceptLab/ocl_issues#2969 | Filled buttons keep 4.5:1 text contrast on hover - #117
Merged
Merged
Conversation
…ast on hover MUI fills a hovered contained button, and a hovered or keyboard-focused clickable chip that has a color, with palette.<color>.dark under contrastText (white). Every .dark in colors.jsx was a tone-80 light tint, so that text fell to about 1.7:1; WCAG 1.4.3 asks 4.5:1. Each .dark is now its palette's tone 30: primary #2d00e5, secondary #464559, tertiary #603c50, error #93000a (M3 error tone 30), each 9.29:1 or more under white. success and info spread primary and secondary in the theme, so they follow. surface.dark is a text color and stays. The user menu's sign-out button used primary.dark as a light fill; it now names primary.80, the same #c3c0ff, so it looks as before. CloseIconButton and DisplayMenu pass 'info.dark' as a color prop. MUI 9 matches that prop only against palette names, so it never resolved: they render the default or inherited color, the same before and after. A test fails if primary, secondary, tertiary or error .dark drops under 4.5:1 against its contrastText. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
paynejd
commented
Oct 27, 2026
paynejd
left a comment
Member
Author
There was a problem hiding this comment.
Codex review, pass 1 (codex-cli 0.164.0, commit 1356f90)
Verdict: clean. No material defects.
findings.json
{
"reviewer": "codex-cli 0.164.0",
"perspective": "defects",
"mode": "full",
"commit": "1356f902737be6380efe9af416e5bbcd6dfa7038",
"verdict": "clean",
"prior": [],
"findings": []
}
Member
Author
|
Simplification review (fresh Claude subagent, lean-loop |
Member
Author
|
On the MapButton divider: no caller reaches the contained split group today, so nothing on screen changes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MUI fills a hovered contained button, and a hovered or keyboard-focused clickable chip that has a color, with
palette.<color>.darkundercontrastText(white). Every.darkinsrc/common/colors.jsxwas a tone-80 light tint, so that text fell to about 1.7:1. WCAG 1.4.3 asks 4.5:1.What changed
src/common/colors.jsx: each.darkis now its palette's tone 30, with a comment on whatdarkis for..dark.dark#c3c0ff#2d00e5#c7c4dd#464559#eab9d1#603c50#ffb4ab#93000a(M3 error tone 30)The theme in
src/index.jsxspreads primary intosuccessand secondary intoinfo, so those follow.surface.darkis a text color (#1c1b1f) and stays.src/components/users/UserMenu.jsx: the sign-out button usedprimary.darkas a light fill. It now namesprimary.80, the same#c3c0ff.src/common/__tests__/colors.test.js: fails if primary, secondary, tertiary or error.darkdrops under 4.5:1 against itscontrastText(MUI'sgetContrastRatio).Every
.darkuse insrc/primary.darkas the sign-out fill: moved toprimary.80. It looks as before.info.darkinCloseIconButtonandDisplayMenu: never resolved, left alone (below).surface.dark, about 30 text colors: the value doesn't change..darkin SCSS, and noPRIMARY_COLORS.dark,COLORS.x.darkorpalette.x.darkin code.The
info.darkfindingCloseIconButtonpassescolor='info.dark'toIconButton.DisplayMenupasses it toButtonGroup, to the unselectedButtonand to both icons. MUI 9'sIconButton,Button,ButtonGroupandSvgIconstyle thecolorprop only through variants built from palette names (Object.entries(theme.palette)). So'info.dark'adds acolorInfo.darkclass and no style.Measured in headless Chromium under the app's palette, with the old and the new colors:
CloseIconButton:rgba(0, 0, 0, 0.54), IconButton's default (action.active).color='info'would give#5e5c71.DisplayMenu, unselected button: text and icon inherit the surrounding text color, and the border iscurrentColor.Both are identical before and after, so this PR leaves them alone.
One visible change to know about
MUI draws the line between the halves of a contained
ButtonGroupinpalette[color].dark. In oclmap that'sMapButton's "Map ▾" split button before a concept is mapped. The line goes from#c3c0ffto#2d00e5, MUI's intended dark divider. Its contrast with the#4836fffill drops from 3.80:1 to 1.45:1. The ▾ glyph still marks the menu half. Ansxborder color on thatButtonGroupwould bring back the light line if we want it.How it was tested
Test first: the new test failed on the old values (four failures, 1.70 to 1.71:1) and passes on the new ones.
Rendered check: a throwaway webpack harness (not committed) rendered the real
CloseIconButton,DisplayMenuandcommon/Buttonunder the app's palette, old and new colors side by side. Computed styles were read in headless Chromium after MUI's transition:#c3c0ff#2d00e5#ffb4ab#93000acommon/Button,color='primary'), hover#c3c0ff#2d00e5Mui-focusVisible)#c3c0ff#2d00e5#c3c0ff/rgba(0,0,0,.12)CloseIconButtonrgba(0,0,0,.54)DisplayMenubuttons and icons#4836ffselected, inherited otherwiseButtonGroupdivider#c3c0ff#2d00e5CI gate, as
.github/workflows/pr.ymlruns it:npm ci;./node_modules/eslint/bin/eslint.js src --ext .jsx,.jsexits 0;npm run test:allpasses 607/607 unit and 6/6 integration tests.Acceptance criteria covered here (oclmap)
.darkvalues insrc/common/colors.jsxare tone 30, and nothing uses a.darkcolor as a light tint..darkdrops under 4.5:1 against itscontrastText.common/Buttonwithcolor='primary'was checked.oclweb3 and the design system are separate PRs.
Part of OpenConceptLab/ocl_issues#2969
🤖 Generated with Claude Code