Skip to content

Commit

Permalink
fix(core/tooltip): remove direct constructor access (#1118)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielleroux authored Feb 23, 2024
1 parent cd3d033 commit 63dd48c
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 1,025 deletions.
8 changes: 4 additions & 4 deletions packages/angular-test-app/src/preview-examples/tooltip.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div style="padding: 4rem">
<ix-button class="any-class" style="margin-right: 4rem">Hover me</ix-button>
<ix-tooltip for=".any-class">Simple selector</ix-tooltip>
<ix-button class="any-class" aria-describedby="tooltip-1">Hover me</ix-button>
<ix-tooltip id="tooltip-1" for=".any-class">Simple selector</ix-tooltip>

<ix-button my-custom-special-selector="any-value">Also hover me</ix-button>
<ix-tooltip for="[my-custom-special-selector='any-value']">
<ix-button my-custom-special-selector="any-value" aria-describedby="tooltip-2">Also hover me</ix-button>
<ix-tooltip id="tooltip-2" for="[my-custom-special-selector='any-value']">
Custom selector
</ix-tooltip>
</div>
2 changes: 1 addition & 1 deletion packages/core/component-doc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"timestamp": "",
"compiler": {
"name": "@stencil/core",
"version": "4.12.0",
"version": "4.12.3",
"typescriptVersion": "5.3.3"
},
"components": [
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"dependencies": {
"@floating-ui/dom": "^1.5.1",
"@stencil/core": "^4.12.0",
"@stencil/core": "^4.12.3",
"@types/luxon": "^3.3.7",
"animejs": "~3.2.1",
"hyperlist": "^1.0.0",
Expand Down
23 changes: 0 additions & 23 deletions packages/core/src/components/tooltip/test/tooltip.ct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,6 @@ test('renders', async ({ mount, page }) => {
});

test.describe('a11y', () => {
test('append to aria-describedby', async ({ mount, page }) => {
await mount(`
<ix-tooltip for=".test">tooltip</ix-tooltip>
<ix-button class="test" aria-describedby="info">button</ix-button>
<div id="info">Info</div>
`);
const button = page.locator('ix-button');
await expect(button).toHaveAttribute(
'aria-describedby',
'info ix-tooltip-1'
);
});

test('handle custom ID in aria-describedby', async ({ mount, page }) => {
await mount(`
<ix-tooltip id="custom-id" for=".test">tooltip</ix-tooltip>
<ix-button class="test" aria-describedby="info">button</ix-button>
<div id="info">Info</div>
`);
const button = page.locator('ix-button');
await expect(button).toHaveAttribute('aria-describedby', 'info custom-id');
});

test('closes on ESC', async ({ mount, page }) => {
await mount(`
<ix-tooltip for=".test">tooltip</ix-tooltip>
Expand Down
42 changes: 18 additions & 24 deletions packages/core/src/components/tooltip/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ type ArrowPosition = {

const numberToPixel = (value: number) => (value != null ? `${value}px` : '');

let sequentialInstanceId = 0;

/**
* @slot title-icon - Icon of tooltip title
* @slot title-content - Content of tooltip title
Expand Down Expand Up @@ -78,14 +76,15 @@ export class Tooltip {

@Element() hostElement: HTMLIxTooltipElement;

private id = ++sequentialInstanceId;
private observer: MutationObserver;
private hideTooltipTimeout: NodeJS.Timeout;
private onEnterElementBind = this.onTooltipShow.bind(this);
private onLeaveElementBind = this.onTooltipHide.bind(this);
private disposeAutoUpdate?: () => void;
private tooltipCloseTimeInMS = 50;

private disposeListener: Function;

private get arrowElement() {
return this.hostElement.shadowRoot.querySelector('.arrow') as HTMLElement;
}
Expand Down Expand Up @@ -221,29 +220,25 @@ export class Tooltip {
return Array.from(document.querySelectorAll(this.for));
}

private updateAriaDescribedBy(element: Element, describedBy: string) {
const oldDescribedBy = element.getAttribute('aria-describedby');
private registerTriggerListener() {
const triggerElementList = this.queryAnchorElements();

if (oldDescribedBy?.indexOf(describedBy) != -1) {
return;
if (this.disposeListener) {
this.disposeListener();
}

const newDescribedBy = `${oldDescribedBy} ${describedBy}`;
element.setAttribute('aria-describedby', newDescribedBy);
}

private getTooltipId() {
return this.hostElement.id || 'ix-tooltip-' + this.id;
}

private registerTriggerListener() {
const elements = this.queryAnchorElements();
elements.forEach((e) => {
e.addEventListener('mouseenter', this.onEnterElementBind);
e.addEventListener('mouseleave', this.onLeaveElementBind);
e.addEventListener('focusin', this.onEnterElementBind);
e.addEventListener('focusout', this.onLeaveElementBind);
this.updateAriaDescribedBy(e, this.getTooltipId());
triggerElementList.forEach((element) => {
element.addEventListener('mouseenter', this.onEnterElementBind);
element.addEventListener('mouseleave', this.onLeaveElementBind);
element.addEventListener('focusin', this.onEnterElementBind);
element.addEventListener('focusout', this.onLeaveElementBind);

this.disposeListener = () => {
element.removeEventListener('mouseenter', this.onEnterElementBind);
element.removeEventListener('mouseleave', this.onLeaveElementBind);
element.removeEventListener('focusin', this.onEnterElementBind);
element.removeEventListener('focusout', this.onLeaveElementBind);
};
});
}

Expand Down Expand Up @@ -300,7 +295,6 @@ export class Tooltip {
class={{
visible: this.visible,
}}
id={this.getTooltipId()}
role="tooltip"
>
<div class={'tooltip-title'}>
Expand Down
19 changes: 10 additions & 9 deletions packages/documentation/docs/controls/tooltip.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,7 @@ import Playground from '@site/src/components/Playground'
<Playground
name="tooltip"
height="16rem"
frameworks={{
react: SourceReact,
angular: {
"tooltip.html": SourceAngularHtml,
"tooltip.ts": SourceAngularTs
},
javascript: SourceJavascript,
vue: SourceVue
}}>
examplesByName>
</Playground>

## Properties
Expand All @@ -42,3 +34,12 @@ frameworks={{
### Slots

<Slots />

## A11y

Set the `aria-describedby` attribute on the trigger element to the tooltip `id` attribute. This allows assistive technologies to establish a logical connection between the trigger and the tooltip.

See examples [above](#usage).

[More information](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/)

14 changes: 9 additions & 5 deletions packages/html-test-app/src/preview-examples/tooltip.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,23 @@
<body class="theme-brand-dark">
<!-- Preview code -->
<div style="padding: 4rem">
<ix-button class="any-class" style="margin-right: 4rem"
>Hover me</ix-button
<ix-button class="any-class" aria-describedby="tooltip-1">Hover me</ix-button
>
<ix-tooltip for=".any-class">Simple selector</ix-tooltip>
<ix-tooltip id="tooltip-1" for=".any-class">Simple selector</ix-tooltip>

<ix-button my-custom-special-selector="any-value"
<ix-button my-custom-special-selector="any-value" aria-describedby="tooltip-2"
>Also hover me</ix-button
>
<ix-tooltip for="[my-custom-special-selector='any-value']">
<ix-tooltip id="tooltip-2" for="[my-custom-special-selector='any-value']">
Custom selector
</ix-tooltip>
</div>
<!-- Preview code -->
<style>
ix-button:first-child {
margin-right: 4rem;
}
</style>
<script type="module" src="./init.js"></script>
</body>
</html>
15 changes: 11 additions & 4 deletions packages/react-test-app/src/preview-examples/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,20 @@ import React from 'react';
export default () => {
return (
<div style={{ padding: '4rem' }}>
<IxButton class="any-class" style={{ 'margin-right': '4rem' }}>
<IxButton class="any-class" aria-describedby="tooltip-1">
Hover me
</IxButton>
<IxTooltip for=".any-class">Simple selector</IxTooltip>
<IxTooltip id="tooltip-1" for=".any-class">
Simple selector
</IxTooltip>

<IxButton my-custom-special-selector="any-value">Also hover me</IxButton>
<IxTooltip for="[my-custom-special-selector='any-value']">
<IxButton
my-custom-special-selector="any-value"
aria-describedby="tooltip-2"
>
Also hover me
</IxButton>
<IxTooltip id="tooltip-2" for="[my-custom-special-selector='any-value']">
Custom selector
</IxTooltip>
</div>
Expand Down
8 changes: 4 additions & 4 deletions packages/vue-test-app/src/preview-examples/tooltip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import { IxButton, IxTooltip } from '@siemens/ix-vue';

<template>
<div :style="{ padding: '4rem' }">
<IxButton class="any-class" :style="{ 'margin-right': '4rem' }">
<IxButton class="any-class" aria-describedby="tooltip-1">
Hover me
</IxButton>
<IxTooltip for=".any-class">Simple selector</IxTooltip>
<IxTooltip id="tooltip-1" for=".any-class">Simple selector</IxTooltip>

<IxButton my-custom-special-selector="any-value">Also hover me</IxButton>
<IxTooltip for="[my-custom-special-selector='any-value']">
<IxButton my-custom-special-selector="any-value" aria-describedby="tooltip-2">Also hover me</IxButton>
<IxTooltip id="tooltip-2" for="[my-custom-special-selector='any-value']">
Custom selector
</IxTooltip>
</div>
Expand Down
Loading

0 comments on commit 63dd48c

Please sign in to comment.