Replace native <select> language picker with styled dropdown
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:
claude
2026-06-16 08:29:10 +00:00
parent 86a902c197
commit 703f4d6ee2
2 changed files with 58 additions and 9 deletions
@@ -1,10 +1,54 @@
li.language-picker
select.language-picker-select(
name='lng'
translate='no'
onchange='window.location.href="/set-language?lng="+encodeURIComponent(this.value)+"&return_to="+encodeURIComponent(window.location.pathname)'
aria-label=translate('select_a_language')
)
each lngCode in availableLanguages
if settings.translatedLanguages[lngCode]
option(value=lngCode selected=lngCode === currentLngCode)= settings.translatedLanguages[lngCode]
.dropdown
button#language-picker-toggle.btn-inline-link(
type='button'
aria-haspopup='true'
aria-expanded='false'
aria-label=translate('select_a_language')
translate='no'
)
span.material-symbols translate
| &nbsp;
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 {
// Open upward — Popper.js isn't available on all page layouts
top: auto;
bottom: 100%;
margin-bottom: var(--spacing-02);
.dropdown-item {
&.active {
color: var(--green-70);