diff --git a/stencil-workspace/src/components/modus-tooltip/modus-tooltip.e2e.ts b/stencil-workspace/src/components/modus-tooltip/modus-tooltip.e2e.ts
index 8fc3fb40a..464ce2d66 100644
--- a/stencil-workspace/src/components/modus-tooltip/modus-tooltip.e2e.ts
+++ b/stencil-workspace/src/components/modus-tooltip/modus-tooltip.e2e.ts
@@ -79,6 +79,83 @@ describe('modus-tooltip', () => {
expect(tooltip.getAttribute('data-show')).toBeNull();
});
+ it('preserves tabindex on hide', async () => {
+ const page = await newE2EPage();
+
+ await page.setContent(`
+
+ Button
+
+ Other button
+ `);
+
+ const tooltip = await page.find('modus-tooltip');
+ const button = await tooltip.find('#tooltip-button');
+ await page.hover('#tooltip-button');
+ await page.waitForChanges();
+ expect(button.getAttribute('tabindex')).toEqual('3');
+
+ await page.hover('#not-tooltip-button');
+ await page.waitForChanges();
+ expect(button.getAttribute('tabindex')).toEqual('3');
+ });
+
+ it('preserves lack of tabindex on hide', async () => {
+ const page = await newE2EPage();
+
+ await page.setContent(`
+
+ Button
+
+ Other button
+ `);
+
+ const tooltip = await page.find('modus-tooltip');
+ const button = await tooltip.find('#tooltip-button');
+ await page.hover('#tooltip-button');
+ await page.waitForChanges();
+ expect(button.getAttribute('tabindex')).toEqual('-1');
+
+ await page.hover('#not-tooltip-button');
+ await page.waitForChanges();
+ expect(button.getAttribute('tabindex')).toBeNull();
+ });
+
+ it('focuses the tooltipped element on show', async () => {
+ const page = await newE2EPage();
+
+ await page.setContent(`
+
+ Button
+
+ `);
+
+ await page.hover('#tooltip-button');
+ await page.waitForChanges();
+ const activeElementId = await page.evaluate(() => document.activeElement!.id);
+ expect(activeElementId).toEqual('tooltip-button');
+ });
+
+ it('hides the tooltip on "escape" key', async () => {
+ const page = await newE2EPage();
+
+ await page.setContent(`
+
+ Button
+
+ `);
+
+ const tooltip = await page.find('modus-tooltip >>> .tooltip');
+ await page.hover('#tooltip-button');
+
+ await page.waitForChanges();
+ expect(tooltip).toHaveAttribute('data-show');
+
+ page.keyboard.press('Escape');
+ await page.waitForChanges();
+ expect(tooltip).not.toHaveAttribute('data-show');
+ });
+
it('renders aria-label on div when set', async () => {
const page = await newE2EPage();
diff --git a/stencil-workspace/src/components/modus-tooltip/modus-tooltip.tsx b/stencil-workspace/src/components/modus-tooltip/modus-tooltip.tsx
index e826c958c..e742ba9ce 100644
--- a/stencil-workspace/src/components/modus-tooltip/modus-tooltip.tsx
+++ b/stencil-workspace/src/components/modus-tooltip/modus-tooltip.tsx
@@ -1,5 +1,5 @@
// eslint-disable-next-line
-import { Component, Element, Fragment, h, Prop, Watch } from '@stencil/core';
+import { Component, Element, h, Prop, Watch, Fragment } from '@stencil/core';
import { createPopper, Instance } from '@popperjs/core';
import { ModusToolTipPlacement } from './modus-tooltip.models';
@@ -47,6 +47,7 @@ export class ModusTooltip {
}
private popperInstance: Instance;
+ private targetTabIndex?: string; // necessary for preserving tab index after blur
private tooltipElement: HTMLDivElement;
private readonly showEvents = ['mouseenter', 'mouseover', 'focus'];
private readonly hideEvents = ['mouseleave', 'blur', 'click'];
@@ -72,6 +73,8 @@ export class ModusTooltip {
const target = this.element.firstElementChild;
if (!target || !this.tooltipElement) return;
+ this.targetTabIndex = target.getAttribute('tabindex');
+
this.popperInstance = createPopper(target, this.tooltipElement, {
placement: position,
modifiers: [
@@ -91,6 +94,8 @@ export class ModusTooltip {
this.hideEvents.forEach((event) => {
target.addEventListener(event, this.hideEventsListener);
});
+
+ target.addEventListener('keydown', this.escapeKeyHandler);
}
cleanupPopper(): void {
@@ -109,7 +114,17 @@ export class ModusTooltip {
this.popperInstance = null;
}
+ escapeKeyHandler = (event: KeyboardEvent) => {
+ if (event.code === 'Escape') {
+ this.hide();
+ }
+ };
+
show(): void {
+ const target = this.element.firstElementChild as HTMLElement;
+ const tabIndex = this.targetTabIndex !== '' && this.targetTabIndex != null ? (this.targetTabIndex as string) : '-1';
+ target.setAttribute('tabindex', tabIndex);
+ target.focus();
if (this.popperInstance) {
// Make the tooltip visible
this.tooltipElement.setAttribute('data-show', '');
@@ -135,6 +150,15 @@ export class ModusTooltip {
...options,
modifiers: [...options.modifiers, { name: 'eventListeners', enabled: false }],
}));
+
+ const target = this.element.firstElementChild as HTMLElement;
+
+ if (this.targetTabIndex == null) {
+ target.removeAttribute('tabindex');
+ } else {
+ target.setAttribute('tabindex', this.targetTabIndex);
+ }
+ target.blur();
}
}