<div class="copyright">
<button class="copyright__button" type="button" title="Image attribution" aria-pressed="false">
<svg class="icon icon--copyright" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.dcaca1c147.svg#copyright"></use>
</svg> </button>
<div class="copyright__floating" tabindex="0" role="floating" hidden data-floating-placements="bottom,top,left,right">This is a copyright hint: <a class="link" data-link-type="internal" href="#"><span class="link__text u-underline">lorem ipsum dolor sit amet</span></a></div>
</div>
<div {{ html_attributes({ class: 'copyright' }, attrs ?? {}) }}>
<button class="copyright__button{{ overlay|default ? ' u-overlay-link' }}" type="button" title="{{ 'Image attribution' | t('site') }}" aria-pressed="false">
{% include '@icon' with { icon: 'copyright' } only %}
</button>
<div class="copyright__floating" tabindex="0" role="floating" hidden data-floating-placements="bottom,top,left,right">
{{- text | componentize(inline_only=true) -}}
</div>
</div>
{
"text": "This is a copyright hint: <a href=\"#\">lorem ipsum dolor sit amet</a>"
}
.copyright {
display: inline-block;
isolation: isolate;
}
.copyright__button {
--icon-size: var(--copyright-icon-size, 1.4rem);
align-items: center;
aspect-ratio: 1.4;
background-color: var(--copyright-background-color, var(--color-gray-950));
block-size: var(--copyright-size, 2.4rem);
border-color: var(--copyright-border-color, var(--color-white));
border-radius: var(--copyright-border-radius, 0.6rem);
border-style: var(--copyright-border-style, solid);
border-width: var(--copyright-border-width, 2px);
color: var(--copyright-color, var(--color-white));
cursor: pointer;
display: flex;
justify-content: center;
line-height: 0;
position: relative;
transition-property: background-color, color;
user-select: none;
z-index: 1;
&:is(:hover, :focus-visible, [aria-pressed='true']) {
background-color: var(--copyright-background-color--engaged, var(--color-orange-700));
color: var(--copyright-color--engaged, var(--color-white));
}
}
import { createFocusTrap, FocusTrap } from 'focus-trap';
import { on } from 'delegated-events';
import createFloatingWithArrow from '../../../javascripts/utils/createFloatingWithArrow';
import abort from '../../../javascripts/utils/abort';
import moveFocus from '../../../javascripts/utils/moveFocus';
let focusTrap: FocusTrap | null = null;
let cleanup: () => void;
on('click', 'button.copyright__button', async (event) => {
const { currentTarget: $button } = event;
const $copyright = $button.closest<HTMLDivElement>('.copyright') ?? abort();
event.preventDefault();
if (focusTrap) {
focusTrap.deactivate();
} else {
const $floating = $copyright?.querySelector<HTMLDivElement>('.copyright__floating') ?? abort();
const $portal = document.getElementById('portal') ?? document.body;
$floating.hidden = false;
$portal.appendChild($floating);
focusTrap = createFocusTrap($copyright, {
onDeactivate() {
$floating.hidden = true;
$copyright.appendChild($floating);
cleanup?.();
$button.classList.remove('copyright__button--active');
$button.setAttribute('aria-pressed', 'false');
moveFocus($button);
focusTrap = null;
},
async onActivate() {
cleanup = await createFloatingWithArrow({ $floating, $reference: $button });
$button.classList.add('copyright__button--active');
$button.setAttribute('aria-pressed', 'true');
moveFocus($floating);
},
initialFocus: false,
clickOutsideDeactivates: (e: MouseEvent | TouchEvent) => (
e.target instanceof HTMLElement ? !$floating.contains(e.target) : false
),
returnFocusOnDeactivate: false,
preventScroll: false,
});
focusTrap.activate();
}
});
No notes defined.