mirror of
https://github.com/FreeTubeApp/FreeTube
synced 2024-11-05 10:12:38 +01:00
Make profiles keyboard accessible (#3863)
Co-authored-by: Jason <84899178+jasonhenriquez@users.noreply.github.com>
This commit is contained in:
parent
ebf7e9985f
commit
2d934eabea
@ -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',
|
||||
|
@ -10,10 +10,12 @@
|
||||
<div class="channelThumbnail">
|
||||
<router-link
|
||||
:to="`/channel/${id}`"
|
||||
tabindex="-1"
|
||||
>
|
||||
<img
|
||||
:src="thumbnail"
|
||||
class="channelImage"
|
||||
alt=""
|
||||
>
|
||||
</router-link>
|
||||
</div>
|
||||
|
@ -22,6 +22,7 @@
|
||||
<img
|
||||
:src="thumbnail"
|
||||
class="thumbnailImage"
|
||||
alt=""
|
||||
>
|
||||
</router-link>
|
||||
<div
|
||||
|
@ -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}`
|
||||
})
|
||||
|
@ -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>
|
||||
|
@ -15,6 +15,7 @@
|
||||
:channel-name="channel.name"
|
||||
:channel-thumbnail="channel.thumbnail"
|
||||
:show-selected="true"
|
||||
role="button"
|
||||
@click="handleChannelClick(index)"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
|
@ -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
|
||||
|
@ -24,6 +24,7 @@
|
||||
:channel-name="channel.name"
|
||||
:channel-thumbnail="channel.thumbnail"
|
||||
:show-selected="true"
|
||||
role="button"
|
||||
@click="handleChannelClick(index)"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
|
@ -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 }}
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user