feat: 為列表元件添加角色屬性以改善可訪問性
This commit is contained in:
@@ -136,7 +136,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<v-list density="compact" width="180">
|
<v-list role="none" density="compact" width="180">
|
||||||
<v-list-subheader class="text-subtitle-1 py-2">顯示設定</v-list-subheader>
|
<v-list-subheader class="text-subtitle-1 py-2">顯示設定</v-list-subheader>
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<v-switch
|
<v-switch
|
||||||
|
|||||||
@@ -1,154 +1,162 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-list v-model:opened="openedModel" color="primary" density="compact" prepend-gap="8">
|
<nav aria-label="sidebar navigation">
|
||||||
<template v-for="item in menuItems" :key="item.path ?? item.title">
|
<v-list
|
||||||
<v-list-group
|
role="none"
|
||||||
v-if="item.subItems?.length"
|
v-model:opened="openedModel"
|
||||||
:id="getGroupId(item)"
|
color="primary"
|
||||||
:value="getGroupValue(item)"
|
density="compact"
|
||||||
>
|
prepend-gap="8"
|
||||||
<template #activator="{ props: activatorProps }">
|
>
|
||||||
<v-list-item
|
<template v-for="item in menuItems" :key="item.path ?? item.title">
|
||||||
v-bind="isShrink ? undefined : activatorProps"
|
<v-list-group
|
||||||
role="listitem"
|
v-if="item.subItems?.length"
|
||||||
:aria-selected="undefined"
|
:id="getGroupId(item)"
|
||||||
:class="{ 'px-0': isShrink }"
|
:value="getGroupValue(item)"
|
||||||
:link="isNavigable(item) && !!item.path"
|
>
|
||||||
:to="isNavigable(item) ? item.path : undefined"
|
<template #activator="{ props: activatorProps }">
|
||||||
@click="emitSelect(item)"
|
<v-list-item
|
||||||
>
|
v-bind="isShrink ? undefined : activatorProps"
|
||||||
<template #prepend>
|
role="button"
|
||||||
<v-icon v-if="item.icon" size="20" :icon="item.icon" />
|
:aria-selected="undefined"
|
||||||
<v-btn
|
:class="{ 'px-0': isShrink }"
|
||||||
v-if="isShrink && !item.icon"
|
:link="isNavigable(item) && !!item.path"
|
||||||
class=""
|
:to="isNavigable(item) ? item.path : undefined"
|
||||||
rounded
|
@click="emitSelect(item)"
|
||||||
size="36"
|
>
|
||||||
spaced="start"
|
<template #prepend>
|
||||||
variant="text"
|
<v-icon v-if="item.icon" size="20" :icon="item.icon" />
|
||||||
>{{ item.title?.charAt(0) }}</v-btn
|
<v-btn
|
||||||
>
|
v-if="isShrink && !item.icon"
|
||||||
</template>
|
class=""
|
||||||
<template #title>
|
rounded
|
||||||
<span v-if="!isShrink" class="text-body-2 nav-text-overflow">{{ item.title }}</span>
|
size="36"
|
||||||
</template>
|
spaced="start"
|
||||||
<template #append>
|
variant="text"
|
||||||
<v-chip
|
>{{ item.title?.charAt(0) }}</v-btn
|
||||||
v-if="!isShrink && getItemCount(item) > 0"
|
>
|
||||||
class="menu-count"
|
</template>
|
||||||
color="secondary"
|
<template #title>
|
||||||
size="x-small"
|
<span v-if="!isShrink" class="text-body-2 nav-text-overflow">{{ item.title }}</span>
|
||||||
variant="tonal"
|
</template>
|
||||||
>
|
<template #append>
|
||||||
{{ getItemCount(item) }}
|
<v-chip
|
||||||
</v-chip>
|
v-if="!isShrink && getItemCount(item) > 0"
|
||||||
</template>
|
class="menu-count"
|
||||||
</v-list-item>
|
color="secondary"
|
||||||
</template>
|
size="x-small"
|
||||||
|
variant="tonal"
|
||||||
|
>
|
||||||
|
{{ getItemCount(item) }}
|
||||||
|
</v-chip>
|
||||||
|
</template>
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-for="subItem in item.subItems" :key="subItem.path ?? subItem.title">
|
||||||
|
<v-list-group
|
||||||
|
v-if="subItem.subItems?.length"
|
||||||
|
:id="getGroupId(subItem, getGroupId(item))"
|
||||||
|
:value="getGroupValue(subItem, getGroupValue(item))"
|
||||||
|
>
|
||||||
|
<template #activator="{ props: subProps }">
|
||||||
|
<v-list-item
|
||||||
|
v-bind="subProps"
|
||||||
|
role="button"
|
||||||
|
:aria-selected="undefined"
|
||||||
|
:link="isNavigable(subItem)"
|
||||||
|
:prepend-icon="subItem.icon || mdiMenuRight"
|
||||||
|
:to="isNavigable(subItem) ? subItem.path : undefined"
|
||||||
|
@click="emitSelect(subItem)"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<span class="text-body-2 nav-text-overflow">{{ subItem.title }}</span>
|
||||||
|
</template>
|
||||||
|
<template #append>
|
||||||
|
<v-chip
|
||||||
|
v-if="getItemCount(subItem) > 0"
|
||||||
|
class="menu-count"
|
||||||
|
color="secondary"
|
||||||
|
size="x-small"
|
||||||
|
variant="tonal"
|
||||||
|
>
|
||||||
|
{{ getItemCount(subItem) }}
|
||||||
|
</v-chip>
|
||||||
|
</template>
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template v-for="subItem in item.subItems" :key="subItem.path ?? subItem.title">
|
|
||||||
<v-list-group
|
|
||||||
v-if="subItem.subItems?.length"
|
|
||||||
:id="getGroupId(subItem, getGroupId(item))"
|
|
||||||
:value="getGroupValue(subItem, getGroupValue(item))"
|
|
||||||
>
|
|
||||||
<template #activator="{ props: subProps }">
|
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-bind="subProps"
|
v-for="subSubItem in subItem.subItems"
|
||||||
role="listitem"
|
:key="subSubItem.path ?? subSubItem.title"
|
||||||
:aria-selected="undefined"
|
:link="!!subSubItem.path"
|
||||||
:link="isNavigable(subItem)"
|
:prepend-icon="mdiCircleSmall"
|
||||||
:prepend-icon="subItem.icon || mdiMenuRight"
|
:to="subSubItem.path"
|
||||||
:to="isNavigable(subItem) ? subItem.path : undefined"
|
@click="emitSelect(subSubItem)"
|
||||||
@click="emitSelect(subItem)"
|
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<span class="text-body-2 nav-text-overflow">{{ subItem.title }}</span>
|
<v-tooltip location="end" :text="subSubItem.title" :aria-label="subSubItem.title">
|
||||||
</template>
|
<template #activator="{ props: tooltipProps }">
|
||||||
<template #append>
|
<span v-bind="tooltipProps" class="text-body-2 nav-text-overflow">{{
|
||||||
<v-chip
|
subSubItem.title
|
||||||
v-if="getItemCount(subItem) > 0"
|
}}</span>
|
||||||
class="menu-count"
|
</template>
|
||||||
color="secondary"
|
</v-tooltip>
|
||||||
size="x-small"
|
|
||||||
variant="tonal"
|
|
||||||
>
|
|
||||||
{{ getItemCount(subItem) }}
|
|
||||||
</v-chip>
|
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</template>
|
</v-list-group>
|
||||||
|
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-for="subSubItem in subItem.subItems"
|
v-else
|
||||||
:key="subSubItem.path ?? subSubItem.title"
|
:link="!!subItem.path"
|
||||||
:link="!!subSubItem.path"
|
:prepend-icon="subItem.icon || mdiMenuRight"
|
||||||
:prepend-icon="mdiCircleSmall"
|
:to="subItem.path"
|
||||||
:to="subSubItem.path"
|
@click="emitSelect(subItem)"
|
||||||
@click="emitSelect(subSubItem)"
|
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<v-tooltip location="end" :text="subSubItem.title" :aria-label="subSubItem.title">
|
<v-tooltip location="end" :text="subItem.title" :aria-label="subItem.title">
|
||||||
<template #activator="{ props: tooltipProps }">
|
<template #activator="{ props: tooltipProps }">
|
||||||
<span v-bind="tooltipProps" class="text-body-2 nav-text-overflow">{{
|
<span v-bind="tooltipProps" class="text-body-2 nav-text-overflow">{{
|
||||||
subSubItem.title
|
subItem.title
|
||||||
}}</span>
|
}}</span>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list-group>
|
</template>
|
||||||
|
</v-list-group>
|
||||||
|
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-else
|
v-else
|
||||||
:link="!!subItem.path"
|
:class="{ 'px-0': isShrink }"
|
||||||
:prepend-icon="subItem.icon || mdiMenuRight"
|
:link="!!item.path"
|
||||||
:to="subItem.path"
|
:to="item.path"
|
||||||
@click="emitSelect(subItem)"
|
@click="emitSelect(item)"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #prepend>
|
||||||
<v-tooltip location="end" :text="subItem.title" :aria-label="subItem.title">
|
<v-icon v-if="item.icon" size="20" :icon="item.icon" />
|
||||||
<template #activator="{ props: tooltipProps }">
|
<v-btn
|
||||||
<span v-bind="tooltipProps" class="text-body-2 nav-text-overflow">{{
|
v-if="isShrink && !item.icon"
|
||||||
subItem.title
|
class=""
|
||||||
}}</span>
|
rounded
|
||||||
</template>
|
size="36"
|
||||||
</v-tooltip>
|
spaced="start"
|
||||||
</template>
|
variant="text"
|
||||||
</v-list-item>
|
>{{ item.title?.charAt(0) }}</v-btn
|
||||||
</template>
|
>
|
||||||
</v-list-group>
|
</template>
|
||||||
|
<template #title>
|
||||||
<v-list-item
|
<v-tooltip v-if="!isShrink" location="end" :text="item.title" :aria-label="item.title">
|
||||||
v-else
|
<template #activator="{ props: tooltipProps }">
|
||||||
:class="{ 'px-0': isShrink }"
|
<span v-bind="tooltipProps" class="text-body-2 nav-text-overflow">{{
|
||||||
:link="!!item.path"
|
item.title
|
||||||
:to="item.path"
|
}}</span>
|
||||||
@click="emitSelect(item)"
|
</template>
|
||||||
>
|
</v-tooltip>
|
||||||
<template #prepend>
|
</template>
|
||||||
<v-icon v-if="item.icon" size="20" :icon="item.icon" />
|
</v-list-item>
|
||||||
<v-btn
|
</template>
|
||||||
v-if="isShrink && !item.icon"
|
</v-list>
|
||||||
class=""
|
</nav>
|
||||||
rounded
|
|
||||||
size="36"
|
|
||||||
spaced="start"
|
|
||||||
variant="text"
|
|
||||||
>{{ item.title?.charAt(0) }}</v-btn
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #title>
|
|
||||||
<v-tooltip v-if="!isShrink" location="end" :text="item.title" :aria-label="item.title">
|
|
||||||
<template #activator="{ props: tooltipProps }">
|
|
||||||
<span v-bind="tooltipProps" class="text-body-2 nav-text-overflow">{{
|
|
||||||
item.title
|
|
||||||
}}</span>
|
|
||||||
</template>
|
|
||||||
</v-tooltip>
|
|
||||||
</template>
|
|
||||||
</v-list-item>
|
|
||||||
</template>
|
|
||||||
</v-list>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-sheet class="mobile-favorites-panel d-flex flex-column" color="surface">
|
<v-sheet class="mobile-favorites-panel d-flex flex-column" color="surface">
|
||||||
<v-list class="px-2 py-2 flex-grow-1 overflow-auto" density="comfortable">
|
<v-list role="none" class="px-2 py-2 flex-grow-1 overflow-auto" density="comfortable">
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-for="item in favoriteItems"
|
v-for="item in favoriteItems"
|
||||||
:key="item.path ?? item.title"
|
:key="item.path ?? item.title"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-sheet class="mobile-menu-panel d-flex flex-column" color="surface">
|
<v-sheet class="mobile-menu-panel d-flex flex-column" color="surface">
|
||||||
<v-list class="px-2 py-2 flex-grow-1 overflow-auto" density="comfortable">
|
<v-list role="none" class="px-2 py-2 flex-grow-1 overflow-auto" density="comfortable">
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-for="item in mobileCurrentItems"
|
v-for="item in mobileCurrentItems"
|
||||||
:key="item.path ?? item.title"
|
:key="item.path ?? item.title"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
variant="text"
|
variant="text"
|
||||||
></v-btn>
|
></v-btn>
|
||||||
</template>
|
</template>
|
||||||
<v-list density="compact">
|
<v-list role="none" density="compact">
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-for="localeOption in localeOptions"
|
v-for="localeOption in localeOptions"
|
||||||
:key="localeOption"
|
:key="localeOption"
|
||||||
|
|||||||
Reference in New Issue
Block a user