67 lines
1.7 KiB
Vue
67 lines
1.7 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref, watch } from 'vue'
|
|
import { locale, t } from '@/i18n'
|
|
import { chooseLanguage, languageName, languageOptions } from '@/composables/useLanguage'
|
|
import { LANGUAGE_MENU_CLASS, useLanguageMenuRadios } from '@/composables/useRadioMenuRoles'
|
|
|
|
const props = defineProps<{ mobile?: boolean }>()
|
|
|
|
const open = ref(false)
|
|
useLanguageMenuRadios(open)
|
|
|
|
const items = computed(() =>
|
|
languageOptions.map((option) => ({
|
|
type: 'checkbox' as const,
|
|
label: option.label,
|
|
checked: locale.value === option.value,
|
|
class: props.mobile
|
|
? 'h-11 items-center py-0 text-base font-normal text-highlighted'
|
|
: 'h-8 items-center py-0 text-base font-normal text-highlighted',
|
|
onUpdateChecked: () => chooseLanguage(option.value),
|
|
})),
|
|
)
|
|
|
|
const chipClass = computed(() => [
|
|
props.mobile ? 'h-11' : 'h-7',
|
|
'gap-1.5 rounded-none border border-accented bg-transparent px-2 text-sm font-normal text-toned ring-0 hover:bg-elevated',
|
|
open.value ? 'bg-elevated' : '',
|
|
])
|
|
|
|
function focusCurrentRow() {
|
|
document.querySelector<HTMLElement>(`.${LANGUAGE_MENU_CLASS} [aria-checked="true"]`)?.focus()
|
|
}
|
|
|
|
watch(open, (value) => {
|
|
if (value) setTimeout(focusCurrentRow, 0)
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<UDropdownMenu
|
|
v-model:open="open"
|
|
:items="items"
|
|
:content="{
|
|
side: 'top',
|
|
align: 'end',
|
|
sideOffset: 8,
|
|
loop: true,
|
|
}"
|
|
:ui="{
|
|
content: `w-42 p-1 ${LANGUAGE_MENU_CLASS}`,
|
|
itemTrailingIcon: 'size-4',
|
|
}"
|
|
>
|
|
<UButton
|
|
color="neutral"
|
|
variant="outline"
|
|
icon="i-lucide-languages"
|
|
:aria-label="t('Language: {0}', [languageName])"
|
|
:aria-expanded="open"
|
|
:class="chipClass"
|
|
:ui="{ leadingIcon: 'size-3.5 text-toned' }"
|
|
>
|
|
{{ languageName }}
|
|
</UButton>
|
|
</UDropdownMenu>
|
|
</template>
|