Make profiles keyboard accessible (#3863)

Co-authored-by: Jason <84899178+jasonhenriquez@users.noreply.github.com>
This commit is contained in:
ChunkyProgrammer 2023-08-14 08:07:57 -07:00 committed by GitHub
parent ebf7e9985f
commit 2d934eabea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 60 additions and 3 deletions

View File

@ -47,7 +47,7 @@ module.exports = {
'plugin:vue/recommended',
'standard',
'plugin:jsonc/recommended-with-json',
// 'plugin:vuejs-accessibility/recommended' // uncomment once issues are fixed
'plugin:vuejs-accessibility/recommended'
],
// https://eslint.org/docs/user-guide/configuring#configuring-plugins
@ -70,6 +70,7 @@ module.exports = {
some: ['nesting', 'id']
}
}],
'vuejs-accessibility/no-static-element-interactions': 'off',
'n/no-callback-literal': 'warn',
'n/no-path-concat': 'warn',
'unicorn/better-regex': 'error',

View File

@ -10,10 +10,12 @@
<div class="channelThumbnail">
<router-link
:to="`/channel/${id}`"
tabindex="-1"
>
<img
:src="thumbnail"
class="channelImage"
alt=""
>
</router-link>
</div>

View File

@ -22,6 +22,7 @@
<img
:src="thumbnail"
class="thumbnailImage"
alt=""
>
</router-link>
<div

View File

@ -1,4 +1,5 @@
import { defineComponent } from 'vue'
import { sanitizeForHtmlId } from '../../helpers/accessibility'
export default defineComponent({
name: 'FtProfileBubble',
@ -21,12 +22,20 @@ export default defineComponent({
}
},
computed: {
sanitizedId: function() {
return 'profileBubble' + sanitizeForHtmlId(this.profileId)
},
profileInitial: function () {
return this?.profileName?.length > 0 ? Array.from(this.profileName)[0].toUpperCase() : ''
}
},
methods: {
goToProfile: function () {
goToProfile: function (event) {
if (event instanceof KeyboardEvent) {
if (event.target.getAttribute('role') === 'link' && event.key !== 'Enter') {
return
}
}
this.$router.push({
path: `/settings/profile/edit/${this.profileId}`
})

View File

@ -1,7 +1,11 @@
<template>
<div
class="bubblePadding"
tabindex="0"
:aria-labelledby="sanitizedId"
@click="goToProfile"
@keydown.space.prevent="goToProfile($event)"
@keydown.enter.prevent="goToProfile($event)"
>
<div
class="bubble"
@ -11,7 +15,10 @@
{{ profileInitial }}
</div>
</div>
<div class="profileName">
<div
:id="sanitizedId"
class="profileName"
>
{{ profileName }}
</div>
</div>

View File

@ -15,6 +15,7 @@
:channel-name="channel.name"
:channel-thumbnail="channel.thumbnail"
:show-selected="true"
role="button"
@click="handleChannelClick(index)"
/>
</ft-flex-box>

View File

@ -19,8 +19,12 @@
v-for="(color, index) in colorValues"
:key="index"
class="colorOption"
:title="color + ' ' + $t('Profile.Custom Color')"
:style="{ background: color }"
tabindex="0"
@click="profileBgColor = color"
@keydown.space.prevent="profileBgColor = color"
@keydown.enter.prevent="profileBgColor = color"
/>
</ft-flex-box>
<ft-flex-box

View File

@ -24,6 +24,7 @@
:channel-name="channel.name"
:channel-thumbnail="channel.thumbnail"
:show-selected="true"
role="button"
@click="handleChannelClick(index)"
/>
</ft-flex-box>

View File

@ -2,9 +2,14 @@
<div>
<div
class="colorOption"
:title="$t('Profile.Toggle Profile List')"
:style="{ background: activeProfile.bgColor, color: activeProfile.textColor }"
tabindex="0"
role="button"
@click="toggleProfileList"
@mousedown="handleIconMouseDown"
@keydown.space.prevent="toggleProfileList"
@keydown.enter.prevent="toggleProfileList"
>
<div
class="initial"
@ -20,6 +25,7 @@
@focusout="handleProfileListFocusOut"
>
<h3
id="profileListTitle"
class="profileListTitle"
>
{{ $t("Profile.Profile Select") }}
@ -31,12 +37,20 @@
/>
<div
class="profileWrapper"
role="listbox"
aria-labelledby="profileListTitle"
>
<div
v-for="(profile, index) in profileList"
:id="'profile-' + index"
:key="index"
class="profile"
:aria-labelledby="'profile-' + index + '-name'"
aria-selected="false"
tabindex="0"
role="option"
@click="setActiveProfile(profile)"
@keydown.enter.prevent="setActiveProfile(profile, $event)"
>
<div
class="colorOption"
@ -49,6 +63,7 @@
</div>
</div>
<p
:id="'profile-' + index + '-name'"
class="profileName"
>
{{ profile.name }}

View File

@ -85,6 +85,7 @@
role="tablist"
:aria-label="$t('Channel.Channel Tabs')"
>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="tabInfoValues.includes('videos')"
id="videosTab"
@ -99,6 +100,7 @@
>
{{ $t("Channel.Videos.Videos").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="tabInfoValues.includes('shorts') && !hideChannelShorts"
id="shortsTab"
@ -113,6 +115,7 @@
>
{{ $t("Global.Shorts").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="tabInfoValues.includes('live') && !hideLiveStreams"
id="liveTab"
@ -127,6 +130,7 @@
>
{{ $t("Channel.Live.Live").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="tabInfoValues.includes('releases') && !hideChannelReleases"
id="releasesTab"
@ -141,6 +145,7 @@
>
{{ $t("Channel.Releases.Releases").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="tabInfoValues.includes('podcasts') && !hideChannelPodcasts"
id="podcastsTab"
@ -155,6 +160,7 @@
>
{{ $t("Channel.Podcasts.Podcasts").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="tabInfoValues.includes('playlists') && !hideChannelPlaylists"
id="playlistsTab"
@ -169,6 +175,7 @@
>
{{ $t("Channel.Playlists.Playlists").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="tabInfoValues.includes('community') && !hideChannelCommunity"
id="communityTab"
@ -183,6 +190,7 @@
>
{{ $t("Channel.Community.Community").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
id="aboutTab"
class="tab"

View File

@ -7,6 +7,7 @@
role="tablist"
:aria-label="$t('Subscriptions.Subscriptions Tabs')"
>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="!hideSubscriptionsVideos"
ref="videos"
@ -22,6 +23,7 @@
>
{{ $t("Global.Videos").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="!hideSubscriptionsShorts"
ref="shorts"
@ -37,6 +39,7 @@
>
{{ $t("Global.Shorts").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
v-if="!hideSubscriptionsLive"
ref="live"

View File

@ -14,6 +14,7 @@
role="tablist"
:aria-label="$t('Trending.Trending Tabs')"
>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
ref="default"
class="tab"
@ -29,6 +30,7 @@
>
{{ $t("Trending.Default").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
ref="music"
class="tab"
@ -44,6 +46,7 @@
>
{{ $t("Trending.Music").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
ref="gaming"
class="tab"
@ -59,6 +62,7 @@
>
{{ $t("Trending.Gaming").toUpperCase() }}
</div>
<!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
<div
ref="movies"
class="tab"

View File

@ -489,6 +489,7 @@ About:
Profile:
Profile Settings: Profile Settings
Toggle Profile List: Toggle Profile List
Profile Select: Profile Select
Profile Filter: Profile Filter
All Channels: All Channels