Replace native <select> language picker with styled dropdown
Build and Deploy Verso / deploy (push) Successful in 13m43s
Build and Deploy Verso / deploy (push) Successful in 13m43s
The native <select> looked like a form control ("cheap"). Replace it with
the same HTML+CSS pattern as the React LanguagePicker: btn-inline-link
toggle with a translate icon, Bootstrap dropdown-menu for the list, active
item highlighted in green.
A tiny self-contained inline script handles the toggle since Bootstrap JS
is not loaded on React-layout pages. It builds the return_to URL from
window.location.pathname at click time (same as the old select approach).
Added top: auto / bottom: 100% to .language-picker .dropdown-menu so the
list always opens upward regardless of whether Popper.js is present.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,54 @@
|
|||||||
li.language-picker
|
li.language-picker
|
||||||
select.language-picker-select(
|
.dropdown
|
||||||
name='lng'
|
button#language-picker-toggle.btn-inline-link(
|
||||||
translate='no'
|
type='button'
|
||||||
onchange='window.location.href="/set-language?lng="+encodeURIComponent(this.value)+"&return_to="+encodeURIComponent(window.location.pathname)'
|
aria-haspopup='true'
|
||||||
aria-label=translate('select_a_language')
|
aria-expanded='false'
|
||||||
)
|
aria-label=translate('select_a_language')
|
||||||
each lngCode in availableLanguages
|
translate='no'
|
||||||
if settings.translatedLanguages[lngCode]
|
)
|
||||||
option(value=lngCode selected=lngCode === currentLngCode)= settings.translatedLanguages[lngCode]
|
span.material-symbols translate
|
||||||
|
|
|
||||||
|
span.language-picker-text= settings.translatedLanguages[currentLngCode] || currentLngCode
|
||||||
|
ul.dropdown-menu.dropdown-menu-sm-width(
|
||||||
|
role='menu'
|
||||||
|
aria-labelledby='language-picker-toggle'
|
||||||
|
translate='no'
|
||||||
|
)
|
||||||
|
each lngCode in availableLanguages
|
||||||
|
if settings.translatedLanguages[lngCode]
|
||||||
|
li(role='none')
|
||||||
|
a.dropdown-item(
|
||||||
|
role='menuitem'
|
||||||
|
data-lng=lngCode
|
||||||
|
class=lngCode === currentLngCode ? 'active' : ''
|
||||||
|
)= settings.translatedLanguages[lngCode]
|
||||||
|
script.
|
||||||
|
(function () {
|
||||||
|
var toggle = document.getElementById('language-picker-toggle')
|
||||||
|
var menu = toggle && toggle.parentElement.querySelector('.dropdown-menu')
|
||||||
|
if (!toggle || !menu) return
|
||||||
|
// Build return_to at runtime so the href reflects the actual current path
|
||||||
|
menu.querySelectorAll('a[data-lng]').forEach(function (a) {
|
||||||
|
var lng = a.getAttribute('data-lng')
|
||||||
|
a.href =
|
||||||
|
'/set-language?lng=' +
|
||||||
|
encodeURIComponent(lng) +
|
||||||
|
'&return_to=' +
|
||||||
|
encodeURIComponent(window.location.pathname)
|
||||||
|
})
|
||||||
|
function close() {
|
||||||
|
menu.classList.remove('show')
|
||||||
|
toggle.setAttribute('aria-expanded', 'false')
|
||||||
|
}
|
||||||
|
toggle.addEventListener('click', function (e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
var opening = !menu.classList.contains('show')
|
||||||
|
menu.classList.toggle('show', opening)
|
||||||
|
toggle.setAttribute('aria-expanded', String(opening))
|
||||||
|
})
|
||||||
|
document.addEventListener('click', close)
|
||||||
|
document.addEventListener('keydown', function (e) {
|
||||||
|
if (e.key === 'Escape') { close(); toggle.focus() }
|
||||||
|
})
|
||||||
|
})()
|
||||||
|
|||||||
@@ -218,6 +218,11 @@ footer.site-footer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.language-picker .dropdown-menu {
|
.language-picker .dropdown-menu {
|
||||||
|
// Open upward — Popper.js isn't available on all page layouts
|
||||||
|
top: auto;
|
||||||
|
bottom: 100%;
|
||||||
|
margin-bottom: var(--spacing-02);
|
||||||
|
|
||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
&.active {
|
&.active {
|
||||||
color: var(--green-70);
|
color: var(--green-70);
|
||||||
|
|||||||
Reference in New Issue
Block a user