feat(a11y): make menu buttons in 'More' dropdown selectable with the keyboard (#2976)

Co-authored-by: userquin <userquin@gmail.com>
This commit is contained in:
jyn 2024-10-21 05:00:51 -04:00 committed by GitHub
parent ae1da4c3e8
commit dac42e062c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 52 additions and 8 deletions

View file

@ -71,6 +71,7 @@ async function removeUserNote() {
/> />
</NuxtLink> </NuxtLink>
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="isShareSupported" v-if="isShareSupported"
:text="$t('menu.share_account', [`@${account.acct}`])" :text="$t('menu.share_account', [`@${account.acct}`])"
icon="i-ri:share-line" icon="i-ri:share-line"
@ -81,12 +82,14 @@ async function removeUserNote() {
<template v-if="currentUser"> <template v-if="currentUser">
<template v-if="!isSelf"> <template v-if="!isSelf">
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.mention_account', [`@${account.acct}`])" :text="$t('menu.mention_account', [`@${account.acct}`])"
icon="i-ri:at-line" icon="i-ri:at-line"
:command="command" :command="command"
@click="mentionUser(account)" @click="mentionUser(account)"
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.direct_message_account', [`@${account.acct}`])" :text="$t('menu.direct_message_account', [`@${account.acct}`])"
icon="i-ri:message-3-line" icon="i-ri:message-3-line"
:command="command" :command="command"
@ -94,6 +97,7 @@ async function removeUserNote() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="!relationship?.showingReblogs" v-if="!relationship?.showingReblogs"
icon="i-ri:repeat-line" icon="i-ri:repeat-line"
:text="$t('menu.show_reblogs', [`@${account.acct}`])" :text="$t('menu.show_reblogs', [`@${account.acct}`])"
@ -101,6 +105,7 @@ async function removeUserNote() {
@click="toggleReblogs()" @click="toggleReblogs()"
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-else v-else
:text="$t('menu.hide_reblogs', [`@${account.acct}`])" :text="$t('menu.hide_reblogs', [`@${account.acct}`])"
icon="i-ri:repeat-line" icon="i-ri:repeat-line"
@ -109,6 +114,7 @@ async function removeUserNote() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="!relationship?.note || relationship?.note?.length === 0" v-if="!relationship?.note || relationship?.note?.length === 0"
:text="$t('menu.add_personal_note', [`@${account.acct}`])" :text="$t('menu.add_personal_note', [`@${account.acct}`])"
icon="i-ri-edit-2-line" icon="i-ri-edit-2-line"
@ -116,6 +122,7 @@ async function removeUserNote() {
@click="addUserNote()" @click="addUserNote()"
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-else v-else
:text="$t('menu.remove_personal_note', [`@${account.acct}`])" :text="$t('menu.remove_personal_note', [`@${account.acct}`])"
icon="i-ri-edit-2-line" icon="i-ri-edit-2-line"
@ -124,6 +131,7 @@ async function removeUserNote() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="!relationship?.muting" v-if="!relationship?.muting"
:text="$t('menu.mute_account', [`@${account.acct}`])" :text="$t('menu.mute_account', [`@${account.acct}`])"
icon="i-ri:volume-mute-line" icon="i-ri:volume-mute-line"
@ -131,6 +139,7 @@ async function removeUserNote() {
@click="toggleMuteAccount (relationship!, account)" @click="toggleMuteAccount (relationship!, account)"
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-else v-else
:text="$t('menu.unmute_account', [`@${account.acct}`])" :text="$t('menu.unmute_account', [`@${account.acct}`])"
icon="i-ri:volume-up-fill" icon="i-ri:volume-up-fill"
@ -139,6 +148,7 @@ async function removeUserNote() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="!relationship?.blocking" v-if="!relationship?.blocking"
:text="$t('menu.block_account', [`@${account.acct}`])" :text="$t('menu.block_account', [`@${account.acct}`])"
icon="i-ri:forbid-2-line" icon="i-ri:forbid-2-line"
@ -146,6 +156,7 @@ async function removeUserNote() {
@click="toggleBlockAccount (relationship!, account)" @click="toggleBlockAccount (relationship!, account)"
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-else v-else
:text="$t('menu.unblock_account', [`@${account.acct}`])" :text="$t('menu.unblock_account', [`@${account.acct}`])"
icon="i-ri:checkbox-circle-line" icon="i-ri:checkbox-circle-line"
@ -155,6 +166,7 @@ async function removeUserNote() {
<template v-if="getServerName(account) !== currentServer"> <template v-if="getServerName(account) !== currentServer">
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="!relationship?.domainBlocking" v-if="!relationship?.domainBlocking"
:text="$t('menu.block_domain', [getServerName(account)])" :text="$t('menu.block_domain', [getServerName(account)])"
icon="i-ri:shut-down-line" icon="i-ri:shut-down-line"
@ -162,6 +174,7 @@ async function removeUserNote() {
@click="toggleBlockDomain(relationship!, account)" @click="toggleBlockDomain(relationship!, account)"
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-else v-else
:text="$t('menu.unblock_domain', [getServerName(account)])" :text="$t('menu.unblock_domain', [getServerName(account)])"
icon="i-ri:restart-line" icon="i-ri:restart-line"
@ -171,6 +184,7 @@ async function removeUserNote() {
</template> </template>
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.report_account', [`@${account.acct}`])" :text="$t('menu.report_account', [`@${account.acct}`])"
icon="i-ri:flag-2-line" icon="i-ri:flag-2-line"
:command="command" :command="command"

View file

@ -1,16 +1,24 @@
<script setup lang="ts"> <script setup lang="ts">
const props = withDefaults(defineProps<{ const {
is = 'div',
text,
description,
icon,
checked,
command,
} = defineProps<{
is?: string is?: string
text?: string text?: string
description?: string description?: string
icon?: string icon?: string
checked?: boolean checked?: boolean
command?: boolean command?: boolean
}>(), { }>()
is: 'div',
})
const emit = defineEmits(['click']) const emit = defineEmits(['click'])
const type = computed(() => is === 'button' ? 'button' : null)
const { hide } = useDropdownContext() || {} const { hide } = useDropdownContext() || {}
const el = ref<HTMLDivElement>() const el = ref<HTMLDivElement>()
@ -24,11 +32,11 @@ useCommand({
scope: 'Actions', scope: 'Actions',
order: -1, order: -1,
visible: () => props.command && props.text, visible: () => command && text,
name: () => props.text!, name: () => text!,
icon: () => props.icon ?? 'i-ri:question-line', icon: () => icon ?? 'i-ri:question-line',
description: () => props.description, description: () => description,
onActivate() { onActivate() {
const clickEvent = new MouseEvent('click', { const clickEvent = new MouseEvent('click', {
@ -46,6 +54,7 @@ useCommand({
v-bind="$attrs" v-bind="$attrs"
:is="is" :is="is"
ref="el" ref="el"
:type="type"
w-full w-full
flex gap-3 items-center cursor-pointer px4 py3 flex gap-3 items-center cursor-pointer px4 py3
select-none select-none

View file

@ -146,6 +146,7 @@ function showFavoritedAndBoostedBy() {
<div flex="~ col"> <div flex="~ col">
<template v-if="getPreferences(userSettings, 'zenMode') && !details"> <template v-if="getPreferences(userSettings, 'zenMode') && !details">
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('action.reply')" :text="$t('action.reply')"
icon="i-ri:chat-1-line" icon="i-ri:chat-1-line"
:command="command" :command="command"
@ -153,6 +154,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="status.reblogged ? $t('action.boosted') : $t('action.boost')" :text="status.reblogged ? $t('action.boosted') : $t('action.boost')"
icon="i-ri:repeat-fill" icon="i-ri:repeat-fill"
:class="status.reblogged ? 'text-green' : ''" :class="status.reblogged ? 'text-green' : ''"
@ -162,6 +164,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="status.favourited ? $t('action.favourited') : $t('action.favourite')" :text="status.favourited ? $t('action.favourited') : $t('action.favourite')"
:icon="useStarFavoriteIcon :icon="useStarFavoriteIcon
? status.favourited ? 'i-ri:star-fill' : 'i-ri:star-line' ? status.favourited ? 'i-ri:star-fill' : 'i-ri:star-line'
@ -176,6 +179,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="status.bookmarked ? $t('action.bookmarked') : $t('action.bookmark')" :text="status.bookmarked ? $t('action.bookmarked') : $t('action.bookmark')"
:icon="status.bookmarked ? 'i-ri:bookmark-fill' : 'i-ri:bookmark-line'" :icon="status.bookmarked ? 'i-ri:bookmark-fill' : 'i-ri:bookmark-line'"
:class="status.bookmarked :class="status.bookmarked
@ -189,6 +193,7 @@ function showFavoritedAndBoostedBy() {
</template> </template>
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.show_favourited_and_boosted_by')" :text="$t('menu.show_favourited_and_boosted_by')"
icon="i-ri:hearts-line" icon="i-ri:hearts-line"
:command="command" :command="command"
@ -196,6 +201,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.copy_link_to_post')" :text="$t('menu.copy_link_to_post')"
icon="i-ri:link" icon="i-ri:link"
:command="command" :command="command"
@ -203,6 +209,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.copy_original_link_to_post')" :text="$t('menu.copy_original_link_to_post')"
icon="i-ri:links-fill" icon="i-ri:links-fill"
:command="command" :command="command"
@ -210,6 +217,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="isShareSupported" v-if="isShareSupported"
:text="$t('menu.share_post')" :text="$t('menu.share_post')"
icon="i-ri:share-line" icon="i-ri:share-line"
@ -218,6 +226,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="currentUser && (status.account.id === currentUser.account.id || status.mentions.some(m => m.id === currentUser!.account.id))" v-if="currentUser && (status.account.id === currentUser.account.id || status.mentions.some(m => m.id === currentUser!.account.id))"
:text="status.muted ? $t('menu.unmute_conversation') : $t('menu.mute_conversation')" :text="status.muted ? $t('menu.unmute_conversation') : $t('menu.mute_conversation')"
:icon="status.muted ? 'i-ri:eye-line' : 'i-ri:eye-off-line'" :icon="status.muted ? 'i-ri:eye-line' : 'i-ri:eye-off-line'"
@ -237,6 +246,7 @@ function showFavoritedAndBoostedBy() {
<template v-if="isHydrated && currentUser"> <template v-if="isHydrated && currentUser">
<template v-if="isAuthor"> <template v-if="isAuthor">
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="status.pinned ? $t('menu.unpin_on_profile') : $t('menu.pin_on_profile')" :text="status.pinned ? $t('menu.unpin_on_profile') : $t('menu.pin_on_profile')"
icon="i-ri:pushpin-line" icon="i-ri:pushpin-line"
:command="command" :command="command"
@ -244,6 +254,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.edit')" :text="$t('menu.edit')"
icon="i-ri:edit-line" icon="i-ri:edit-line"
:command="command" :command="command"
@ -251,6 +262,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.delete')" :text="$t('menu.delete')"
icon="i-ri:delete-bin-line" icon="i-ri:delete-bin-line"
text-red-600 text-red-600
@ -259,6 +271,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.delete_and_redraft')" :text="$t('menu.delete_and_redraft')"
icon="i-ri:eraser-line" icon="i-ri:eraser-line"
text-red-600 text-red-600
@ -268,6 +281,7 @@ function showFavoritedAndBoostedBy() {
</template> </template>
<template v-else> <template v-else>
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.mention_account', [`@${status.account.acct}`])" :text="$t('menu.mention_account', [`@${status.account.acct}`])"
icon="i-ri:at-line" icon="i-ri:at-line"
:command="command" :command="command"
@ -275,6 +289,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="!useRelationship(status.account).value?.muting" v-if="!useRelationship(status.account).value?.muting"
:text="$t('menu.mute_account', [`@${status.account.acct}`])" :text="$t('menu.mute_account', [`@${status.account.acct}`])"
icon="i-ri:volume-mute-line" icon="i-ri:volume-mute-line"
@ -282,6 +297,7 @@ function showFavoritedAndBoostedBy() {
@click="toggleMuteAccount(useRelationship(status.account).value!, status.account)" @click="toggleMuteAccount(useRelationship(status.account).value!, status.account)"
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-else v-else
:text="$t('menu.unmute_account', [`@${status.account.acct}`])" :text="$t('menu.unmute_account', [`@${status.account.acct}`])"
icon="i-ri:volume-up-fill" icon="i-ri:volume-up-fill"
@ -290,6 +306,7 @@ function showFavoritedAndBoostedBy() {
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="!useRelationship(status.account).value?.blocking" v-if="!useRelationship(status.account).value?.blocking"
:text="$t('menu.block_account', [`@${status.account.acct}`])" :text="$t('menu.block_account', [`@${status.account.acct}`])"
icon="i-ri:forbid-2-line" icon="i-ri:forbid-2-line"
@ -297,6 +314,7 @@ function showFavoritedAndBoostedBy() {
@click="toggleBlockAccount(useRelationship(status.account).value!, status.account)" @click="toggleBlockAccount(useRelationship(status.account).value!, status.account)"
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-else v-else
:text="$t('menu.unblock_account', [`@${status.account.acct}`])" :text="$t('menu.unblock_account', [`@${status.account.acct}`])"
icon="i-ri:checkbox-circle-line" icon="i-ri:checkbox-circle-line"
@ -306,6 +324,7 @@ function showFavoritedAndBoostedBy() {
<template v-if="getServerName(status.account) && getServerName(status.account) !== currentServer"> <template v-if="getServerName(status.account) && getServerName(status.account) !== currentServer">
<CommonDropdownItem <CommonDropdownItem
is="button"
v-if="!useRelationship(status.account).value?.domainBlocking" v-if="!useRelationship(status.account).value?.domainBlocking"
:text="$t('menu.block_domain', [getServerName(status.account)])" :text="$t('menu.block_domain', [getServerName(status.account)])"
icon="i-ri:shut-down-line" icon="i-ri:shut-down-line"
@ -313,6 +332,7 @@ function showFavoritedAndBoostedBy() {
@click="toggleBlockDomain(useRelationship(status.account).value!, status.account)" @click="toggleBlockDomain(useRelationship(status.account).value!, status.account)"
/> />
<CommonDropdownItem <CommonDropdownItem
is="button"
v-else v-else
:text="$t('menu.unblock_domain', [getServerName(status.account)])" :text="$t('menu.unblock_domain', [getServerName(status.account)])"
icon="i-ri:restart-line" icon="i-ri:restart-line"
@ -322,6 +342,7 @@ function showFavoritedAndBoostedBy() {
</template> </template>
<CommonDropdownItem <CommonDropdownItem
is="button"
:text="$t('menu.report_account', [`@${status.account.acct}`])" :text="$t('menu.report_account', [`@${status.account.acct}`])"
icon="i-ri:flag-2-line" icon="i-ri:flag-2-line"
:command="command" :command="command"