All checks were successful
Build and Deploy Nuxt / build (push) Successful in 29s
146 lines
3.0 KiB
Vue
146 lines
3.0 KiB
Vue
<script setup>
|
|
import { ref } from 'vue'
|
|
|
|
const dropdownVisible = ref(false);
|
|
|
|
const toggleDropdown = () => {
|
|
dropdownVisible.value = !dropdownVisible.value;
|
|
}
|
|
|
|
const menuContainer = ref(null);
|
|
|
|
const handleClickOutside = (e) => {
|
|
if (menuContainer.value && !menuContainer.value.contains(e.target)) {
|
|
dropdownVisible.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
document.addEventListener('click', handleClickOutside)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
document.removeEventListener('click', handleClickOutside)
|
|
})
|
|
|
|
|
|
// i18n
|
|
const { locales, setLocale, locale } = useI18n()
|
|
|
|
const changeLocale = (lang) => {
|
|
setLocale(lang.code);
|
|
dropdownVisible.value = false
|
|
}
|
|
|
|
const localeIcon = (code) => {
|
|
const icons = {
|
|
en: 'EN',
|
|
es: 'ES',
|
|
ca: 'CA',
|
|
zh: 'ZH'
|
|
}
|
|
return icons[code] || code.toUpperCase()
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="menu-container" ref="menuContainer">
|
|
<button class="menu-button" @click="toggleDropdown">{{ $t("site_options.language_selector.dropdown") }} ▾</button>
|
|
|
|
<Transition name="dropdown">
|
|
<div class="dropdown" v-show="dropdownVisible">
|
|
<div class="section">
|
|
<div :class="{'menu-item': true, 'active': locale === loc.code}"
|
|
v-for="loc in locales" @click="changeLocale(loc)">
|
|
<span class="locale-icon">{{ localeIcon(loc.code) }}</span>{{ $t('locales.' + loc.code) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.menu-container {
|
|
position: relative;
|
|
}
|
|
|
|
.menu-button {
|
|
background: var(--color-background-fore);
|
|
color: var(--color-text);
|
|
font-size: 1em;
|
|
border: 1px solid var(--color-border-color);
|
|
padding: 8px 12px;
|
|
border-radius: 0;
|
|
cursor: pointer;
|
|
margin-right: 15px;
|
|
|
|
&.active {
|
|
background-color: var(--color-selected);
|
|
}
|
|
}
|
|
/* Dropdown transitions */
|
|
.dropdown-enter-active, .dropdown-leave-active {
|
|
transition: opacity 0.2s ease, transform 0.2s ease;
|
|
}
|
|
.dropdown-enter-from, .dropdown-leave-to {
|
|
opacity: 0;
|
|
transform: translateY(-8px);
|
|
}
|
|
|
|
.dropdown {
|
|
z-index: 10;
|
|
position: absolute;
|
|
top: 50px;
|
|
left: 0;
|
|
max-width: calc(100vw - 32px);
|
|
width: auto;
|
|
min-width: 140px;
|
|
background: var(--color-background-fore);
|
|
border: 1px solid var(--color-border-color);
|
|
border-radius: 0;
|
|
padding: 8px 0;
|
|
box-shadow: 4px -4px 0px 0px rgba(0,0,0,0.3);
|
|
border-left: 2px solid var(--color-border-color);
|
|
}
|
|
|
|
/* Items */
|
|
.locale-icon {
|
|
font-family: 'Hermit', 'Hurmit', monospace;
|
|
background: var(--color-border-color);
|
|
color: var(--color-text);
|
|
padding: 2px 6px;
|
|
font-size: 0.75em;
|
|
letter-spacing: 1px;
|
|
min-width: 32px;
|
|
text-align: center;
|
|
}
|
|
|
|
.menu-item {
|
|
padding: 8px 16px;
|
|
color: var(--color-text);
|
|
cursor: pointer;
|
|
display: flex;
|
|
gap: 10px;
|
|
align-items: center;
|
|
min-height: 36px;
|
|
|
|
&.active {
|
|
background: var(--color-selected);
|
|
}
|
|
}
|
|
|
|
.menu-item:hover {
|
|
background: var(--color-hover);
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.dropdown {
|
|
top: 42px;
|
|
}
|
|
|
|
.menu-item {
|
|
padding: 10px 12px;
|
|
}
|
|
}
|
|
</style> |