diff --git a/app.vue b/app.vue index c4659aa86..882239f65 100644 --- a/app.vue +++ b/app.vue @@ -56,6 +56,7 @@ useSeoMeta({ + diff --git a/components/ExampleCategoryListItem.vue b/components/ExampleCategoryListItem.vue index 1b4bc6f6d..594811e90 100644 --- a/components/ExampleCategoryListItem.vue +++ b/components/ExampleCategoryListItem.vue @@ -75,15 +75,15 @@ selectPronounForExample(false); () - - - - + + diff --git a/components/FilterBar.vue b/components/FilterBar.vue index 49e599d9d..726ce1023 100644 --- a/components/FilterBar.vue +++ b/components/FilterBar.vue @@ -4,7 +4,7 @@ import type { Category } from '~/src/classes.ts'; const filter = defineModel(); const filterCategory = defineModel('category'); -defineProps<{ +const props = defineProps<{ categories?: Category[] | undefined; submitButton?: boolean; }>(); @@ -17,10 +17,32 @@ const filterInput = useTemplateRef('filterInput'); const { $translator: translator } = useNuxtApp(); const allCategory: Category = { key: '', text: translator.translate('crud.all'), icon: 'clipboard-list' }; +const categoriesWithAllCategory = computed(() => [allCategory, ...(props.categories ?? [])]); defineExpose({ focus: () => filterInput.value?.focus(), }); + +const categoryList = useTemplateRef('categoryList'); +const categoryButtonKeydown = (event: KeyboardEvent) => { + if (filterCategory.value === undefined) { + return; + } + const activeIndex = categoriesWithAllCategory.value.map((category) => category.key).indexOf(filterCategory.value); + if (activeIndex === -1) { + return; + } + + if ((event.key === 'ArrowUp' || event.key === 'ArrowLeft') && + activeIndex > 0) { + filterCategory.value = categoriesWithAllCategory.value[activeIndex - 1].key; + (categoryList.value?.children[activeIndex - 1] as HTMLButtonElement | undefined)?.focus(); + } else if ((event.key === 'ArrowDown' || event.key === 'ArrowRight') && + activeIndex < categoriesWithAllCategory.value.length - 1) { + filterCategory.value = categoriesWithAllCategory.value[activeIndex + 1].key; + (categoryList.value?.children[activeIndex + 1] as HTMLButtonElement | undefined)?.focus(); + } +}; @@ -36,7 +58,12 @@ defineExpose({ class="form-control border-primary" :placeholder="$t('crud.filterLong')" > - + diff --git a/components/GrammarTable.vue b/components/GrammarTable.vue index a30406f6c..82b079152 100644 --- a/components/GrammarTable.vue +++ b/components/GrammarTable.vue @@ -1,12 +1,8 @@ + + + + home.skipToContent + + diff --git a/components/Table.vue b/components/Table.vue index cb7ba36f5..1cba4a24d 100644 --- a/components/Table.vue +++ b/components/Table.vue @@ -55,7 +55,7 @@ defineExpose({ - + {{ data.length }} - + @@ -86,6 +86,7 @@ defineExpose({ v-for="el in dataPage" :key="el.id" :class="['row-content p-2 d-grid gap-2 border-top', marked?.(el) ? 'marked' : '']" + role="row" > diff --git a/components/VersionDropdown.vue b/components/VersionDropdown.vue index 169fd1b0b..48cf6f8a6 100644 --- a/components/VersionDropdown.vue +++ b/components/VersionDropdown.vue @@ -72,6 +72,7 @@ const setSpelling = (spelling: string) => { class="d-inline-block" :end="end" menu-class="locale-dropdown shadow" + :title="$t('links.languageVersions')" > diff --git a/components/nouns/NounsConventionPage.vue b/components/nouns/NounsConventionPage.vue index dac71df50..5a69042f7 100644 --- a/components/nouns/NounsConventionPage.vue +++ b/components/nouns/NounsConventionPage.vue @@ -119,7 +119,11 @@ const nounConventionGroup = computed(() => { - + diff --git a/components/nouns/NounsDictionary.vue b/components/nouns/NounsDictionary.vue index 4133ca268..433f2c069 100644 --- a/components/nouns/NounsDictionary.vue +++ b/components/nouns/NounsDictionary.vue @@ -127,7 +127,12 @@ defineExpose({ loadNouns }); fixed > - + diff --git a/components/nouns/NounsGenderLabel.vue b/components/nouns/NounsGenderLabel.vue index 4c8ceed65..020176850 100644 --- a/components/nouns/NounsGenderLabel.vue +++ b/components/nouns/NounsGenderLabel.vue @@ -1,5 +1,6 @@