feat(tooltip): add invoker relation for accessibility
This commit is contained in:
parent
dfe1905e7c
commit
3f84a3bab8
3 changed files with 61 additions and 2 deletions
|
|
@ -80,6 +80,24 @@ import '@lion/tooltip/lion-tooltip.js';
|
|||
|
||||
## Examples
|
||||
|
||||
### invokerRelation
|
||||
|
||||
There is a difference between tooltips used as a primary label or as a description. In most cases a button will already have its own label, so the tooltip will be used as a description with extra information, which is already set as default. Only in case of icon buttons you want to use the tooltip as the primary label. To do so you need to set the `invokerRelation` to `label`.
|
||||
|
||||
> For detailed information please read: [inclusive tooltips](https://inclusive-components.design/tooltips-toggletips/#inclusivetooltips).
|
||||
|
||||
```js preview-story
|
||||
export const invokerRelation = () => html`
|
||||
<style>
|
||||
${tooltipDemoStyles}
|
||||
</style>
|
||||
<lion-tooltip .config=${{ invokerRelation: 'label' }}>
|
||||
<button slot="invoker" class="demo-tooltip-invoker">📅</button>
|
||||
<div slot="content" class="demo-tooltip-content">Agenda<div>
|
||||
</lion-tooltip>
|
||||
`;
|
||||
```
|
||||
|
||||
### Placements
|
||||
|
||||
You can easily change the placement of the content node relative to the invoker.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ export class LionTooltip extends OverlayMixin(LitElement) {
|
|||
reflect: true,
|
||||
attribute: 'has-arrow',
|
||||
},
|
||||
invokerRelation: {
|
||||
type: String,
|
||||
attribute: 'invoker-relation',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -70,6 +74,17 @@ export class LionTooltip extends OverlayMixin(LitElement) {
|
|||
|
||||
constructor() {
|
||||
super();
|
||||
/**
|
||||
* Whether an arrow should be displayed
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hasArrow = false;
|
||||
/**
|
||||
* Decides whether the tooltip invoker text should be considered a description
|
||||
* (sets aria-describedby) or a label (sets aria-labelledby).
|
||||
* @type {'label'\'description'}
|
||||
*/
|
||||
this.invokerRelation = 'description';
|
||||
this._mouseActive = false;
|
||||
this._keyActive = false;
|
||||
this.__setupRepositionCompletePromise();
|
||||
|
|
@ -79,7 +94,6 @@ export class LionTooltip extends OverlayMixin(LitElement) {
|
|||
if (super.connectedCallback) {
|
||||
super.connectedCallback();
|
||||
}
|
||||
this._overlayContentNode.setAttribute('role', 'tooltip');
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
@ -128,8 +142,9 @@ export class LionTooltip extends OverlayMixin(LitElement) {
|
|||
this.__syncFromPopperState(data);
|
||||
},
|
||||
},
|
||||
isTooltip: true,
|
||||
handlesAccessibility: true,
|
||||
isTooltip: true,
|
||||
invokerRelation: this.invokerRelation,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -206,6 +206,32 @@ describe('lion-tooltip', () => {
|
|||
expect(content.getAttribute('role')).to.be.equal('tooltip');
|
||||
});
|
||||
|
||||
it('should have aria-describedby role set on the invoker', async () => {
|
||||
const el = await fixture(html`
|
||||
<lion-tooltip>
|
||||
<div slot="content">Hey there</div>
|
||||
<button slot="invoker">Tooltip button</button>
|
||||
</lion-tooltip>
|
||||
`);
|
||||
const content = el.querySelector('[slot=content]');
|
||||
const invoker = el.querySelector('[slot=invoker]');
|
||||
expect(invoker.getAttribute('aria-describedby')).to.be.equal(content.id);
|
||||
expect(invoker.getAttribute('aria-labelledby')).to.be.equal(null);
|
||||
});
|
||||
|
||||
it('should have aria-labelledby role set on the invoker when [ invoker-relation="label"]', async () => {
|
||||
const el = await fixture(html`
|
||||
<lion-tooltip invoker-relation="label">
|
||||
<div slot="content">Hey there</div>
|
||||
<button slot="invoker">Tooltip button</button>
|
||||
</lion-tooltip>
|
||||
`);
|
||||
const content = el.querySelector('[slot=content]');
|
||||
const invoker = el.querySelector('[slot=invoker]');
|
||||
expect(invoker.getAttribute('aria-describedby')).to.be.equal(null);
|
||||
expect(invoker.getAttribute('aria-labelledby')).to.be.equal(content.id);
|
||||
});
|
||||
|
||||
it('should be accessible when closed', async () => {
|
||||
const el = await fixture(html`
|
||||
<lion-tooltip>
|
||||
|
|
|
|||
Loading…
Reference in a new issue