Skip to content

Commit

Permalink
Adding updated copy to tooltip page. Also refactored the label for th…
Browse files Browse the repository at this point in the history
…e button that opens the tooltip.
  • Loading branch information
zoltan-dulac committed Oct 17, 2024
1 parent d170968 commit a7e133b
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 49 deletions.
45 changes: 27 additions & 18 deletions content/body/tooltip.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
This solution can be styled exactly as wanted and uses the maximum value of a z-index in the document.
We show different types of tooltips below, based on how they are triggered.
It will disappear when keyboard users press the Escape key.
<strong>It doesn't work in mobile,</strong> which while consistent with other tooltip solutions,
is something that we are still looking to fix. If anyone has any ideas, please feel free to <a href="https://twitter.com/zoltandulac">reach out to me on Twitter</a>.
</p>

<h3> Clickable tooltip </h3>
Expand All @@ -39,21 +37,21 @@
<legend>Vehicle Inspection Form</legend>
<div class="enable-form-example__fieldset-inner-container">
<div class="field-block">
<label for="clickable_example_1" class="form-label">
<label id="vin-label" for="vin" class="form-label">
<span>VIN</span>
</label>
<input id="clickable_example_1" size="25" type="text">
<button id="tooltip_button_1" type="button" class="tooltip__text-button" aria-label="Clickable tooltip information"
<input id="vin" size="25" type="text">
<button id="tooltip_button_1" type="button" class="tooltip__text-button" aria-describedby="vin-label"
data-tooltip="VIN (Vehicle Identification Number) is a 17 character (digits/capital letters) unique identifier for a vehicle.">
<span>What's this?</span>
<span>More info</span>
</button>
</div>
<div class="field-block">
<label for="clickable_example_2" class="form-label">
<label id="body-style-label" for="body-style" class="form-label">
<span>Body style</span>
</label>
<input id="clickable_example_2" size="25" type="text">
<button id="tooltip_button_2" type="button" class="tooltip__icon-button" aria-label="Clickable tooltip information"
<input id="body-style" size="25" type="text">
<button id="tooltip_button_2" type="button" class="tooltip__icon-button" aria-label="More Information" aria-describedby="body-style-label"
data-tooltip="Categorization of a car based on its shape, style, and space. Examples include sedan, SUV, convertible, etc.">
<span class="icon" aria-hidden="true">i</span>
</button>
Expand All @@ -69,24 +67,35 @@
<script type="application/json" id="example1-props">
{
"replaceHtmlRules": {},
"steps": [{
"label": "Create markup",
"highlight": "data-tooltip",
"steps": [
{
"label": "Create markup for the button that opens the tooltip",
"highlight": "[\\s]*data-tooltip",
"notes": "Our script uses the <code>data-tooltip</code> attribute instead of the <code>title</code> attribute, since <strong>title</strong> is rendered by user agents by default and cannot be styled."
},
{
"label": "Give button context on what it is giving information on",
"highlight": "aria-describedby",
"notes": "When screen reader users tab into this control, they will not just hear the label of the button that opens the tooptip (e.g. \"More Info\"), but also the context of what the context of the what information will be given when clicking the button via the <code>aria-describedby</code> (e.g. \"VIN\")"
},
{
"label": "Create HTML for the tooltip",
"highlight": "%OUTERHTML%tooltip ||| role=\"tooltip ||| aria-live=\"assertive\"",
"notes": "Note the role of tooltip. It is an aria-live region so that the content is announced by screen readers. The content is dynamically changed in JS when any of the buttons that open up the tooltip are pressed."
},
{
"label": "Create JavaScript events for tooltip script",
"highlight": "%JS% tooltip.create; tooltip.init",
"highlight": "%JS% tooltip.create; tooltip.init ||| (this.create|this.init)[^=]*=",
"notes": "When the page is loaded, create the tooltip DOM object and initialize the mouse and keyboard events that will display the tooltips. <strong>Note the role of tooltip being added to the tooltip DOM object</strong>."
},
{
"label": "Create the show and hide methods for the tooltip",
"highlight": "%JS% tooltip.show; tooltip.hide",
"highlight": "%JS% tooltip.show; tooltip.hide ||| (this.hide|this.show)\\s=\\s",
"notes": "We make sure the element that triggered the tooltip's <code>show</code> method will be connected to it with the aria-describedby attribute, which points to the tooltip. This ensures screen readers announce the tooltip on focus."
},
{
"label": "Ensure tooltip disappears when Escape key is pressed",
"highlight": "%JS% tooltip.onKeyup",
"highlight": "%JS% tooltip.onKeyup ||| (this.onKeyup)\\s=\\s",
"notes": "This is to ensure keyboard users can make the tooltip disappear without tabbing out of the component."
},
{
Expand All @@ -101,7 +110,7 @@
<h3> Focusable tooltip </h3>
<p> This type of tooltip can be triggered when the user either clicks on it or navigates to it by keyboard.</p>
<p>
The form example below demonstrates a tooltip that can be triggered via input field click.
The form example below demonstrates a tooltip that can be triggered via input field click.
</p>
<div id="example2" class="enable-example">
<form class="enable-form-example">
Expand Down Expand Up @@ -130,12 +139,12 @@
"replaceHtmlRules": {},
"steps": [{
"label": "Create markup",
"highlight": "data-tooltip",
"highlight": "[\\s]*data-tooltip",
"notes": "Our script uses the <code>data-tooltip</code> attribute instead of the <code>title</code> attribute, since <strong>title</strong> is rendered by user agents by default and cannot be styled."
},
{
"label": "Create JavaScript events for tooltip script",
"highlight": "%JS% tooltip.create; tooltip.init",
"highlight": "%JS% tooltip.create; tooltip.init ||| (this.create|this.init)[^=]*=",
"notes": "When the page is loaded, create the tooltip DOM object and initialize the mouse and keyboard events that will display the tooltips. <strong>Note the role of tooltip being added to the tooltip DOM object</strong>."
},
{
Expand Down
4 changes: 4 additions & 0 deletions css/tooltip.css
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,7 @@
vertical-align: top;
}
}
.tooltip__text-button,
.tooltip__icon-button {
outline-offset: 2px;
}
29 changes: 11 additions & 18 deletions js/modules/es4/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@
* Released under the MIT License.
******************************************************************************/

const tooltip = new function () {
const tooltip = new (function() {
// global constants
const { body } = document;
const tooltipEl = document.createElement('div');
const tooltipStyle = tooltipEl.style;
const escapeKey = 'Escape';
const tabKey = 'Tab';
const buttonName = 'BUTTON';
const inputName = 'INPUT';
let tooltipTarget = null;
let isTooltipVisible = false;
let tooltipBelongsTo = null;
Expand Down Expand Up @@ -67,7 +65,7 @@ const tooltip = new function () {
tooltipEl.id = 'tooltip';
tooltipEl.setAttribute('role', 'tooltip');
tooltipEl.classList.add('tooltip--hidden');
tooltipEl.innerHTML = '<div class="tooltip__content">Loading ...</div>';
tooltipEl.innerHTML = '<div class="tooltip__content">Loading</div>';
tooltipEl.setAttribute('aria-live', 'assertive');
body.appendChild(tooltipEl);
}
Expand All @@ -94,7 +92,7 @@ const tooltip = new function () {
tooltipTarget = e.target;

//Hide tooltip on initial focus if tabbed in
if (tooltipTarget.tagName === buttonName && tabbedIn) {
if (tooltipTarget.tagName === 'BUTTON' && tabbedIn) {
if (tooltipBelongsTo !== tooltipTarget){
return;
}
Expand All @@ -106,25 +104,22 @@ const tooltip = new function () {
this.show = (e) => {
tooltipTarget = e.target;

if (tooltipTarget.tagName === 'SPAN'){
tooltipTarget = e.target.parentNode;
}

const text = tooltipTarget.dataset.tooltip;
if (!text || (isTooltipVisible && tooltipBelongsTo === tooltipTarget)) {
return;
}

//Set aria attribute only for onFocus (input) elements
if (tooltipTarget.tagName === inputName){
if (tooltipTarget.tagName === 'INPUT'){
tooltipTarget.setAttribute('aria-describedby', 'tooltip');
}

const tooltipTargetRect = tooltipTarget.getBoundingClientRect();
tooltipEl.innerHTML = text;
tooltipEl.classList.remove('tooltip--hidden');

tooltipEl.innerHTML = text;
tooltipStyle.top = `calc(${tooltipTargetRect.bottom + window.scrollY}px + 1em)`
tooltipStyle.left = `${tooltipTargetRect.left + window.pageXOffset}px`;
tooltipStyle.left = `${tooltipTargetRect.left + window.scrollX}px`;
tooltipEl.classList.remove('tooltip--bottom');
tooltipEl.classList.add('tooltip--top');

Expand All @@ -151,7 +146,7 @@ const tooltip = new function () {
this.handleClick = (e) => {
tooltipTarget = e.target;

if (tooltipTarget.tagName === buttonName && tabbedIn) {
if (tooltipTarget.tagName === 'BUTTON' && tabbedIn) {
if (!isTooltipVisible) {
this.show(e);
} else {
Expand All @@ -177,7 +172,7 @@ const tooltip = new function () {
if (tooltipTarget) {
tooltipTarget.removeEventListener('mouseleave', this.hide);
tooltipEl.removeEventListener('mouseleave', this.hide);
if (tooltipTarget.tagName === inputName){
if (tooltipTarget.tagName === 'INPUT'){
tooltipTarget.removeAttribute('aria-describedby');
}
tooltipTarget = null;
Expand All @@ -192,6 +187,4 @@ const tooltip = new function () {
new CustomEvent('enable-hide', { bubbles: true })
);
}
}

export default tooltip;
})
21 changes: 8 additions & 13 deletions js/modules/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ const tooltip = new function () {
const tooltipStyle = tooltipEl.style;
const escapeKey = 'Escape';
const tabKey = 'Tab';
const buttonName = 'BUTTON';
const inputName = 'INPUT';
let tooltipTarget = null;
let isTooltipVisible = false;
let tooltipBelongsTo = null;
Expand Down Expand Up @@ -67,7 +65,7 @@ const tooltip = new function () {
tooltipEl.id = 'tooltip';
tooltipEl.setAttribute('role', 'tooltip');
tooltipEl.classList.add('tooltip--hidden');
tooltipEl.innerHTML = '<div class="tooltip__content">Loading ...</div>';
tooltipEl.innerHTML = '<div class="tooltip__content">Loading</div>';
tooltipEl.setAttribute('aria-live', 'assertive');
body.appendChild(tooltipEl);
}
Expand All @@ -94,7 +92,7 @@ const tooltip = new function () {
tooltipTarget = e.target;

//Hide tooltip on initial focus if tabbed in
if (tooltipTarget.tagName === buttonName && tabbedIn) {
if (tooltipTarget.tagName === 'BUTTON' && tabbedIn) {
if (tooltipBelongsTo !== tooltipTarget){
return;
}
Expand All @@ -106,25 +104,22 @@ const tooltip = new function () {
this.show = (e) => {
tooltipTarget = e.target;

if (tooltipTarget.tagName === 'SPAN'){
tooltipTarget = e.target.parentNode;
}

const text = tooltipTarget.dataset.tooltip;
if (!text || (isTooltipVisible && tooltipBelongsTo === tooltipTarget)) {
return;
}

//Set aria attribute only for onFocus (input) elements
if (tooltipTarget.tagName === inputName){
if (tooltipTarget.tagName === 'INPUT'){
tooltipTarget.setAttribute('aria-describedby', 'tooltip');
}

const tooltipTargetRect = tooltipTarget.getBoundingClientRect();
tooltipEl.innerHTML = text;
tooltipEl.classList.remove('tooltip--hidden');

tooltipEl.innerHTML = text;
tooltipStyle.top = `calc(${tooltipTargetRect.bottom + window.scrollY}px + 1em)`
tooltipStyle.left = `${tooltipTargetRect.left + window.pageXOffset}px`;
tooltipStyle.left = `${tooltipTargetRect.left + window.scrollX}px`;
tooltipEl.classList.remove('tooltip--bottom');
tooltipEl.classList.add('tooltip--top');

Expand All @@ -151,7 +146,7 @@ const tooltip = new function () {
this.handleClick = (e) => {
tooltipTarget = e.target;

if (tooltipTarget.tagName === buttonName && tabbedIn) {
if (tooltipTarget.tagName === 'BUTTON' && tabbedIn) {
if (!isTooltipVisible) {
this.show(e);
} else {
Expand All @@ -177,7 +172,7 @@ const tooltip = new function () {
if (tooltipTarget) {
tooltipTarget.removeEventListener('mouseleave', this.hide);
tooltipEl.removeEventListener('mouseleave', this.hide);
if (tooltipTarget.tagName === inputName){
if (tooltipTarget.tagName === 'INPUT'){
tooltipTarget.removeAttribute('aria-describedby');
}
tooltipTarget = null;
Expand Down
5 changes: 5 additions & 0 deletions less/tooltip.less
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,9 @@
vertical-align: top;
}
}

&__text-button,
&__icon-button {
outline-offset: 2px;
}
}

0 comments on commit a7e133b

Please sign in to comment.