diff --git a/pkg/rancher-components/src/components/Banner/Banner.vue b/pkg/rancher-components/src/components/Banner/Banner.vue index 24d172a21c0..8ca20a56701 100644 --- a/pkg/rancher-components/src/components/Banner/Banner.vue +++ b/pkg/rancher-components/src/components/Banner/Banner.vue @@ -67,6 +67,7 @@ export default defineComponent({ :class="{ [color]: true, }" + role="banner" > @@ -72,6 +77,11 @@ export default { .close-button { position: absolute; visibility: hidden; + + &:focus-visible { + @include focus-outline; + outline-offset: 2px; + } } &:hover .close-button { diff --git a/shell/components/ButtonMultiAction.vue b/shell/components/ButtonMultiAction.vue index a762013873b..c9992fa400b 100644 --- a/shell/components/ButtonMultiAction.vue +++ b/shell/components/ButtonMultiAction.vue @@ -33,6 +33,12 @@ const buttonClass = computed(() => { .borderless { background-color: transparent; border: none; + + &:focus-visible { + @include focus-outline; + outline-offset: -2px; + } + &:hover, &:focus { background-color: var(--accent-btn); box-shadow: none; diff --git a/shell/components/CommunityLinks.vue b/shell/components/CommunityLinks.vue index 70b39a2b61a..37c31532d6e 100644 --- a/shell/components/CommunityLinks.vue +++ b/shell/components/CommunityLinks.vue @@ -110,6 +110,8 @@ export default { {{ link.label }} @@ -118,6 +120,8 @@ export default { :href="link.value" rel="noopener noreferrer nofollow" target="_blank" + role="link" + :aria-label="link.label" > {{ link.label }} @@ -127,7 +131,11 @@ export default { > {{ t('footer.wechat.title') }} @@ -147,7 +155,12 @@ export default {
diff --git a/shell/components/SortableTable/THead.vue b/shell/components/SortableTable/THead.vue index c08e249dadc..8e215dad1ff 100644 --- a/shell/components/SortableTable/THead.vue +++ b/shell/components/SortableTable/THead.vue @@ -162,6 +162,14 @@ export default { return col.name === this.sortBy; }, + ariaSort(col) { + if (this.isCurrent(col)) { + return this.descending ? this.t('generic.descending') : this.t('generic.ascending'); + } + + return this.t('generic.none'); + }, + tableColsOptionsClick(ev) { // set menu position const menu = document.querySelector('.table-options-container'); @@ -235,7 +243,12 @@ export default { :align="col.align || 'left'" :width="col.width" :class="{ sortable: col.sort, [col.breakpoint]: !!col.breakpoint}" + :tabindex="col.sort ? 0 : -1" + class="sortable-table-head-element" + :aria-sort="ariaSort(col)" @click.prevent="changeSort($event, col)" + @keyup.enter="changeSort($event, col)" + @keyup.space="changeSort($event, col)" >
diff --git a/shell/components/SortableTable/selection.js b/shell/components/SortableTable/selection.js index c76b9db42d3..ebc979cdb33 100644 --- a/shell/components/SortableTable/selection.js +++ b/shell/components/SortableTable/selection.js @@ -1,3 +1,4 @@ +import { mapGetters } from 'vuex'; import { isMore, isRange, suppressContextMenu, isAlternate } from '@shell/utils/platform'; import { get } from '@shell/utils/object'; import { filterBy } from '@shell/utils/array'; @@ -29,6 +30,13 @@ export default { }, computed: { + ...mapGetters({ + // Use either these Vuex getters + // OR the props to set the action menu state, + // but don't use both. + targetElem: 'action-menu/elem', + shouldShow: 'action-menu/showing', + }), // Used for the table-level selection check-box to show checked (all selected)/intermediate (some selected)/unchecked (none selected) howMuchSelected() { const total = this.pagedRows.length; @@ -270,11 +278,17 @@ export default { } } - this.$store.commit(`action-menu/show`, { - resources, - event: e, - elem: actionElement - }); + if (!this.targetElem && !this.shouldShow) { + this.$store.commit(`action-menu/show`, { + resources, + event: e, + elem: actionElement + }); + } else if (this.targetElem === actionElement && this.shouldShow) { + // this condition is needed so that we can "toggle" the action menu with + // the keyboard for accessibility (row action menu) + this.$store.commit('action-menu/hide'); + } return; } diff --git a/shell/pages/home.vue b/shell/pages/home.vue index c9d3e16735e..058087f9279 100644 --- a/shell/pages/home.vue +++ b/shell/pages/home.vue @@ -504,16 +504,18 @@ export default defineComponent({ {{ t('landing.seeWhatsNew') }}
-
@@ -583,6 +589,9 @@ export default defineComponent({ :to="manageLocation" class="btn btn-sm role-secondary" data-testid="cluster-management-manage-button" + role="button" + :aria-label="t('cluster.manageAction')" + @keyup.space="$router.push(manageLocation)" > {{ t('cluster.manageAction') }} @@ -591,6 +600,9 @@ export default defineComponent({ :to="importLocation" class="btn btn-sm role-primary" data-testid="cluster-create-import-button" + role="button" + :aria-label="t('cluster.importAction')" + @keyup.space="$router.push(importLocation)" > {{ t('cluster.importAction') }} @@ -599,6 +611,9 @@ export default defineComponent({ :to="createLocation" class="btn btn-sm role-primary" data-testid="cluster-create-button" + role="button" + :aria-label="t('generic.create')" + @keyup.space="$router.push(createLocation)" > {{ t('generic.create') }} @@ -614,6 +629,8 @@ export default defineComponent({ {{ row.nameDisplay }} @@ -687,6 +704,10 @@ export default defineComponent({