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