fix(ui,a11y): focus lost when navigating using the keyboard (tab) (#2766)

zio/stable
Joaquín Sánchez 2024-04-06 05:58:50 +02:00 committed by GitHub
parent 25fb7c1c97
commit e53f651fbb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 31 additions and 23 deletions

View File

@ -11,7 +11,7 @@ defineProps<{
text-secondary-light text-secondary-light
> >
<slot name="prepend" /> <slot name="prepend" />
<CommonTooltip no-auto-focus :content="$t('account.bot')" :disabled="showLabel"> <CommonTooltip :content="$t('account.bot')" :disabled="showLabel">
<div i-mdi:robot-outline /> <div i-mdi:robot-outline />
</CommonTooltip> </CommonTooltip>
<div v-if="showLabel"> <div v-if="showLabel">

View File

@ -38,7 +38,7 @@ async function rejectFollowRequest() {
<template> <template>
<div flex gap-4> <div flex gap-4>
<template v-if="relationship?.requestedBy"> <template v-if="relationship?.requestedBy">
<CommonTooltip :content="$t('account.authorize')" no-auto-focus> <CommonTooltip :content="$t('account.authorize')">
<button <button
type="button" type="button"
rounded-full text-sm p2 border-1 rounded-full text-sm p2 border-1
@ -48,7 +48,7 @@ async function rejectFollowRequest() {
<span block text-current i-ri:check-fill /> <span block text-current i-ri:check-fill />
</button> </button>
</CommonTooltip> </CommonTooltip>
<CommonTooltip :content="$t('account.reject')" no-auto-focus> <CommonTooltip :content="$t('account.reject')">
<button <button
type="button" type="button"
rounded-full text-sm p2 border-1 rounded-full text-sm p2 border-1

View File

@ -196,7 +196,7 @@ async function copyAccountName() {
<div flex items-center gap-1> <div flex items-center gap-1>
<AccountHandle :account="account" overflow-unset line-clamp-unset /> <AccountHandle :account="account" overflow-unset line-clamp-unset />
<CommonTooltip placement="bottom" :content="$t('account.copy_account_name')" no-auto-focus flex> <CommonTooltip placement="bottom" :content="$t('account.copy_account_name')" flex>
<button text-secondary-light text-sm :class="isCopied ? 'i-ri:check-fill text-green' : 'i-ri:file-copy-line'" @click="copyAccountName"> <button text-secondary-light text-sm :class="isCopied ? 'i-ri:check-fill text-green' : 'i-ri:file-copy-line'" @click="copyAccountName">
<span sr-only>{{ $t('account.copy_account_name') }}</span> <span sr-only>{{ $t('account.copy_account_name') }}</span>
</button> </button>

View File

@ -58,6 +58,7 @@ const userSettings = useUserSettings()
:delay="{ show: 500, hide: 100 }" :delay="{ show: 500, hide: 100 }"
v-bind="$attrs" v-bind="$attrs"
:close-on-content-click="false" :close-on-content-click="false"
no-auto-focus
> >
<slot /> <slot />
<template #popper> <template #popper>

View File

@ -13,7 +13,7 @@ const { t } = useI18n()
text-secondary-light text-secondary-light
> >
<slot name="prepend" /> <slot name="prepend" />
<CommonTooltip no-auto-focus content="Lock" :disabled="showLabel"> <CommonTooltip content="Lock" :disabled="showLabel">
<div i-ri:lock-line /> <div i-ri:lock-line />
</CommonTooltip> </CommonTooltip>
<div v-if="showLabel"> <div v-if="showLabel">

View File

@ -33,6 +33,7 @@ const userSettings = useUserSettings()
:delay="{ show: 500, hide: 100 }" :delay="{ show: 500, hide: 100 }"
v-bind="$attrs" v-bind="$attrs"
:close-on-content-click="false" :close-on-content-click="false"
no-auto-focus
> >
<slot /> <slot />
<template #popper> <template #popper>

View File

@ -46,7 +46,7 @@ useCommands(() => command
</template> </template>
<template v-if="isHydrated && moreOptions?.options?.length"> <template v-if="isHydrated && moreOptions?.options?.length">
<CommonDropdown placement="bottom" flex cursor-pointer mx-1.25rem> <CommonDropdown placement="bottom" flex cursor-pointer mx-1.25rem>
<CommonTooltip placement="top" no-auto-focus :content="moreOptions.tooltip || t('action.more')"> <CommonTooltip placement="top" :content="moreOptions.tooltip || t('action.more')">
<button <button
cursor-pointer cursor-pointer
flex flex

View File

@ -13,6 +13,7 @@ defineProps<Props>()
v-if="isHydrated" v-if="isHydrated"
v-bind="$attrs" v-bind="$attrs"
auto-hide auto-hide
no-auto-focus
> >
<slot /> <slot />
<template #popper> <template #popper>

View File

@ -39,7 +39,6 @@ async function edit() {
<CommonTooltip <CommonTooltip
:content="isRemoved ? $t('list.add_account') : $t('list.remove_account')" :content="isRemoved ? $t('list.add_account') : $t('list.remove_account')"
:hover="isRemoved ? 'text-green' : 'text-red'" :hover="isRemoved ? 'text-green' : 'text-red'"
no-auto-focus
> >
<button <button
text-sm p2 border-1 transition-colors text-sm p2 border-1 transition-colors

View File

@ -113,7 +113,7 @@ onDeactivated(cancelEdit)
bg-base border="~ base" h10 m2 ps-1 pe-4 rounded-3 w-full flex="~ row" bg-base border="~ base" h10 m2 ps-1 pe-4 rounded-3 w-full flex="~ row"
items-center relative focus-within:box-shadow-outline gap-3 items-center relative focus-within:box-shadow-outline gap-3
> >
<CommonTooltip v-if="isEditing" :content="$t('list.cancel_edit')" no-auto-focus> <CommonTooltip v-if="isEditing" :content="$t('list.cancel_edit')">
<button <button
type="button" type="button"
rounded-full text-sm p2 transition-colors rounded-full text-sm p2 transition-colors
@ -136,7 +136,7 @@ onDeactivated(cancelEdit)
{{ form.title }} {{ form.title }}
</NuxtLink> </NuxtLink>
<div mr4 flex gap2> <div mr4 flex gap2>
<CommonTooltip v-if="isEditing" :content="$t('list.save')" no-auto-focus> <CommonTooltip v-if="isEditing" :content="$t('list.save')">
<button <button
type="submit" type="submit"
text-sm p2 border-1 transition-colors text-sm p2 border-1 transition-colors
@ -152,7 +152,7 @@ onDeactivated(cancelEdit)
</template> </template>
</button> </button>
</CommonTooltip> </CommonTooltip>
<CommonTooltip v-else :content="$t('list.edit')" no-auto-focus> <CommonTooltip v-else :content="$t('list.edit')">
<button <button
ref="editBtn" ref="editBtn"
type="button" type="button"
@ -164,7 +164,7 @@ onDeactivated(cancelEdit)
<span block text-current i-ri:edit-2-line class="rtl-flip" /> <span block text-current i-ri:edit-2-line class="rtl-flip" />
</button> </button>
</CommonTooltip> </CommonTooltip>
<CommonTooltip :content="$t('list.delete')" no-auto-focus> <CommonTooltip :content="$t('list.delete')">
<button <button
type="button" type="button"
text-sm p2 border-1 transition-colors text-sm p2 border-1 transition-colors
@ -192,7 +192,7 @@ onDeactivated(cancelEdit)
<div aria-hidden="true" i-ri:error-warning-fill /> <div aria-hidden="true" i-ri:error-warning-fill />
<p>{{ $t(`list.${isEditing ? 'edit_error' : 'delete_error'}`) }}</p> <p>{{ $t(`list.${isEditing ? 'edit_error' : 'delete_error'}`) }}</p>
</div> </div>
<CommonTooltip placement="bottom" :content="$t('list.clear_error')" no-auto-focus> <CommonTooltip placement="bottom" :content="$t('list.clear_error')">
<button <button
flex rounded-4 p1 hover:bg-active cursor-pointer transition-100 :aria-label="$t('list.clear_error')" flex rounded-4 p1 hover:bg-active cursor-pointer transition-100 :aria-label="$t('list.clear_error')"
@click="clearError" @click="clearError"

View File

@ -389,26 +389,26 @@ onDeactivated(() => {
</button> </button>
</PublishEmojiPicker> </PublishEmojiPicker>
<CommonTooltip v-if="draft.params.poll === undefined" placement="top" :content="$t('tooltip.add_media')" no-auto-focus> <CommonTooltip v-if="draft.params.poll === undefined" placement="top" :content="$t('tooltip.add_media')">
<button btn-action-icon :aria-label="$t('tooltip.add_media')" @click="pickAttachments"> <button btn-action-icon :aria-label="$t('tooltip.add_media')" @click="pickAttachments">
<div i-ri:image-add-line /> <div i-ri:image-add-line />
</button> </button>
</CommonTooltip> </CommonTooltip>
<template v-if="draft.attachments.length === 0"> <template v-if="draft.attachments.length === 0">
<CommonTooltip v-if="!draft.params.poll" placement="top" :content="$t('polls.create')" no-auto-focus> <CommonTooltip v-if="!draft.params.poll" placement="top" :content="$t('polls.create')">
<button btn-action-icon :aria-label="$t('polls.create')" @click="draft.params.poll = { options: [''], expiresIn: expiresInOptions[expiresInDefaultOptionIndex].seconds }"> <button btn-action-icon :aria-label="$t('polls.create')" @click="draft.params.poll = { options: [''], expiresIn: expiresInOptions[expiresInDefaultOptionIndex].seconds }">
<div i-ri:chat-poll-line /> <div i-ri:chat-poll-line />
</button> </button>
</CommonTooltip> </CommonTooltip>
<div v-else rounded-full b-1 border-dark flex="~ row" gap-1> <div v-else rounded-full b-1 border-dark flex="~ row" gap-1>
<CommonTooltip placement="top" :content="$t('polls.cancel')" no-auto-focus> <CommonTooltip placement="top" :content="$t('polls.cancel')">
<button btn-action-icon b-r border-dark :aria-label="$t('polls.cancel')" @click="draft.params.poll = undefined"> <button btn-action-icon b-r border-dark :aria-label="$t('polls.cancel')" @click="draft.params.poll = undefined">
<div i-ri:close-line /> <div i-ri:close-line />
</button> </button>
</CommonTooltip> </CommonTooltip>
<CommonDropdown placement="top"> <CommonDropdown placement="top">
<CommonTooltip placement="top" :content="$t('polls.settings')" no-auto-focus> <CommonTooltip placement="top" :content="$t('polls.settings')">
<button :aria-label="$t('polls.settings')" btn-action-icon w-12> <button :aria-label="$t('polls.settings')" btn-action-icon w-12>
<div i-ri:list-settings-line /> <div i-ri:list-settings-line />
<div i-ri:arrow-down-s-line text-sm text-secondary me--1 /> <div i-ri:arrow-down-s-line text-sm text-secondary me--1 />
@ -422,7 +422,7 @@ onDeactivated(() => {
</template> </template>
</CommonDropdown> </CommonDropdown>
<CommonDropdown placement="bottom"> <CommonDropdown placement="bottom">
<CommonTooltip placement="top" :content="$t('polls.expiration')" no-auto-focus> <CommonTooltip placement="top" :content="$t('polls.expiration')">
<button :aria-label="$t('polls.expiration')" btn-action-icon w-12> <button :aria-label="$t('polls.expiration')" btn-action-icon w-12>
<div i-ri:hourglass-line /> <div i-ri:hourglass-line />
<div i-ri:arrow-down-s-line text-sm text-secondary me--1 /> <div i-ri:arrow-down-s-line text-sm text-secondary me--1 />
@ -447,7 +447,7 @@ onDeactivated(() => {
<PublishCharacterCounter :max="characterLimit" :length="characterCount" /> <PublishCharacterCounter :max="characterLimit" :length="characterCount" />
<CommonTooltip placement="top" :content="$t('tooltip.change_language')" no-auto-focus> <CommonTooltip placement="top" :content="$t('tooltip.change_language')">
<CommonDropdown placement="bottom" auto-boundary-max-size> <CommonDropdown placement="bottom" auto-boundary-max-size>
<button btn-action-icon :aria-label="$t('tooltip.change_language')" w-max mr1> <button btn-action-icon :aria-label="$t('tooltip.change_language')" w-max mr1>
<span v-if="postLanguageDisplay" text-secondary text-sm ml1>{{ postLanguageDisplay }}</span> <span v-if="postLanguageDisplay" text-secondary text-sm ml1>{{ postLanguageDisplay }}</span>
@ -461,7 +461,7 @@ onDeactivated(() => {
</CommonDropdown> </CommonDropdown>
</CommonTooltip> </CommonTooltip>
<CommonTooltip placement="top" :content="$t('tooltip.add_content_warning')" no-auto-focus> <CommonTooltip placement="top" :content="$t('tooltip.add_content_warning')">
<button btn-action-icon :aria-label="$t('tooltip.add_content_warning')" @click="toggleSensitive"> <button btn-action-icon :aria-label="$t('tooltip.add_content_warning')" @click="toggleSensitive">
<div v-if="draft.params.sensitive" i-ri:alarm-warning-fill text-orange /> <div v-if="draft.params.sensitive" i-ri:alarm-warning-fill text-orange />
<div v-else i-ri:alarm-warning-line /> <div v-else i-ri:alarm-warning-line />
@ -477,7 +477,7 @@ onDeactivated(() => {
</template> </template>
</PublishVisibilityPicker> </PublishVisibilityPicker>
<CommonTooltip v-if="failedMessages.length > 0" id="publish-failed-tooltip" placement="top" :content="$t('tooltip.publish_failed')" no-auto-focus> <CommonTooltip v-if="failedMessages.length > 0" id="publish-failed-tooltip" placement="top" :content="$t('tooltip.publish_failed')">
<button <button
btn-danger rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit aria-describedby="publish-failed-tooltip" btn-danger rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit aria-describedby="publish-failed-tooltip"
> >
@ -488,7 +488,7 @@ onDeactivated(() => {
</button> </button>
</CommonTooltip> </CommonTooltip>
<CommonTooltip v-else id="publish-tooltip" placement="top" :content="$t('tooltip.add_publishable_content')" :disabled="!(isPublishDisabled || isExceedingCharacterLimit)" no-auto-focus> <CommonTooltip v-else id="publish-tooltip" placement="top" :content="$t('tooltip.add_publishable_content')" :disabled="!(isPublishDisabled || isExceedingCharacterLimit)">
<button <button
btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center
md:w-fit md:w-fit

View File

@ -160,7 +160,7 @@ const forceShow = ref(false)
<div flex="~ gap1" items-center> <div flex="~ gap1" items-center>
<StatusVisibilityIndicator v-if="status.visibility !== 'public'" :status="status" /> <StatusVisibilityIndicator v-if="status.visibility !== 'public'" :status="status" />
<div flex> <div flex>
<CommonTooltip :content="createdAt" no-auto-focus> <CommonTooltip :content="createdAt">
<NuxtLink :title="status.createdAt" :href="statusRoute.href" @click.prevent="go($event)"> <NuxtLink :title="status.createdAt" :href="statusRoute.href" @click.prevent="go($event)">
<time text-sm ws-nowrap hover:underline :datetime="status.createdAt"> <time text-sm ws-nowrap hover:underline :datetime="status.createdAt">
{{ timeago }} {{ timeago }}

View File

@ -129,7 +129,7 @@ onDeactivated(() => clearError(false))
<div aria-hidden="true" i-ri:error-warning-fill /> <div aria-hidden="true" i-ri:error-warning-fill />
<p>{{ $t('list.error') }}</p> <p>{{ $t('list.error') }}</p>
</div> </div>
<CommonTooltip placement="bottom" :content="$t('list.clear_error')" no-auto-focus> <CommonTooltip placement="bottom" :content="$t('list.clear_error')">
<button <button
flex rounded-4 p1 hover:bg-active cursor-pointer transition-100 :aria-label="$t('list.clear_error')" flex rounded-4 p1 hover:bg-active cursor-pointer transition-100 :aria-label="$t('list.clear_error')"
@click="clearError(true)" @click="clearError(true)"

View File

@ -185,6 +185,7 @@ exports[`content-rich > hashtag adds bdi 1`] = `
placement="bottom-start" placement="bottom-start"
class="inline-block" class="inline-block"
close-on-content-click="false" close-on-content-click="false"
no-auto-focus
><a ><a
class="mention hashtag" class="mention hashtag"
rel="nofollow noopener noreferrer" rel="nofollow noopener noreferrer"
@ -206,6 +207,7 @@ exports[`content-rich > hashtag doesn't add 2 bdi 1`] = `
placement="bottom-start" placement="bottom-start"
class="inline-block" class="inline-block"
close-on-content-click="false" close-on-content-click="false"
no-auto-focus
><a ><a
class="mention hashtag" class="mention hashtag"
rel="nofollow noopener noreferrer" rel="nofollow noopener noreferrer"
@ -328,6 +330,7 @@ exports[`content-rich > root p includes dir="auto" attr when mixed content 1`] =
placement="bottom-start" placement="bottom-start"
class="inline-block" class="inline-block"
close-on-content-click="false" close-on-content-click="false"
no-auto-focus
><a ><a
class="mention hashtag" class="mention hashtag"
rel="nofollow noopener noreferrer" rel="nofollow noopener noreferrer"
@ -341,6 +344,7 @@ exports[`content-rich > root p includes dir="auto" attr when mixed content 1`] =
placement="bottom-start" placement="bottom-start"
class="inline-block" class="inline-block"
close-on-content-click="false" close-on-content-click="false"
no-auto-focus
><a ><a
class="mention hashtag" class="mention hashtag"
rel="nofollow noopener noreferrer" rel="nofollow noopener noreferrer"
@ -388,6 +392,7 @@ exports[`content-rich > root p includes dir="auto" attr when mixed content 1`] =
placement="bottom-start" placement="bottom-start"
class="inline-block" class="inline-block"
close-on-content-click="false" close-on-content-click="false"
no-auto-focus
><a ><a
class="mention hashtag" class="mention hashtag"
rel="nofollow noopener noreferrer" rel="nofollow noopener noreferrer"
@ -401,6 +406,7 @@ exports[`content-rich > root p includes dir="auto" attr when mixed content 1`] =
placement="bottom-start" placement="bottom-start"
class="inline-block" class="inline-block"
close-on-content-click="false" close-on-content-click="false"
no-auto-focus
><a ><a
class="mention hashtag" class="mention hashtag"
rel="nofollow noopener noreferrer" rel="nofollow noopener noreferrer"