Skip to content

Commit

Permalink
Merge branch 'main' into feat/dialog/use-native-dialog-element-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
adamjohnson authored Jan 6, 2025
2 parents 1d3abdc + 8dd9a5f commit 541b0ed
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 36 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
68 changes: 47 additions & 21 deletions elements/rh-code-block/docs/20-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,24 +57,50 @@ Container spacing and code text size reduces as breakpoints get smaller.

## Best practices

### Different font

Do not use a different font than `--rh-font-family-code`.

<uxdot-example width-adjustment="872px" danger>
<img src="../code-block-best-practice-1.png"
alt="Image of a code block showing the Red Hat Text font used for code text which is incorrect usage"
width="872"
height="285">
</uxdot-example>

### Different styling

Do not change any of the code block styling.

<uxdot-example width-adjustment="872px" danger>
<img src="../code-block-best-practice-2.png"
alt="Image of a code block showing different styles which is incorrect usage"
width="872"
height="285">
</uxdot-example>
### Font family

<uxdot-best-practice variant="do">
<uxdot-example slot="image" width-adjustment="768px">
<img src="../code-block-best-practices-font-family-do.svg"
alt="Code block text using Red Hat Mono"
width="768"
height="192">
</uxdot-example>

<p>Use <code>--rh-font-family-code</code>.</p>
</uxdot-best-practice>

<uxdot-best-practice variant="dont">
<uxdot-example slot="image" width-adjustment="768px">
<img src="../code-block-best-practices-font-family-dont.svg"
alt="Code block text using Red Hat Text"
width="768"
height="192">
</uxdot-example>

<p>Do not use a different font family token than <code>--rh-font-family-code</code>.</p>
</uxdot-best-practice>

### Customizing

<uxdot-best-practice variant="do">
<uxdot-example slot="image" width-adjustment="768px">
<img src="../code-block-best-practices-customizing-do.svg"
alt="Code block using default styling"
width="768"
height="192">
</uxdot-example>

<p>Use the available options for customizing code block. (Adjusting syntax highlighting is ok.)</p>
</uxdot-best-practice>

<uxdot-best-practice variant="dont">
<uxdot-example slot="image" width-adjustment="768px">
<img src="../code-block-best-practices-customizing-dont.svg"
alt="Code block with white background and black border"
width="768"
height="192">
</uxdot-example>

<p>Do not change the code block styling, especially if it will look like other text containers on the same page.</p>
</uxdot-best-practice>
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 541b0ed

Please sign in to comment.