From 135bdd3cca222ddb181b995cfc847c25d27e0178 Mon Sep 17 00:00:00 2001 From: Jullierme Barros Date: Sun, 21 Jul 2024 11:22:21 -0300 Subject: [PATCH 1/3] feat(material/form-field): replicate tooltipClass to default MatTooltipDefaultOptions The `tooltipClass` property has been added to the default configuration options in `MatTooltipDefaultOptions`. This new property is optional and supports the same syntax as `ngClass`, just like the component's default attribute. As with some existing configurations, if a CSS class is defined directly on the tooltip component, it will automatically override the default class. An example has been added to the `tooltip-demo` file. Additionally, two tests have been created to ensure the solution works as expected. Fixes #29355 --- .../material/tooltip/index.ts | 1 + .../tooltip-default-custom-class-example.css | 3 + .../tooltip-default-custom-class-example.html | 5 ++ .../tooltip-default-custom-class-example.ts | 30 +++++++ src/dev-app/tooltip/tooltip-demo.html | 3 + src/dev-app/tooltip/tooltip-demo.ts | 2 + src/material/tooltip/tooltip.spec.ts | 81 +++++++++++++++++++ src/material/tooltip/tooltip.ts | 11 +++ 8 files changed, 136 insertions(+) create mode 100644 src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.css create mode 100644 src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.html create mode 100644 src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.ts diff --git a/src/components-examples/material/tooltip/index.ts b/src/components-examples/material/tooltip/index.ts index 1376bd523b27..aec973ba0861 100644 --- a/src/components-examples/material/tooltip/index.ts +++ b/src/components-examples/material/tooltip/index.ts @@ -1,5 +1,6 @@ export {TooltipAutoHideExample} from './tooltip-auto-hide/tooltip-auto-hide-example'; export {TooltipCustomClassExample} from './tooltip-custom-class/tooltip-custom-class-example'; +export {TooltipDefaultCustomClassExample} from './tooltip-default-custom-class/tooltip-default-custom-class-example'; export {TooltipDelayExample} from './tooltip-delay/tooltip-delay-example'; export {TooltipDisabledExample} from './tooltip-disabled/tooltip-disabled-example'; export {TooltipManualExample} from './tooltip-manual/tooltip-manual-example'; diff --git a/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.css b/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.css new file mode 100644 index 000000000000..bd01311d8566 --- /dev/null +++ b/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.css @@ -0,0 +1,3 @@ +.example-tooltip-default-custom-class { + text-transform: uppercase; +} diff --git a/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.html b/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.html new file mode 100644 index 000000000000..4ff8fa043d15 --- /dev/null +++ b/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.html @@ -0,0 +1,5 @@ + diff --git a/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.ts b/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.ts new file mode 100644 index 000000000000..315a4f651e31 --- /dev/null +++ b/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.ts @@ -0,0 +1,30 @@ +import {Component, ViewEncapsulation} from '@angular/core'; +import { + MAT_TOOLTIP_DEFAULT_OPTIONS, + MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY, + MatTooltipDefaultOptions, + MatTooltipModule, +} from '@angular/material/tooltip'; +import {MatButtonModule} from '@angular/material/button'; + +/** Custom options the configure the tooltip's default class. */ +export const myCustomTooltipDefaults: MatTooltipDefaultOptions = { + ...MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY(), + tooltipClass: 'example-tooltip-default-custom-class', +}; + +/** + * @title Tooltip with default custom class + */ +@Component({ + selector: 'tooltip-default-custom-class-example', + templateUrl: 'tooltip-default-custom-class-example.html', + styleUrl: 'tooltip-default-custom-class-example.css', + providers: [{provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: myCustomTooltipDefaults}], + standalone: true, + // Need to remove view encapsulation so that the custom tooltip style defined in + // `tooltip-default-custom-class-example.css` will not be scoped to this component's view. + encapsulation: ViewEncapsulation.None, + imports: [MatButtonModule, MatTooltipModule], +}) +export class TooltipDefaultCustomClassExample {} diff --git a/src/dev-app/tooltip/tooltip-demo.html b/src/dev-app/tooltip/tooltip-demo.html index b848c7acd64f..05b2356fb70b 100644 --- a/src/dev-app/tooltip/tooltip-demo.html +++ b/src/dev-app/tooltip/tooltip-demo.html @@ -4,6 +4,9 @@

Tooltip auto hide

Tooltip custom class

+

Tooltip default custom class

+ +

Tooltip with delay

diff --git a/src/dev-app/tooltip/tooltip-demo.ts b/src/dev-app/tooltip/tooltip-demo.ts index 10a8afadd0a3..68d25cba6b8f 100644 --- a/src/dev-app/tooltip/tooltip-demo.ts +++ b/src/dev-app/tooltip/tooltip-demo.ts @@ -8,6 +8,7 @@ import { TooltipAutoHideExample, TooltipCustomClassExample, + TooltipDefaultCustomClassExample, TooltipDelayExample, TooltipDisabledExample, TooltipHarnessExample, @@ -27,6 +28,7 @@ import {ChangeDetectionStrategy, Component} from '@angular/core'; imports: [ TooltipAutoHideExample, TooltipCustomClassExample, + TooltipDefaultCustomClassExample, TooltipDelayExample, TooltipDisabledExample, TooltipManualExample, diff --git a/src/material/tooltip/tooltip.spec.ts b/src/material/tooltip/tooltip.spec.ts index 5569df953caa..f6553f8a923d 100644 --- a/src/material/tooltip/tooltip.spec.ts +++ b/src/material/tooltip/tooltip.spec.ts @@ -233,6 +233,65 @@ describe('MDC-based MatTooltip', () => { expect(tooltipDirective._getOverlayPosition().fallback.overlayX).toBe('end'); })); + it('should be able to define a default (global) tooltip class', fakeAsync(() => { + TestBed.resetTestingModule() + .configureTestingModule({ + declarations: [TooltipDemoWithoutTooltipClassBinding], + imports: [MatTooltipModule, OverlayModule], + providers: [ + { + provide: MAT_TOOLTIP_DEFAULT_OPTIONS, + useValue: {tooltipClass: 'my-default-tooltip-class'}, + }, + ], + }) + .compileComponents(); + + const fixture = TestBed.createComponent(TooltipDemoWithoutTooltipClassBinding); + fixture.detectChanges(); + tooltipDirective = fixture.componentInstance.tooltip; + tooltipDirective.show(); + fixture.detectChanges(); + tick(); + const overlayRef = tooltipDirective._overlayRef!; + const tooltipElement = overlayRef.overlayElement.querySelector( + '.mat-mdc-tooltip', + ) as HTMLElement; + + expect(tooltipDirective.tooltipClass).toBe('my-default-tooltip-class'); + expect(tooltipElement.classList).toContain('my-default-tooltip-class'); + })); + + it('should be able to provide tooltip class over the custom default one', fakeAsync(() => { + TestBed.resetTestingModule() + .configureTestingModule({ + declarations: [TooltipDemoWithTooltipClassBinding], + imports: [MatTooltipModule, OverlayModule], + providers: [ + { + provide: MAT_TOOLTIP_DEFAULT_OPTIONS, + useValue: {tooltipClass: 'my-default-tooltip-class'}, + }, + ], + }) + .compileComponents(); + + const fixture = TestBed.createComponent(TooltipDemoWithTooltipClassBinding); + fixture.detectChanges(); + tooltipDirective = fixture.componentInstance.tooltip; + tooltipDirective.show(); + fixture.detectChanges(); + tick(); + const overlayRef = tooltipDirective._overlayRef!; + const tooltipElement = overlayRef.overlayElement.querySelector( + '.mat-mdc-tooltip', + ) as HTMLElement; + + expect(tooltipDirective.tooltipClass).not.toBe('my-default-tooltip-class'); + expect(tooltipElement.classList).not.toContain('my-default-tooltip-class'); + expect(tooltipElement.classList).toContain('fixed-tooltip-class'); + })); + it('should position on the bottom-left by default', fakeAsync(() => { // We don't bind mouse events on mobile devices. if (platform.IOS || platform.ANDROID) { @@ -1660,6 +1719,28 @@ class TooltipDemoWithoutPositionBinding { @ViewChild('button') button: ElementRef; } +@Component({ + selector: 'app', + template: ``, +}) +class TooltipDemoWithoutTooltipClassBinding { + message = initialTooltipMessage; + @ViewChild(MatTooltip) tooltip: MatTooltip; + @ViewChild('button') button: ElementRef; +} + +@Component({ + selector: 'app', + template: ` + + `, +}) +class TooltipDemoWithTooltipClassBinding { + message: any = initialTooltipMessage; + @ViewChild(MatTooltip) tooltip: MatTooltip; + @ViewChild('button') button: ElementRef; +} + @Component({ selector: 'app', styles: `button { width: 500px; height: 500px; }`, diff --git a/src/material/tooltip/tooltip.ts b/src/material/tooltip/tooltip.ts index be12011ed202..98c19c4eca8e 100644 --- a/src/material/tooltip/tooltip.ts +++ b/src/material/tooltip/tooltip.ts @@ -147,6 +147,13 @@ export interface MatTooltipDefaultOptions { /** Disables the ability for the user to interact with the tooltip element. */ disableTooltipInteractivity?: boolean; + + /** + * Default classes to be applied to the tooltip. Supports the same syntax as `ngClass`. These + * default classes will not be applied if `tooltipClass` is defined directly on the tooltip + * element, as it will override the default. + */ + tooltipClass?: string | string[] | Set | {[key: string]: any}; } /** @@ -389,6 +396,10 @@ export class MatTooltip implements OnDestroy, AfterViewInit { if (_defaultOptions.touchGestures) { this.touchGestures = _defaultOptions.touchGestures; } + + if (_defaultOptions.tooltipClass) { + this.tooltipClass = _defaultOptions.tooltipClass; + } } _dir.change.pipe(takeUntil(this._destroyed)).subscribe(() => { From bc3d4fd916d118c93ed670efc302e1dfcaf510d8 Mon Sep 17 00:00:00 2001 From: Jullierme Barros Date: Sun, 21 Jul 2024 16:25:56 -0300 Subject: [PATCH 2/3] feat(material/form-field): replicate tooltipClass to default MatTooltipDefaultOptions The `tooltipClass` property has been added to the default configuration options in `MatTooltipDefaultOptions`. This new property is optional. As with some existing configurations, if a CSS class is defined directly on the tooltip component, it will automatically override the default class. Two tests have been created to ensure the solution works as expected. Fixes #29355 --- .../material/tooltip/index.ts | 1 - .../tooltip-default-custom-class-example.css | 3 -- .../tooltip-default-custom-class-example.html | 5 ---- .../tooltip-default-custom-class-example.ts | 30 ------------------- src/dev-app/tooltip/tooltip-demo.ts | 2 -- src/material/tooltip/tooltip.ts | 7 ++--- 6 files changed, 3 insertions(+), 45 deletions(-) delete mode 100644 src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.css delete mode 100644 src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.html delete mode 100644 src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.ts diff --git a/src/components-examples/material/tooltip/index.ts b/src/components-examples/material/tooltip/index.ts index aec973ba0861..1376bd523b27 100644 --- a/src/components-examples/material/tooltip/index.ts +++ b/src/components-examples/material/tooltip/index.ts @@ -1,6 +1,5 @@ export {TooltipAutoHideExample} from './tooltip-auto-hide/tooltip-auto-hide-example'; export {TooltipCustomClassExample} from './tooltip-custom-class/tooltip-custom-class-example'; -export {TooltipDefaultCustomClassExample} from './tooltip-default-custom-class/tooltip-default-custom-class-example'; export {TooltipDelayExample} from './tooltip-delay/tooltip-delay-example'; export {TooltipDisabledExample} from './tooltip-disabled/tooltip-disabled-example'; export {TooltipManualExample} from './tooltip-manual/tooltip-manual-example'; diff --git a/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.css b/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.css deleted file mode 100644 index bd01311d8566..000000000000 --- a/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.css +++ /dev/null @@ -1,3 +0,0 @@ -.example-tooltip-default-custom-class { - text-transform: uppercase; -} diff --git a/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.html b/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.html deleted file mode 100644 index 4ff8fa043d15..000000000000 --- a/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.html +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.ts b/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.ts deleted file mode 100644 index 315a4f651e31..000000000000 --- a/src/components-examples/material/tooltip/tooltip-default-custom-class/tooltip-default-custom-class-example.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {Component, ViewEncapsulation} from '@angular/core'; -import { - MAT_TOOLTIP_DEFAULT_OPTIONS, - MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY, - MatTooltipDefaultOptions, - MatTooltipModule, -} from '@angular/material/tooltip'; -import {MatButtonModule} from '@angular/material/button'; - -/** Custom options the configure the tooltip's default class. */ -export const myCustomTooltipDefaults: MatTooltipDefaultOptions = { - ...MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY(), - tooltipClass: 'example-tooltip-default-custom-class', -}; - -/** - * @title Tooltip with default custom class - */ -@Component({ - selector: 'tooltip-default-custom-class-example', - templateUrl: 'tooltip-default-custom-class-example.html', - styleUrl: 'tooltip-default-custom-class-example.css', - providers: [{provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: myCustomTooltipDefaults}], - standalone: true, - // Need to remove view encapsulation so that the custom tooltip style defined in - // `tooltip-default-custom-class-example.css` will not be scoped to this component's view. - encapsulation: ViewEncapsulation.None, - imports: [MatButtonModule, MatTooltipModule], -}) -export class TooltipDefaultCustomClassExample {} diff --git a/src/dev-app/tooltip/tooltip-demo.ts b/src/dev-app/tooltip/tooltip-demo.ts index 68d25cba6b8f..10a8afadd0a3 100644 --- a/src/dev-app/tooltip/tooltip-demo.ts +++ b/src/dev-app/tooltip/tooltip-demo.ts @@ -8,7 +8,6 @@ import { TooltipAutoHideExample, TooltipCustomClassExample, - TooltipDefaultCustomClassExample, TooltipDelayExample, TooltipDisabledExample, TooltipHarnessExample, @@ -28,7 +27,6 @@ import {ChangeDetectionStrategy, Component} from '@angular/core'; imports: [ TooltipAutoHideExample, TooltipCustomClassExample, - TooltipDefaultCustomClassExample, TooltipDelayExample, TooltipDisabledExample, TooltipManualExample, diff --git a/src/material/tooltip/tooltip.ts b/src/material/tooltip/tooltip.ts index 98c19c4eca8e..428d8a5792fc 100644 --- a/src/material/tooltip/tooltip.ts +++ b/src/material/tooltip/tooltip.ts @@ -149,11 +149,10 @@ export interface MatTooltipDefaultOptions { disableTooltipInteractivity?: boolean; /** - * Default classes to be applied to the tooltip. Supports the same syntax as `ngClass`. These - * default classes will not be applied if `tooltipClass` is defined directly on the tooltip - * element, as it will override the default. + * Default classes to be applied to the tooltip. These default classes will not be applied if + * `tooltipClass` is defined directly on the tooltip element, as it will override the default. */ - tooltipClass?: string | string[] | Set | {[key: string]: any}; + tooltipClass?: string | string[]; } /** From 9021346d223feff17e8ba9cce78b13b3a747807e Mon Sep 17 00:00:00 2001 From: Jullierme Barros Date: Sun, 21 Jul 2024 16:27:55 -0300 Subject: [PATCH 3/3] feat(material/form-field): replicate tooltipClass to default MatTooltipDefaultOptions The `tooltipClass` property has been added to the default configuration options in `MatTooltipDefaultOptions`. This new property is optional. As with some existing configurations, if a CSS class is defined directly on the tooltip component, it will automatically override the default class. Two tests have been created to ensure the solution works as expected. Fixes #29355 --- src/dev-app/tooltip/tooltip-demo.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dev-app/tooltip/tooltip-demo.html b/src/dev-app/tooltip/tooltip-demo.html index 05b2356fb70b..b848c7acd64f 100644 --- a/src/dev-app/tooltip/tooltip-demo.html +++ b/src/dev-app/tooltip/tooltip-demo.html @@ -4,9 +4,6 @@

Tooltip auto hide

Tooltip custom class

-

Tooltip default custom class

- -

Tooltip with delay