Skip to content

Commit

Permalink
Merge branch 'main' into chore/tokens-2-1-1
Browse files Browse the repository at this point in the history
  • Loading branch information
bennypowers authored Jan 8, 2025
2 parents e576af5 + 8dd9a5f commit f537380
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/brown-fans-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rhds/elements": patch
---

`<rh-tooltip>`: make tooltip content available to assistive technology
9 changes: 9 additions & 0 deletions elements/rh-tooltip/demo/content-attributes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<rh-tooltip content="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Mi eget mauris pharetra et ultrices.">
<rh-button>Tooltip</rh-button>
</rh-tooltip>

<script type="module">
import '@rhds/elements/rh-button/rh-button.js';
import '@rhds/elements/rh-tooltip/rh-tooltip.js';
</script>
1 change: 0 additions & 1 deletion elements/rh-tooltip/demo/rh-tooltip.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@
import '@rhds/elements/rh-button/rh-button.js';
import '@rhds/elements/rh-tooltip/rh-tooltip.js';
</script>

4 changes: 0 additions & 4 deletions elements/rh-tooltip/rh-tooltip.css
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,6 @@
var(--rh-tooltip__content--BackgroundColor, var(--rh-color-surface-darkest, #151515)));
}

.c {
display: contents;
}

.open #tooltip {
opacity: 1;
}
Expand Down
67 changes: 61 additions & 6 deletions elements/rh-tooltip/rh-tooltip.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { html, LitElement } from 'lit';
import { html, LitElement, isServer } from 'lit';
import { customElement } from 'lit/decorators/custom-element.js';
import { property } from 'lit/decorators/property.js';
import { classMap } from 'lit/directives/class-map.js';
Expand Down Expand Up @@ -43,6 +43,41 @@ export class RhTooltip extends LitElement {

static readonly styles = [styles];

private static instances = new Set<RhTooltip>();

static {
if (!isServer) {
globalThis.addEventListener('keydown', (event: KeyboardEvent) => {
const { instances } = RhTooltip;
for (const instance of instances) {
instance.#onKeydown(event);
}
});
RhTooltip.initAnnouncer();
}
}

private static announcer: HTMLElement;

private static announce(message: string) {
this.announcer.innerText = message;
}

private static initAnnouncer() {
document.body.append((this.announcer = Object.assign(document.createElement('div'), {
role: 'status',
// apply `.visually-hidden` styles
style: /* css */`
position: fixed;
inset-block-start: 0;
inset-inline-start: 0;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
border: 0;`,
})));
}

/** The position of the tooltip, relative to the invoking content */
@property() position: Placement = 'top';

Expand All @@ -57,10 +92,22 @@ export class RhTooltip extends LitElement {

#initialized = false;

get #content() {
if (!this.#float.open || isServer) {
return '';
} else {
return this.content || (this.shadowRoot
?.getElementById('content') as HTMLSlotElement)
?.assignedNodes().map(x => x.textContent ?? '')
?.join(' ');
}
}

override connectedCallback(): void {
super.connectedCallback();
ENTER_EVENTS.forEach(evt => this.addEventListener(evt, this.show));
EXIT_EVENTS.forEach(evt => this.addEventListener(evt, this.hide));
RhTooltip.instances.add(this);
}

override render() {
Expand All @@ -71,15 +118,15 @@ export class RhTooltip extends LitElement {
<div id="container"
style="${styleMap(styles)}"
class="${classMap({ open,
'initialized': !!this.#initialized,
initialized: !!this.#initialized,
[on]: !!on,
[anchor]: !!anchor,
[alignment]: !!alignment })}">
<div class="c" role="tooltip" aria-labelledby="tooltip">
<slot id="invoker"></slot>
<div id="invoker">
<slot id="invoker-slot"></slot>
</div>
<div class="c" aria-hidden="${String(!open) as 'true' | 'false'}">
<slot id="tooltip" name="content">${this.content}</slot>
<div id="tooltip" role="status">
<slot id="content" name="content">${this.content}</slot>
</div>
</div>
`;
Expand All @@ -94,12 +141,20 @@ export class RhTooltip extends LitElement {
: { mainAxis: 15, alignmentAxis: -4 };
await this.#float.show({ offset, placement });
this.#initialized ||= true;
RhTooltip.announce(this.#content);
}

/** Hide the tooltip */
async hide() {
await this.#float.hide();
RhTooltip.announcer.innerText = '';
}

#onKeydown = (event: KeyboardEvent): void => {
if (event.key === 'Escape') {
this.hide();
}
};
}

declare global {
Expand Down
6 changes: 2 additions & 4 deletions elements/rh-tooltip/test/rh-tooltip.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,8 @@ describe('<rh-tooltip>', function() {
beforeEach(() => sendMouseToTooltip(element));
it('content should be available to assistive technology', async function() {
await sendMouseToTooltip(element);
const snapshot = await a11ySnapshot();
expect(snapshot.children?.length).to.equal(1);
expect(snapshot.children?.at(0)?.role).to.equal('text');
expect(snapshot.children?.at(0)?.name).to.equal(content);
expect(await a11ySnapshot())
.to.have.axQuery({ role: 'text', name: content });
});
});
});
Expand Down

0 comments on commit f537380

Please sign in to comment.