Skip to content

Commit 0d735d9

Browse files
committed
fix(tooltip): unable to type in input with tooltip on iOS
Fixes an issue, caused by HammerJS adding `user-select: none` to the trigger element, that prevents users from being able to type inside inputs on iOS, if they have a tooltip. Fixes #8331.
1 parent 461dfaf commit 0d735d9

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

src/lib/tooltip/tooltip.spec.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ describe('MatTooltip', () => {
4343
BasicTooltipDemo,
4444
ScrollableTooltipDemo,
4545
OnPushTooltipDemo,
46-
DynamicTooltipsDemo
46+
DynamicTooltipsDemo,
47+
TooltipOnTextFields
4748
],
4849
providers: [
4950
{provide: Platform, useValue: {IOS: false, isBrowser: true}},
@@ -667,6 +668,25 @@ describe('MatTooltip', () => {
667668
}));
668669
});
669670

671+
describe('special cases', () => {
672+
it('should clear the `user-select` when a tooltip is set on a text field in iOS', () => {
673+
TestBed.overrideProvider(Platform, {
674+
useValue: {IOS: true, isBrowser: true}
675+
});
676+
677+
const fixture = TestBed.createComponent(TooltipOnTextFields);
678+
const instance = fixture.componentInstance;
679+
680+
fixture.detectChanges();
681+
682+
expect(instance.input.nativeElement.style.userSelect).toBeFalsy();
683+
expect(instance.input.nativeElement.style.webkitUserSelect).toBeFalsy();
684+
685+
expect(instance.textarea.nativeElement.style.userSelect).toBeFalsy();
686+
expect(instance.textarea.nativeElement.style.webkitUserSelect).toBeFalsy();
687+
});
688+
});
689+
670690
});
671691

672692
@Component({
@@ -752,6 +772,24 @@ class DynamicTooltipsDemo {
752772
}
753773
}
754774

775+
@Component({
776+
template: `
777+
<input
778+
#input
779+
style="user-select: none; -webkit-user-select: none"
780+
matTooltip="Something">
781+
782+
<textarea
783+
#textarea
784+
style="user-select: none; -webkit-user-select: none"
785+
matTooltip="Another thing"></textarea>
786+
`,
787+
})
788+
class TooltipOnTextFields {
789+
@ViewChild('input') input: ElementRef;
790+
@ViewChild('textarea') textarea: ElementRef;
791+
}
792+
755793
/** Asserts whether a tooltip directive has a tooltip instance. */
756794
function assertTooltipInstance(tooltip: MatTooltip, shouldExist: boolean): void {
757795
// Note that we have to cast this to a boolean, because Jasmine will go into an infinite loop

src/lib/tooltip/tooltip.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ export class MatTooltip implements OnDestroy {
176176
@Inject(MAT_TOOLTIP_SCROLL_STRATEGY) private _scrollStrategy,
177177
@Optional() private _dir: Directionality) {
178178

179+
const element: HTMLElement = _elementRef.nativeElement;
180+
179181
// The mouse events shouldn't be bound on iOS devices, because
180182
// they can prevent the first tap from firing its click event.
181183
if (!_platform.IOS) {
@@ -184,9 +186,16 @@ export class MatTooltip implements OnDestroy {
184186

185187
this._manualListeners
186188
.forEach((listener, event) => _elementRef.nativeElement.addEventListener(event, listener));
189+
} else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
190+
// When we bind a gesture event on an element (in this case `longpress`), HammerJS
191+
// will add some inline styles by default, including `user-select: none`. This is
192+
// problematic on iOS, because it will prevent users from typing in inputs. If
193+
// we're on iOS and the tooltip is attached on an input or textarea, we clear
194+
// the `user-select` to avoid these issues.
195+
element.style.webkitUserSelect = element.style.userSelect = '';
187196
}
188197

189-
_focusMonitor.monitor(_elementRef.nativeElement, false).subscribe(origin => {
198+
_focusMonitor.monitor(element, false).subscribe(origin => {
190199
// Note that the focus monitor runs outside the Angular zone.
191200
if (!origin) {
192201
_ngZone.run(() => this.hide(0));

0 commit comments

Comments
 (0)