From df5c1d6fcd0b013bebc132188335f3b36cb76963 Mon Sep 17 00:00:00 2001 From: Yogeshwaran C <84272111+yogeshwaran-c@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:54:52 +0530 Subject: [PATCH 1/2] fix(material/form-field): add aria-hidden to line ripple directive --- .../form-field/directives/line-ripple.ts | 145 +++++++++--------- 1 file changed, 73 insertions(+), 72 deletions(-) diff --git a/src/material/form-field/directives/line-ripple.ts b/src/material/form-field/directives/line-ripple.ts index f334b3314dd4..416bbca217e1 100644 --- a/src/material/form-field/directives/line-ripple.ts +++ b/src/material/form-field/directives/line-ripple.ts @@ -1,72 +1,73 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import {Directive, ElementRef, NgZone, OnDestroy, Renderer2, inject} from '@angular/core'; - -/** Class added when the line ripple is active. */ -const ACTIVATE_CLASS = 'mdc-line-ripple--active'; - -/** Class added when the line ripple is being deactivated. */ -const DEACTIVATING_CLASS = 'mdc-line-ripple--deactivating'; - -/** - * Internal directive that creates an instance of the MDC line-ripple component. Using a - * directive allows us to conditionally render a line-ripple in the template without having - * to manually create and destroy the `MDCLineRipple` component whenever the condition changes. - * - * The directive sets up the styles for the line-ripple and provides an API for activating - * and deactivating the line-ripple. - */ -@Directive({ - selector: 'div[matFormFieldLineRipple]', - host: { - 'class': 'mdc-line-ripple', - }, -}) -export class MatFormFieldLineRipple implements OnDestroy { - private _elementRef = inject>(ElementRef); - private _cleanupTransitionEnd!: () => void; - - constructor(...args: unknown[]); - - constructor() { - const ngZone = inject(NgZone); - const renderer = inject(Renderer2); - - ngZone.runOutsideAngular(() => { - this._cleanupTransitionEnd = renderer.listen( - this._elementRef.nativeElement, - 'transitionend', - this._handleTransitionEnd, - ); - }); - } - - activate() { - const classList = this._elementRef.nativeElement.classList; - classList.remove(DEACTIVATING_CLASS); - classList.add(ACTIVATE_CLASS); - } - - deactivate() { - this._elementRef.nativeElement.classList.add(DEACTIVATING_CLASS); - } - - private _handleTransitionEnd = (event: TransitionEvent) => { - const classList = this._elementRef.nativeElement.classList; - const isDeactivating = classList.contains(DEACTIVATING_CLASS); - - if (event.propertyName === 'opacity' && isDeactivating) { - classList.remove(ACTIVATE_CLASS, DEACTIVATING_CLASS); - } - }; - - ngOnDestroy() { - this._cleanupTransitionEnd(); - } -} +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import {Directive, ElementRef, NgZone, OnDestroy, Renderer2, inject} from '@angular/core'; + +/** Class added when the line ripple is active. */ +const ACTIVATE_CLASS = 'mdc-line-ripple--active'; + +/** Class added when the line ripple is being deactivated. */ +const DEACTIVATING_CLASS = 'mdc-line-ripple--deactivating'; + +/** + * Internal directive that creates an instance of the MDC line-ripple component. Using a + * directive allows us to conditionally render a line-ripple in the template without having + * to manually create and destroy the `MDCLineRipple` component whenever the condition changes. + * + * The directive sets up the styles for the line-ripple and provides an API for activating + * and deactivating the line-ripple. + */ +@Directive({ + selector: 'div[matFormFieldLineRipple]', + host: { + 'class': 'mdc-line-ripple', + 'aria-hidden': 'true', + }, +}) +export class MatFormFieldLineRipple implements OnDestroy { + private _elementRef = inject>(ElementRef); + private _cleanupTransitionEnd!: () => void; + + constructor(...args: unknown[]); + + constructor() { + const ngZone = inject(NgZone); + const renderer = inject(Renderer2); + + ngZone.runOutsideAngular(() => { + this._cleanupTransitionEnd = renderer.listen( + this._elementRef.nativeElement, + 'transitionend', + this._handleTransitionEnd, + ); + }); + } + + activate() { + const classList = this._elementRef.nativeElement.classList; + classList.remove(DEACTIVATING_CLASS); + classList.add(ACTIVATE_CLASS); + } + + deactivate() { + this._elementRef.nativeElement.classList.add(DEACTIVATING_CLASS); + } + + private _handleTransitionEnd = (event: TransitionEvent) => { + const classList = this._elementRef.nativeElement.classList; + const isDeactivating = classList.contains(DEACTIVATING_CLASS); + + if (event.propertyName === 'opacity' && isDeactivating) { + classList.remove(ACTIVATE_CLASS, DEACTIVATING_CLASS); + } + }; + + ngOnDestroy() { + this._cleanupTransitionEnd(); + } +} From cd57f38d1e48b61233cf41c82961993fdf984acb Mon Sep 17 00:00:00 2001 From: Yogeshwaran C <84272111+yogeshwaran-c@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:55:09 +0530 Subject: [PATCH 2/2] fix(material/form-field): add aria-hidden to focus overlay and hint spacer --- src/material/form-field/form-field.html | 244 ++++++++++++------------ 1 file changed, 122 insertions(+), 122 deletions(-) diff --git a/src/material/form-field/form-field.html b/src/material/form-field/form-field.html index b5e38afad4fb..783edd94b139 100644 --- a/src/material/form-field/form-field.html +++ b/src/material/form-field/form-field.html @@ -1,122 +1,122 @@ - - - @if (_hasFloatingLabel()) { - - } - - -
- @if (!_hasOutline() && !_control.disabled) { -
- } -
- @if (_hasOutline()) { -
- @if (!_forceDisplayInfixLabel()) { - - } -
- } - - @if (_hasIconPrefix) { -
- -
- } - - @if (_hasTextPrefix) { -
- -
- } - -
- @if (!_hasOutline() || _forceDisplayInfixLabel()) { - - } - - -
- - @if (_hasTextSuffix) { -
- -
- } - - @if (_hasIconSuffix) { -
- -
- } -
- - @if (!_hasOutline()) { -
- } -
- -
- @let subscriptMessageType = _getSubscriptMessageType(); - - @switch (subscriptMessageType) { - @case ('error') { -
- -
- } - - @case ('hint') { -
- @if (hintLabel) { - {{hintLabel}} - } - -
- -
- } - } -
+ + + @if (_hasFloatingLabel()) { + + } + + +
+ @if (!_hasOutline() && !_control.disabled) { + + } +
+ @if (_hasOutline()) { +
+ @if (!_forceDisplayInfixLabel()) { + + } +
+ } + + @if (_hasIconPrefix) { +
+ +
+ } + + @if (_hasTextPrefix) { +
+ +
+ } + +
+ @if (!_hasOutline() || _forceDisplayInfixLabel()) { + + } + + +
+ + @if (_hasTextSuffix) { +
+ +
+ } + + @if (_hasIconSuffix) { +
+ +
+ } +
+ + @if (!_hasOutline()) { +
+ } +
+ +
+ @let subscriptMessageType = _getSubscriptMessageType(); + + @switch (subscriptMessageType) { + @case ('error') { +
+ +
+ } + + @case ('hint') { +
+ @if (hintLabel) { + {{hintLabel}} + } + + + +
+ } + } +