From eba3c70c9bef683382a092ec4cf0164a36a08617 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Sun, 10 Oct 2021 16:24:12 +0200 Subject: [PATCH] Various accessibility improvements * Add announcement element with `aria-live` * Add skip to main content element Signed-off-by: Thomas Citharel --- js/package.json | 2 + js/src/App.vue | 48 ++++++- js/src/common.scss | 20 +++ .../components/Account/ProfileOnboarding.vue | 4 +- js/src/components/Comment/Comment.vue | 1 + js/src/components/Comment/CommentTree.vue | 9 +- .../Discussion/DiscussionComment.vue | 2 +- js/src/components/Editor.vue | 9 ++ js/src/components/Error.vue | 8 +- .../components/Event/AddressAutoComplete.vue | 1 + .../components/Event/EventMetadataSidebar.vue | 20 +-- .../components/Event/ParticipationButton.vue | 36 ++++-- js/src/components/Footer.vue | 21 +++- js/src/components/NavBar.vue | 22 +++- .../Participation/ConfirmParticipation.vue | 8 +- .../ParticipationWithAccount.vue | 5 + .../ParticipationWithoutAccount.vue | 5 + .../Participation/UnloggedParticipation.vue | 5 + js/src/components/PictureUpload.vue | 7 +- js/src/main.ts | 4 + js/src/router/actor.ts | 13 +- js/src/router/discussion.ts | 17 ++- js/src/router/error.ts | 4 + js/src/router/event.ts | 50 ++++++-- js/src/router/groups.ts | 27 ++-- js/src/router/index.ts | 56 +++++++-- js/src/router/settings.ts | 117 ++++++++++++++---- js/src/router/user.ts | 47 +++++-- js/src/types/event.model.ts | 6 +- js/src/views/About.vue | 49 ++++---- js/src/views/About/AboutInstance.vue | 14 +-- js/src/views/Admin/AdminProfile.vue | 8 ++ js/src/views/Admin/AdminUserProfile.vue | 8 ++ js/src/views/Admin/Follows.vue | 5 + js/src/views/Discussions/Create.vue | 2 +- js/src/views/Discussions/Discussion.vue | 2 +- js/src/views/Event/Edit.vue | 5 +- js/src/views/Event/Event.vue | 12 ++ js/src/views/Event/Participants.vue | 27 +++- js/src/views/Group/Group.vue | 3 +- js/src/views/Group/GroupSettings.vue | 6 +- js/src/views/Group/Settings.vue | 5 + js/src/views/Home.vue | 3 + js/src/views/Moderation/Logs.vue | 5 + js/src/views/Moderation/ReportList.vue | 5 + js/src/views/Posts/Edit.vue | 2 +- js/src/views/Posts/List.vue | 10 +- js/src/views/Resources/ResourceFolder.vue | 1 + js/src/views/Settings/Notifications.vue | 20 ++- js/src/views/Settings/Preferences.vue | 3 +- js/src/views/Todos/Todo.vue | 8 ++ js/src/views/Todos/TodoList.vue | 8 ++ js/src/views/Todos/TodoLists.vue | 10 ++ js/src/views/User/EmailValidate.vue | 8 +- js/src/views/User/PasswordReset.vue | 8 +- js/src/views/User/ProviderValidation.vue | 8 +- js/src/views/User/Register.vue | 4 +- js/src/views/User/ResendConfirmation.vue | 8 +- js/src/views/User/SendPasswordReset.vue | 8 +- js/src/views/User/SettingsOnboard.vue | 5 + js/src/views/User/Validate.vue | 8 +- js/yarn.lock | 10 ++ 62 files changed, 687 insertions(+), 175 deletions(-) diff --git a/js/package.json b/js/package.json index 7b3fc2b9f..9e38573ef 100644 --- a/js/package.json +++ b/js/package.json @@ -29,6 +29,8 @@ "@tiptap/extension-underline": "^2.0.0-beta.7", "@tiptap/starter-kit": "^2.0.0-beta.37", "@tiptap/vue-2": "^2.0.0-beta.21", + "@vue-a11y/announcer": "^2.1.0", + "@vue-a11y/skip-to": "^2.1.2", "@vue/apollo-option": "4.0.0-alpha.11", "apollo-absinthe-upload-link": "^1.5.0", "blurhash": "^1.1.3", diff --git a/js/src/App.vue b/js/src/App.vue index f9818269d..bcda04912 100644 --- a/js/src/App.vue +++ b/js/src/App.vue @@ -1,5 +1,7 @@ @@ -218,4 +256,8 @@ $mdi-font-path: "~@mdi/font/fonts"; flex-grow: 1; } } + +.vue-skip-to { + z-index: 40; +} diff --git a/js/src/common.scss b/js/src/common.scss index 004ddb1b4..66979923b 100644 --- a/js/src/common.scss +++ b/js/src/common.scss @@ -135,3 +135,23 @@ a.list-item { font-size: 1.25rem; } } + +@mixin focus() { + &:focus { + border: 2px solid black; + border-radius: 5px; + } +} + +ul.menu-list > li, +p { + @include focus; +} +.navbar-item { + @include focus; +} + +.navbar-dropdown span.navbar-item:hover { + background-color: whitesmoke; + color: #0a0a0a; +} diff --git a/js/src/components/Account/ProfileOnboarding.vue b/js/src/components/Account/ProfileOnboarding.vue index 43448fc1b..bba073384 100644 --- a/js/src/components/Account/ProfileOnboarding.vue +++ b/js/src/components/Account/ProfileOnboarding.vue @@ -11,7 +11,7 @@ ) }}

-
+

{{ @@ -33,7 +33,7 @@ " />

-
+

{{ $t( diff --git a/js/src/components/Comment/Comment.vue b/js/src/components/Comment/Comment.vue index 14d0a9be3..33fd0cc92 100644 --- a/js/src/components/Comment/Comment.vue +++ b/js/src/components/Comment/Comment.vue @@ -137,6 +137,7 @@ ref="commentEditor" v-model="newComment.text" mode="comment" + :aria-label="$t('Comment body')" />

@@ -30,9 +31,11 @@

- {{ - $t("Notify participants") - }} + {{ $t("Notify participants") }}
diff --git a/js/src/components/Discussion/DiscussionComment.vue b/js/src/components/Discussion/DiscussionComment.vue index c3d27c968..3dd5706e6 100644 --- a/js/src/components/Discussion/DiscussionComment.vue +++ b/js/src/components/Discussion/DiscussionComment.vue @@ -88,7 +88,7 @@ {{ $t("[This comment has been deleted by it's author]") }}
- +
- {{ - $t("Copy details to clipboard") - }} + {{ $t("Copy details to clipboard") }}
diff --git a/js/src/components/Event/AddressAutoComplete.vue b/js/src/components/Event/AddressAutoComplete.vue index a3c806801..886c3fa13 100644 --- a/js/src/components/Event/AddressAutoComplete.vue +++ b/js/src/components/Event/AddressAutoComplete.vue @@ -31,6 +31,7 @@ v-if="!gettingLocation" icon-right="target" @click="locateMe" + @keyup.enter="locateMe" >{{ $t("Use my location") }} {{ $t("Getting location") }} diff --git a/js/src/components/Event/EventMetadataSidebar.vue b/js/src/components/Event/EventMetadataSidebar.vue index af567ee76..912038d6d 100644 --- a/js/src/components/Event/EventMetadataSidebar.vue +++ b/js/src/components/Event/EventMetadataSidebar.vue @@ -7,25 +7,15 @@
{{ $t("No address defined") }}
-
-
-

- {{ physicalAddress.poiInfos.name }} -

-

- {{ physicalAddress.poiInfos.alternativeName }} -

-
-
- + {{ $t("Show map") }} + {{ $t("Show map") }} +
diff --git a/js/src/components/Event/ParticipationButton.vue b/js/src/components/Event/ParticipationButton.vue index c19a30ccf..65c44041f 100644 --- a/js/src/components/Event/ParticipationButton.vue +++ b/js/src/components/Event/ParticipationButton.vue @@ -30,18 +30,22 @@ A button to set your participation position="is-bottom-left" v-if="participation && participation.role === ParticipantRole.PARTICIPANT" > - + {{ $t("Cancel my participation…") }} @@ -73,6 +77,7 @@ A button to set your participation :value="false" aria-role="listitem" @click="confirmLeave" + @keyup.enter="confirmLeave" class="has-text-danger" >{{ $t("Cancel my participation request…") }} @@ -101,17 +106,21 @@ A button to set your participation position="is-bottom-left" v-else-if="!participation && currentActor.id" > - +
@@ -136,6 +145,7 @@ A button to set your participation :value="false" aria-role="listitem" @click="joinModal" + @keyup.enter="joinModal" v-if="identities.length > 1" >{{ $t("with another identity…") }} diff --git a/js/src/components/Footer.vue b/js/src/components/Footer.vue index b64546566..a38792dbd 100644 --- a/js/src/components/Footer.vue +++ b/js/src/components/Footer.vue @@ -25,7 +25,12 @@ v-model="locale" :placeholder="$t('Select a language')" > - @@ -48,6 +53,9 @@ {{ $t("License") }} +
  • + {{ $t("Back to top") }} +
  • diff --git a/js/src/views/Group/Group.vue b/js/src/views/Group/Group.vue index 8a867ca1d..2cde993c2 100644 --- a/js/src/views/Group/Group.vue +++ b/js/src/views/Group/Group.vue @@ -203,6 +203,7 @@ @@ -224,7 +225,7 @@ {{ $t("ICS/WebCal Feed") }} - + - @@ -259,6 +260,7 @@
    @@ -297,6 +299,7 @@
    = { total: 0, elements: [] }; diff --git a/js/src/views/Moderation/ReportList.vue b/js/src/views/Moderation/ReportList.vue index 928e19c35..bce76169d 100644 --- a/js/src/views/Moderation/ReportList.vue +++ b/js/src/views/Moderation/ReportList.vue @@ -111,6 +111,11 @@ const REPORT_PAGE_LIMIT = 10; pollInterval: 120000, // 2 minutes }, }, + metaInfo() { + return { + title: this.$t("Reports") as string, + }; + }, }) export default class ReportList extends Vue { reports?: Paginate = { elements: [], total: 0 }; diff --git a/js/src/views/Posts/Edit.vue b/js/src/views/Posts/Edit.vue index 899dc3d72..91bf702b9 100644 --- a/js/src/views/Posts/Edit.vue +++ b/js/src/views/Posts/Edit.vue @@ -72,7 +72,7 @@

    {{ errors.body }}

    - +
    {{ $t("Who can view this post") }}
    diff --git a/js/src/views/Posts/List.vue b/js/src/views/Posts/List.vue index 85288374e..14d87b781 100644 --- a/js/src/views/Posts/List.vue +++ b/js/src/views/Posts/List.vue @@ -127,11 +127,13 @@ const POSTS_PAGE_LIMIT = 10; PostElementItem, }, metaInfo() { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const { group } = this; return { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - title: this.$t("My groups") as string, - titleTemplate: "%s | Mobilizon", + title: this.$t("{group} posts", { + group: group.name || usernameWithDomain(group), + }) as string, }; }, }) diff --git a/js/src/views/Resources/ResourceFolder.vue b/js/src/views/Resources/ResourceFolder.vue index 360c85892..c830327b4 100644 --- a/js/src/views/Resources/ResourceFolder.vue +++ b/js/src/views/Resources/ResourceFolder.vue @@ -58,6 +58,7 @@ {{ $t("New link") }} diff --git a/js/src/views/Settings/Notifications.vue b/js/src/views/Settings/Notifications.vue index adb60576c..cf3abb3a5 100644 --- a/js/src/views/Settings/Notifications.vue +++ b/js/src/views/Settings/Notifications.vue @@ -18,12 +18,16 @@

    {{ $t("Browser notifications") }}

    - {{ - $t("Unsubscribe to browser push notifications") - }} + {{ $t("Unsubscribe to browser push notifications") }} {{ $t("Activate browser push notifications") }} @@ -247,6 +251,9 @@ @click=" (e) => copyURL(e, tokenToURL(feedToken.token, 'atom'), 'atom') " + @keyup.enter=" + (e) => copyURL(e, tokenToURL(feedToken.token, 'atom'), 'atom') + " :href="tokenToURL(feedToken.token, 'atom')" target="_blank" >{{ $t("RSS/Atom Feed") }}{{ $t("Regenerate new links") }}
    @@ -283,6 +294,7 @@ icon-left="refresh" type="is-text" @click="generateFeedTokens" + @keyup.enter="generateFeedTokens" >{{ $t("Create new links") }} @@ -333,7 +345,7 @@ type NotificationType = { label: string; subtypes: NotificationSubType[] }; }, metaInfo() { return { - title: this.$t("Notifications") as string, + title: this.$t("Notification settings") as string, }; }, }) diff --git a/js/src/views/Settings/Preferences.vue b/js/src/views/Settings/Preferences.vue index 521ed247a..95543b864 100644 --- a/js/src/views/Settings/Preferences.vue +++ b/js/src/views/Settings/Preferences.vue @@ -61,7 +61,7 @@ {{ $t("Unable to detect timezone.") }} -
    +
    { const accessToken = this.getValueFromMeta("auth-access-token"); diff --git a/js/src/views/User/Register.vue b/js/src/views/User/Register.vue index 8d8b10ccb..a1638a75d 100644 --- a/js/src/views/User/Register.vue +++ b/js/src/views/User/Register.vue @@ -59,7 +59,7 @@ {{ $t("Learn more") }} -
    +
    {{ $t("About {instance}", { instance: config.name }) @@ -170,7 +170,7 @@ >

    -
    +