Files
hextra_mirror/assets/js/lang.js
Ludovic Fernandez 363b1e50ff feat(navbar): language switcher (#760)
* feat(navbar): language switcher

* docs: add language-switch

* chore: just for the demo

* fix: drop conflicting CSS

* fix: use constant

* fix: pre-existing bug with rtl on mobile

* docs: add comment to explain the algo

* chore: more readable algo

* review

Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>

* feat: different icons

* feat: icon as param

* fix: inconsitency with rtl

* fix: render inside the sidebar

* chore: remove the demo

---------

Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
2025-08-17 23:26:43 +01:00

50 lines
1.8 KiB
JavaScript

(function () {
const languageSwitchers = document.querySelectorAll('.hextra-language-switcher');
languageSwitchers.forEach((switcher) => {
switcher.addEventListener('click', (e) => {
e.preventDefault();
switcher.dataset.state = switcher.dataset.state === 'open' ? 'closed' : 'open';
const optionsElement = switcher.nextElementSibling;
optionsElement.classList.toggle('hx:hidden');
// Calculate the position of a language options element.
const switcherRect = switcher.getBoundingClientRect();
// Must be called before optionsElement.clientWidth.
optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`;
const isOnTop = switcher.dataset.location === 'top';
const isRTL = document.body.dir === 'rtl'
// Stuck on the left side of the switcher.
let translateX = switcherRect.left;
if (isOnTop && !isRTL || !isOnTop && isRTL) {
// Stuck on the right side of the switcher.
translateX = switcherRect.right - optionsElement.clientWidth;
}
// Stuck on the top of the switcher.
let translateY = switcherRect.top - window.innerHeight - 15;
if (isOnTop) {
// Stuck on the bottom of the switcher.
translateY = switcherRect.top - window.innerHeight + 180;
}
optionsElement.style.transform = `translate3d(${translateX}px, ${translateY}px, 0)`;
});
});
// Dismiss language switcher when clicking outside
document.addEventListener('click', (e) => {
if (e.target.closest('.hextra-language-switcher') === null) {
languageSwitchers.forEach((switcher) => {
switcher.dataset.state = 'closed';
const optionsElement = switcher.nextElementSibling;
optionsElement.classList.add('hx:hidden');
});
}
});
})();