@use 'sprucecss/scss/spruce' as *;
.tooltip-demo {
align-items: center;
display: flex;
flex-wrap: wrap;
gap: spacer('m');
padding-block: spacer('xl');
}
.tooltip {
display: inline-flex;
position: relative;
&__content {
background-color: color('heading');
border-radius: radius('sm');
box-shadow: shadow('md');
color: color('background');
font-size: config('font-size-sm', $typography);
inline-size: max-content;
inset-block-end: calc(100% + #{spacer('xs')});
inset-inline-start: 50%;
line-height: config('line-height-md', $typography);
max-inline-size: 16rem;
opacity: 0;
padding: spacer('xxs') spacer('xs');
pointer-events: none;
position: absolute;
translate: -50% 0.25rem;
visibility: hidden;
z-index: z-index('tooltip');
@include transition($property: 'opacity, translate, visibility');
&::after {
border: 0.375rem solid transparent;
border-block-start-color: color('heading');
content: '';
inset-block-start: 100%;
inset-inline-start: 50%;
position: absolute;
translate: -50% 0;
}
}
&:hover &__content,
&:focus-within &__content,
&.is-open &__content {
opacity: 1;
translate: -50% 0;
visibility: visible;
}
&.is-dismissed &__content {
opacity: 0;
visibility: hidden;
}
&--bottom &__content {
inset-block: calc(100% + #{spacer('xs')}) auto;
translate: -50% -0.25rem;
&::after {
border-block-end-color: color('heading');
border-block-start-color: transparent;
inset-block: auto 100%;
}
}
}
[dir='rtl'] .tooltip__content {
translate: 50% 0.25rem;
}
<p class="tooltip-demo">
Hover or focus the buttons:
<span class="tooltip">
<button class="btn btn--outline-primary btn--icon" type="button" aria-describedby="tooltip-copy">
<svg class="btn__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect width="14" height="14" x="8" y="8" rx="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
<span class="sr-only">Copy</span>
</button>
<span class="tooltip__content" role="tooltip" id="tooltip-copy">Copy to clipboard</span>
</span>
<span class="tooltip tooltip--bottom">
<button class="btn btn--primary" type="button" aria-describedby="tooltip-publish">Publish</button>
<span class="tooltip__content" role="tooltip" id="tooltip-publish">Visible to everyone with the link</span>
</span>
</p>
(() => {
document.querySelectorAll('.tooltip').forEach((tooltip) => {
const reset = () => tooltip.classList.remove('is-dismissed');
tooltip.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
tooltip.classList.add('is-dismissed');
}
});
tooltip.addEventListener('mouseleave', reset);
tooltip.addEventListener('focusout', reset);
});
})();