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>
This commit is contained in:
Ludovic Fernandez
2025-08-18 00:26:43 +02:00
committed by GitHub
parent b2ff662c8e
commit 363b1e50ff
8 changed files with 72 additions and 6 deletions

View File

@@ -7,11 +7,32 @@
const optionsElement = switcher.nextElementSibling;
optionsElement.classList.toggle('hx:hidden');
// Calculate position of language options element
// Calculate the position of a language options element.
const switcherRect = switcher.getBoundingClientRect();
const translateY = switcherRect.top - window.innerHeight - 15;
optionsElement.style.transform = `translate3d(${switcherRect.left}px, ${translateY}px, 0)`;
// 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)`;
});
});