Skip to content

Commit 0b0a955

Browse files
committed
feat(tooltip): add pf-v6-tooltip element
Port tooltip to v6 design tokens and patterns. - FloatingDOMController with arrow element positioning - Cancellable TooltipShowEvent/TooltipHideEvent with reason enum - `trigger` attribute (IDREF) and property (Element ref) - `entry-delay`/`exit-delay` attributes (default 300ms) - `alignment` attribute (start/end/left/right) - `position`, `no-flip`, `flip-behavior` carried from v5 - `light-dark()` CSS fallbacks for inverse color scheme - `ariaDescribedByElements` wiring on show/hide - Escape key dismissal - 9 demos including playground, color-scheme, and element-ref trigger - 17 unit tests covering API, a11y, events, and cancellation Closes #3048 Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f88f79e commit 0b0a955

12 files changed

Lines changed: 1026 additions & 0 deletions
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
description: Tooltip inverts to contrast with the page color scheme.
3+
---
4+
<section class="light">
5+
<h3>Light mode</h3>
6+
<pf-v6-tooltip content="Dark tooltip on light background">
7+
<pf-v5-button>Light page trigger</pf-v5-button>
8+
</pf-v6-tooltip>
9+
</section>
10+
11+
<section class="dark">
12+
<h3>Dark mode</h3>
13+
<pf-v6-tooltip content="Light tooltip on dark background">
14+
<pf-v5-button>Dark page trigger</pf-v5-button>
15+
</pf-v6-tooltip>
16+
</section>
17+
18+
<script type="module">
19+
import '@patternfly/elements/pf-v5-button/pf-v5-button.js';
20+
import '@patternfly/elements/pf-v6-tooltip/pf-v6-tooltip.js';
21+
</script>
22+
23+
<style>
24+
section {
25+
padding: 3em;
26+
text-align: center;
27+
}
28+
29+
.light {
30+
color-scheme: light;
31+
background-color: #fff;
32+
color: #1f1f1f;
33+
}
34+
35+
.dark {
36+
color-scheme: dark;
37+
background-color: #1b1d21;
38+
color: #f2f2f2;
39+
}
40+
41+
h3 {
42+
margin-block-start: 0;
43+
}
44+
</style>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
description: Tooltip content that updates dynamically.
3+
---
4+
<section>
5+
<pf-v6-tooltip content="Copy to clipboard">
6+
<button id="copy-btn" aria-label="Copy">
7+
<svg viewBox="0 0 448 512" width="14" height="14" fill="currentColor" aria-hidden="true">
8+
<path d="M384 336H192c-8.8 0-16-7.2-16-16V64c0-8.8 7.2-16 16-16l140.1 0L400 115.9V320c0 8.8-7.2 16-16 16zM192 384h192c35.3 0 64-28.7 64-64V115.9c0-12.7-5.1-24.9-14.1-33.9L366 14.1c-9-9-21.2-14.1-33.9-14.1H192c-35.3 0-64 28.7-64 64v256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64v256c0 35.3 28.7 64 64 64h192c35.3 0 64-28.7 64-64v-32h-48v32c0 8.8-7.2 16-16 16H64c-8.8 0-16-7.2-16-16V192c0-8.8 7.2-16 16-16h32v-48H64z"/>
9+
</svg>
10+
</button>
11+
</pf-v6-tooltip>
12+
</section>
13+
14+
<script type="module">
15+
import '@patternfly/elements/pf-v6-tooltip/pf-v6-tooltip.js';
16+
17+
const tooltip = document.querySelector('pf-v6-tooltip');
18+
const btn = document.getElementById('copy-btn');
19+
btn.addEventListener('click', function() {
20+
tooltip.content = 'Successfully copied to clipboard!';
21+
setTimeout(function() {
22+
tooltip.content = 'Copy to clipboard';
23+
}, 2000);
24+
});
25+
</script>
26+
27+
<style>
28+
section {
29+
padding: 6em;
30+
text-align: center;
31+
}
32+
33+
button {
34+
border: none;
35+
background: none;
36+
cursor: pointer;
37+
padding: 0.5em;
38+
}
39+
</style>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
description: A tooltip wrapping a button, shown on hover or focus.
3+
---
4+
<section>
5+
<pf-v6-tooltip content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.">
6+
<pf-v5-button>I have a tooltip!</pf-v5-button>
7+
</pf-v6-tooltip>
8+
</section>
9+
10+
<script type="module">
11+
import '@patternfly/elements/pf-v5-button/pf-v5-button.js';
12+
import '@patternfly/elements/pf-v6-tooltip/pf-v6-tooltip.js';
13+
</script>
14+
15+
<style>
16+
section {
17+
padding: 6em;
18+
text-align: center;
19+
}
20+
</style>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
description: Tooltip text can be left-aligned instead of centered.
3+
---
4+
<section>
5+
<pf-v6-tooltip alignment="start"
6+
content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.">
7+
<pf-v5-button>Left-aligned tooltip</pf-v5-button>
8+
</pf-v6-tooltip>
9+
</section>
10+
11+
<script type="module">
12+
import '@patternfly/elements/pf-v5-button/pf-v5-button.js';
13+
import '@patternfly/elements/pf-v6-tooltip/pf-v6-tooltip.js';
14+
</script>
15+
16+
<style>
17+
section {
18+
padding: 6em;
19+
text-align: center;
20+
}
21+
</style>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---
2+
description: Interactive playground for tooltip options.
3+
---
4+
<section>
5+
<fieldset>
6+
<legend>Position</legend>
7+
<select id="position">
8+
<option value="top" selected>top</option>
9+
<option value="top-start">top-start</option>
10+
<option value="top-end">top-end</option>
11+
<option value="bottom">bottom</option>
12+
<option value="bottom-start">bottom-start</option>
13+
<option value="bottom-end">bottom-end</option>
14+
<option value="left">left</option>
15+
<option value="left-start">left-start</option>
16+
<option value="left-end">left-end</option>
17+
<option value="right">right</option>
18+
<option value="right-start">right-start</option>
19+
<option value="right-end">right-end</option>
20+
</select>
21+
</fieldset>
22+
23+
<fieldset>
24+
<legend>Alignment</legend>
25+
<select id="alignment">
26+
<option value="" selected>(default: center)</option>
27+
<option value="start">start</option>
28+
<option value="end">end</option>
29+
</select>
30+
</fieldset>
31+
32+
<fieldset>
33+
<legend>Delays</legend>
34+
<label>Entry delay (ms): <input id="entry-delay" type="number" value="300" min="0" step="50"></label>
35+
<label>Exit delay (ms): <input id="exit-delay" type="number" value="300" min="0" step="50"></label>
36+
</fieldset>
37+
38+
<fieldset>
39+
<legend>Flip</legend>
40+
<label><input id="no-flip" type="checkbox"> Disable flip</label>
41+
</fieldset>
42+
</section>
43+
44+
<section class="demo-area">
45+
<pf-v6-tooltip id="demo-tooltip"
46+
content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.">
47+
<pf-v5-button>Tooltip</pf-v5-button>
48+
</pf-v6-tooltip>
49+
</section>
50+
51+
<script type="module">
52+
import '@patternfly/elements/pf-v5-button/pf-v5-button.js';
53+
import '@patternfly/elements/pf-v6-tooltip/pf-v6-tooltip.js';
54+
55+
const tooltip = document.getElementById('demo-tooltip');
56+
57+
document.getElementById('position').addEventListener('change', function(e) {
58+
tooltip.position = e.target.value;
59+
});
60+
61+
document.getElementById('alignment').addEventListener('change', function(e) {
62+
tooltip.alignment = e.target.value || undefined;
63+
});
64+
65+
document.getElementById('entry-delay').addEventListener('input', function(e) {
66+
tooltip.entryDelay = Number(e.target.value);
67+
});
68+
69+
document.getElementById('exit-delay').addEventListener('input', function(e) {
70+
tooltip.exitDelay = Number(e.target.value);
71+
});
72+
73+
document.getElementById('no-flip').addEventListener('change', function(e) {
74+
tooltip.noFlip = e.target.checked;
75+
});
76+
</script>
77+
78+
<style>
79+
section {
80+
padding: 1em 2em;
81+
}
82+
83+
.demo-area {
84+
padding: 8em 2em;
85+
text-align: center;
86+
}
87+
88+
fieldset {
89+
margin-block-end: 0.5em;
90+
border: 1px solid #ccc;
91+
border-radius: 4px;
92+
}
93+
94+
label {
95+
margin-inline-end: 1em;
96+
}
97+
98+
input[type="number"] {
99+
width: 5em;
100+
}
101+
</style>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
description: Tooltips can be positioned on any side of the trigger element.
3+
---
4+
<section>
5+
<div class="grid">
6+
<pf-v6-tooltip position="top" content="Top">
7+
<pf-v5-button>Top</pf-v5-button>
8+
</pf-v6-tooltip>
9+
<pf-v6-tooltip position="top-start" content="Top Start">
10+
<pf-v5-button>Top Start</pf-v5-button>
11+
</pf-v6-tooltip>
12+
<pf-v6-tooltip position="top-end" content="Top End">
13+
<pf-v5-button>Top End</pf-v5-button>
14+
</pf-v6-tooltip>
15+
<pf-v6-tooltip position="bottom" content="Bottom">
16+
<pf-v5-button>Bottom</pf-v5-button>
17+
</pf-v6-tooltip>
18+
<pf-v6-tooltip position="bottom-start" content="Bottom Start">
19+
<pf-v5-button>Bottom Start</pf-v5-button>
20+
</pf-v6-tooltip>
21+
<pf-v6-tooltip position="bottom-end" content="Bottom End">
22+
<pf-v5-button>Bottom End</pf-v5-button>
23+
</pf-v6-tooltip>
24+
<pf-v6-tooltip position="left" content="Left">
25+
<pf-v5-button>Left</pf-v5-button>
26+
</pf-v6-tooltip>
27+
<pf-v6-tooltip position="left-start" content="Left Start">
28+
<pf-v5-button>Left Start</pf-v5-button>
29+
</pf-v6-tooltip>
30+
<pf-v6-tooltip position="left-end" content="Left End">
31+
<pf-v5-button>Left End</pf-v5-button>
32+
</pf-v6-tooltip>
33+
<pf-v6-tooltip position="right" content="Right">
34+
<pf-v5-button>Right</pf-v5-button>
35+
</pf-v6-tooltip>
36+
<pf-v6-tooltip position="right-start" content="Right Start">
37+
<pf-v5-button>Right Start</pf-v5-button>
38+
</pf-v6-tooltip>
39+
<pf-v6-tooltip position="right-end" content="Right End">
40+
<pf-v5-button>Right End</pf-v5-button>
41+
</pf-v6-tooltip>
42+
</div>
43+
</section>
44+
45+
<script type="module">
46+
import '@patternfly/elements/pf-v5-button/pf-v5-button.js';
47+
import '@patternfly/elements/pf-v6-tooltip/pf-v6-tooltip.js';
48+
</script>
49+
50+
<style>
51+
section {
52+
padding: 6em;
53+
}
54+
55+
.grid {
56+
display: grid;
57+
grid-template-columns: repeat(3, auto);
58+
gap: 1em;
59+
justify-content: center;
60+
}
61+
</style>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
description: Tooltip content can include formatted HTML via the content slot.
3+
---
4+
<section>
5+
<p>A tooltip may contain
6+
<pf-v6-tooltip>
7+
<samp tabindex="0">HTML content</samp>
8+
<span slot="content">
9+
Slotted content can be <mark>formatted</mark>, using HTML
10+
tags like <em>em</em>, <strong>strong</strong>, or <code>code</code>.
11+
</span>
12+
</pf-v6-tooltip> by using the <code>content</code> slot.
13+
</p>
14+
</section>
15+
16+
<script type="module">
17+
import '@patternfly/elements/pf-v6-tooltip/pf-v6-tooltip.js';
18+
</script>
19+
20+
<style>
21+
section {
22+
padding: 6em;
23+
}
24+
25+
samp {
26+
font-weight: bold;
27+
}
28+
</style>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
description: Setting the trigger property to an Element reference directly.
3+
---
4+
<section>
5+
<pf-v5-button id="ref-button">Tooltip via element reference</pf-v5-button>
6+
<pf-v6-tooltip id="ref-tooltip"
7+
content="This tooltip's trigger was set via the trigger property with an Element reference.">
8+
</pf-v6-tooltip>
9+
</section>
10+
11+
<script type="module">
12+
import '@patternfly/elements/pf-v5-button/pf-v5-button.js';
13+
import '@patternfly/elements/pf-v6-tooltip/pf-v6-tooltip.js';
14+
15+
const tooltip = document.getElementById('ref-tooltip');
16+
const button = document.getElementById('ref-button');
17+
tooltip.trigger = button;
18+
</script>
19+
20+
<style>
21+
section {
22+
padding: 6em;
23+
text-align: center;
24+
}
25+
</style>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
description: A tooltip referencing an external element as its trigger.
3+
---
4+
<section>
5+
<pf-v5-button id="my-button">Tooltip attached via trigger ref</pf-v5-button>
6+
<pf-v6-tooltip trigger="my-button"
7+
content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.">
8+
</pf-v6-tooltip>
9+
</section>
10+
11+
<script type="module">
12+
import '@patternfly/elements/pf-v5-button/pf-v5-button.js';
13+
import '@patternfly/elements/pf-v6-tooltip/pf-v6-tooltip.js';
14+
</script>
15+
16+
<style>
17+
section {
18+
padding: 6em;
19+
text-align: center;
20+
}
21+
</style>

0 commit comments

Comments
 (0)