-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Open
Labels
P4A relatively minor issue that is not relevant to core functionsA relatively minor issue that is not relevant to core functionsneeds: discussionFurther discussion with the team is needed before proceedingFurther discussion with the team is needed before proceeding
Description
Is this a regression?
- Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
v14.2.7
Description
There is a long-standing issue in Angular Material where, after clicking on interactive components (buttons, radio buttons, checkboxes, slide-toggle), the focus or “ripple” visual indicator remains visible until the user clicks somewhere else (i.e., until the component loses focus).
Key points:
- History of this issue
- In issue Radio button ripple effect 7.0.0-rc.1 #13544 (Oct 2018), a user reported that the radio ripple doesn’t fade when clicking: "the ripple doesn't fade away until it loses focus." The team responded that "it is intentional but only supposed to be for keyboard and programmatic focus."
- In mat-radio-button animation - outer circle remains at the end of the animation #14349 (Dec 2018), the animation "outer circle remains at the end [...] disappears only if I click somewhere" — also closed as working as intended for some obscure reasons (contradicting the answer from 2 months before)
- In Angular Material Radio button - Ripple effect persists until clicking away. #23807 (Oct. 2021), someones note that this started around Angular 11 and continues through Angular 12 and 13, and has been patched on v14, even if the issue was apparently related to PR fix(radio): show ripple on programmatic focus #16512, which was merged for accessibility reasons, and maintainers indicated at that time they didn’t want to revert it
- In bug(FocusMonitor): cdk-program-focused on mouse click #25188 (June 2022), someone reports that "clicked element contains cdk-program-focused class instead of cdk-mouse-focused", got answered that it "Should've been fixed in fix(cdk/a11y): correctly detect focus from input label #25232", but linked PR doesn't seem to be about cdk-mouse-focused at all?
- In bug(cdkContextMenu): First item focus:visible and gets ring design #31569 (July 2025), it's a bit different as it concerns menu items but still has the same issue: "right click first item gets focus (which he should), but he also receive focus:visible ring design". Another user points out that it may be related to "the sequence of events the CDK sends to it", but the issue died without any proper investigation.
- Fixes attempted
- The FocusMonitor bug bug(FocusMonitor): cdk-program-focused on mouse click #25188 (Jun 2022) where
cdk-program-focusedis incorrectly applied on mouse click was marked as completed - The associated PR fix(cdk/a11y): correctly detect focus from input label #25232 improved focus detection, especially when a label is clicked, but it doesn’t entirely solve the visual persistence issue for all components.
- Version testing on the Angular Material doc site
After checking each latest minor version on the material.angular.dev website:
- For checkboxes, the issue does not appear in earlier latest minor versions (before v15), but is present again from v15 onward (tested in v16, v17… up to v21 RC). A few issues also indicate this bug actually existed in version like v14 but got fixed before the latest minor, hence why I couldn't check it today.
- For radio buttons, the bug is visible from v11 to v13, was fixed in v14 (see Angular Material Radio button - Ripple effect persists until clicking away. #23807), but was reintroduced somewhen during v15 until today
- Accessibility & UX concerns
- The persistent indicator can be confusing: after clicking, the element looks like it’s still “active” or focused, which might not reflect its real state
- Most other libraries I've checked fade out ripples after mouse click, so this behavior is surprising for people used to other websites
- According to the CSS
:focus-visiblemechanism, focus indication should ideally reflect input modality (e.g. keyboard vs mouse). The MDN spec explains that:focus-visibleis designed to show focus rings only when useful (e.g. keyboard navigation), precisely to differentiate when focus indicators should be shown depending on input modality (y'know, on the contrary to:focus...). - Persistent focus indicators can degrade usability or cause visual noise, especially in complex UI flows (I actually got several bug reports from customers confused by it)
Reproduction
StackBlitz link: https://stackblitz.com/edit/components-issue-starter-dqjhk5mq?file=src%2Fmain.ts
Steps to reproduce:
- Use Angular Material (e.g. version 15+)
- Render a component like
<mat-radio-button>or<mat-checkbox> - Click the element with the mouse
- Observe that the ripple or focus ring stays visible after the click completes
- Click somewhere else (outside the element) to unfocus and notice how the focus indicator disappears
Expected Behavior
- After a mouse click, the ripple/focus indicator should fade out (or be removed) even if the component remains focused.
- The behavior should be consistent across input types: mouse clicks vs keyboard interactions
- Persistent focus indicators should align with modern focus pseudo-attributes (
:focusvs:focus-visible), showing visible indicators only when needed and not “sticking” unnecessarily after click interactions
Actual Behavior
- Ripple or focus ring remains on the component after click and only goes away when the component loses focus (when clicking away)
- This behavior is visible on both checkboxes, radio buttons and actual buttons
- The bug has appeared, disappeared, and reappeared across versions, suggesting regression or incomplete fix
Environment
Doesn't really matter that much but here's the linked Stackblitz env.
- Angular: 18.2.8
- Browser(s): Firefox 145.0
- Operating System (e.g. Windows, macOS, Ubuntu): Windows 11, macOS 26
Metadata
Metadata
Assignees
Labels
P4A relatively minor issue that is not relevant to core functionsA relatively minor issue that is not relevant to core functionsneeds: discussionFurther discussion with the team is needed before proceedingFurther discussion with the team is needed before proceeding