diff --git a/goldens/material/tooltip/index.api.md b/goldens/material/tooltip/index.api.md index fd219dd1dc81..bcf5273172e6 100644 --- a/goldens/material/tooltip/index.api.md +++ b/goldens/material/tooltip/index.api.md @@ -92,7 +92,7 @@ export class MatTooltip implements OnDestroy, AfterViewInit { // @public export interface MatTooltipDefaultOptions { - detectHoverCapability?: boolean; + detectHoverCapability?: boolean | (() => boolean); disableTooltipInteractivity?: boolean; hideDelay: number; position?: TooltipPosition; diff --git a/src/material/tooltip/tooltip.ts b/src/material/tooltip/tooltip.ts index 7902004be6e3..2058f39a8d46 100644 --- a/src/material/tooltip/tooltip.ts +++ b/src/material/tooltip/tooltip.ts @@ -140,12 +140,23 @@ export interface MatTooltipDefaultOptions { tooltipClass?: string | string[]; /** - * Whether the tooltip should use a media query to detect if the device is able to hover. - * Note that this may affect tests that run in a headless browser which reports that it's - * unable to hover. In such cases you may need to include an additional timeout, because - * the tooltip will fall back to treating the device as a touch screen. + * By default the tooltip attempts to detect whether the user's device is able to hover by + * consulting the `Platform` provider that was created a long time ago and is based on + * some data points that may not be entirely accurate anymore (e.g. user agent string and + * Android/iOS-specific APIs), however changing them will break existing users. You can use this + * config property to opt into a more modern detection mechanism. + * + * The supported values include: + * + * - `false` - Default value. Detection is based on the `Platform` provider. + * - `true` - The tooltip will use the `any-hover` media query for more accurate detection. + * Note that this may break existing unit tests running in a headless browser. + * - `() => boolean` - If the automatic detection doesn't work properly in your case (e.g. the + * `any-hover` media query isn't supported) and you're able to detect more accurately, you can + * pass in a function that will be used for detection instead. It should return `true` if the + * device **has the ability to hover**, or `false` if it cannot. */ - detectHoverCapability?: boolean; + detectHoverCapability?: boolean | (() => boolean); } /** @@ -855,6 +866,12 @@ export class MatTooltip implements OnDestroy, AfterViewInit { } private _isTouchPlatform(): boolean { + const detectHoverCapability = this._defaultOptions?.detectHoverCapability; + + if (typeof detectHoverCapability === 'function') { + return !detectHoverCapability(); + } + if (this._platform.IOS || this._platform.ANDROID) { // If we detected iOS or Android, it's definitely supported. return true; @@ -863,10 +880,7 @@ export class MatTooltip implements OnDestroy, AfterViewInit { return false; } - return ( - !!this._defaultOptions?.detectHoverCapability && - this._mediaMatcher.matchMedia('(any-hover: none)').matches - ); + return !!detectHoverCapability && this._mediaMatcher.matchMedia('(any-hover: none)').matches; } /** Disables the native browser gestures, based on how the tooltip has been configured. */