bug(focus): Persistent focus/ripple indicator stays visible on click
未关闭
还没有人认领这个 Issue。
needs: discussion
P4
- 主要语言
- TypeScript
- 星标
- 25k
- 派生
- 6.8k
- 平均合并
- 1 天 8 小时
- 30 天内合并 PR
- 91
描述
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 #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 #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 #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 #16512, which was merged for accessibility reasons, and maintainers indicated at that time they didn’t want to revert it
- In #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 #25232", but linked PR doesn't seem to be about cdk-mouse-focused at all?
- In #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 #25188 (Jun 2022) where
cdk-program-focusedis incorrectly applied on mouse click was marked as completed - The associated PR #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 #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
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从链接的 StackBlitz 复现开始,比较 mat-radio-button、mat-checkbox 和按钮在报告的各个版本中的鼠标点击行为。跟踪这些组件使用的焦点和 ripple 处理,然后验证鼠标指示器会淡出而不会抑制键盘焦点指示,并确认该行为在列出的输入类型之间保持一致。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- angular, typescript
- 领域
- accessibility, frontend
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 38/100