Skip to content

Commit

Permalink
keyboard navigation for cluster badge appearance modal (#13021)
Browse files Browse the repository at this point in the history
* working on key nav for cluster badge appearance

* color input is now key nav friendly + tooltip works on focus + trying to get focus trap to work properly

* remove console logs + add focus trap to card component with prop control + fix element for config badge button

* fix lint problem

* fix TS errors on pkg build

* remove step of building the skeleton app in the check-plugins-build step, which imo doesnt serve any purpose whatsoever

* add focus-trap as a shell dependency + revert publish script change

* remove focus-trap directive + improve chaining event handler modifiers

* pin focus-trap to 7.6.2 + replace link for button on cluster explorer main page + remove unused ev

* address pr comments
  • Loading branch information
aalves08 authored Jan 24, 2025
1 parent 9985ce0 commit 1349648
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 21 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"express": "4.17.1",
"file-saver": "2.0.2",
"floating-vue": "5.2.2",
"focus-trap": "7.6.2",
"https": "1.0.0",
"identicon.js": "2.3.3",
"intl-messageformat": "7.8.4",
Expand Down Expand Up @@ -178,6 +179,7 @@
"eslint-plugin-cypress": "2.12.1",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-jest": "24.4.0",
"eslint-plugin-local-rules": "link:./eslint-plugin-local-rules",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-vue": "9.10.0",
"eslint": "7.32.0",
Expand All @@ -197,8 +199,7 @@
"webpack-virtual-modules": "0.4.3",
"worker-loader": "3.0.8",
"yaml-lint": "1.7.0",
"yarn": "1.22.18",
"eslint-plugin-local-rules": "link:./eslint-plugin-local-rules"
"yarn": "1.22.18"
},
"resolutions": {
"html-webpack-plugin": "^5.0.0"
Expand Down
28 changes: 27 additions & 1 deletion pkg/rancher-components/src/components/Card/Card.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { defineComponent, PropType } from 'vue';
import { createFocusTrap, FocusTrap } from 'focus-trap';
export default defineComponent({
name: 'Card',
Expand Down Expand Up @@ -50,12 +51,37 @@ export default defineComponent({
type: Boolean,
default: false,
},
}
triggerFocusTrap: {
type: Boolean,
default: false,
},
},
data() {
return { focusTrapInstance: {} as FocusTrap };
},
mounted() {
if (this.triggerFocusTrap) {
this.focusTrapInstance = createFocusTrap(this.$refs.cardContainer as HTMLElement, {
escapeDeactivates: true,
allowOutsideClick: true,
});
this.$nextTick(() => {
this.focusTrapInstance.activate();
});
}
},
beforeUnmount() {
if (this.focusTrapInstance && this.triggerFocusTrap) {
this.focusTrapInstance.deactivate();
}
},
});
</script>

<template>
<div
ref="cardContainer"
class="card-container"
:class="{'highlight-border': showHighlightBorder, 'card-sticky': sticky}"
data-testid="card"
Expand Down
11 changes: 9 additions & 2 deletions pkg/rancher-components/src/components/Form/Checkbox/Checkbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -264,13 +264,15 @@ export default defineComponent({
<template v-else-if="label">{{ label }}</template>
<i
v-if="tooltipKey"
v-clean-tooltip="t(tooltipKey)"
v-clean-tooltip="{content: t(tooltipKey), triggers: ['hover', 'touch', 'focus']}"
class="checkbox-info icon icon-info icon-lg"
:tabindex="isDisabled ? -1 : 0"
/>
<i
v-else-if="tooltip"
v-clean-tooltip="tooltip"
v-clean-tooltip="{content: tooltip, triggers: ['hover', 'touch', 'focus']}"
class="checkbox-info icon icon-info icon-lg"
:tabindex="isDisabled ? -1 : 0"
/>
</slot>
</span>
Expand Down Expand Up @@ -329,6 +331,11 @@ $fontColor: var(--input-label);
.checkbox-info {
line-height: normal;
margin-left: 2px;
&:focus-visible {
@include focus-outline;
outline-offset: 2px;
}
}
.checkbox-custom {
Expand Down
5 changes: 5 additions & 0 deletions shell/assets/styles/global/_button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ button,
color: var(--link);
box-shadow: none;
}

&:focus-visible {
@include focus-outline;
outline-offset: 2px;
}
}

.role-multi-action {
Expand Down
1 change: 1 addition & 0 deletions shell/assets/translations/en-us.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ generic:
back: Back
cancel: Cancel
confirm: Confirm
colorPicker: Color picker
clear: Clear
clearAll: Clear All
close: Close
Expand Down
13 changes: 12 additions & 1 deletion shell/components/Tabbed/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ export default {
role="tablist"
class="tabs"
:class="{'clearfix':!sideTabs, 'vertical': sideTabs, 'horizontal': !sideTabs}"
tabindex="0"
data-testid="tabbed-block"
@keydown.right.prevent="selectNext(1)"
@keydown.left.prevent="selectNext(-1)"
Expand All @@ -277,8 +276,12 @@ export default {
:data-testid="`btn-${tab.name}`"
:aria-controls="'#' + tab.name"
:aria-selected="tab.active"
:aria-label="tab.labelDisplay"
role="tab"
tabindex="0"
@click.prevent="select(tab.name, $event)"
@keyup.enter="select(tab.name, $event)"
@keyup.space="select(tab.name, $event)"
>
<span>{{ tab.labelDisplay }}</span>
<span
Expand Down Expand Up @@ -403,6 +406,14 @@ export default {
text-decoration: underline;
}
}
&:focus-visible {
@include focus-outline;
span {
text-decoration: underline;
}
}
}
.conditions-alert-icon {
Expand Down
25 changes: 24 additions & 1 deletion shell/components/form/ColorInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,21 @@ export default {
mounted() {
// Ensures that if the default value is used, the model is updated with it
this.$emit('update:value', this.inputValue);
}
},
methods: {
handleKeyup(ev) {
if (this.isDisabled) {
return '';
}
return this.$refs.input.click(ev);
}
},
// according to https://www.w3.org/TR/html-aria/
// input type="color" has no applicable role
// and only aria-label and aria-disabled
};
</script>

Expand All @@ -82,6 +96,8 @@ export default {
class="color-input"
:class="{[mode]:mode, disabled: isDisabled}"
:data-testid="componentTestid + '-color-input'"
:tabindex="isDisabled ? -1 : 0"
@keyup.enter.space.stop="handleKeyup($event)"
>
<label class="text-label"><t
v-if="labelKey"
Expand All @@ -99,8 +115,11 @@ export default {
>
<input
ref="input"
:aria-disabled="isDisabled ? 'true' : 'false'"
:aria-label="t('generic.colorPicker')"
type="color"
:disabled="isDisabled"
tabindex="-1"
:value="inputValue"
@input="$emit('update:value', $event.target.value)"
>
Expand All @@ -116,6 +135,10 @@ export default {
border-radius: var(--border-radius);
padding: 10px;
&:focus-visible {
@include focus-outline;
}
&.disabled, &.disabled .selected, &[disabled], &[disabled]:hover {
color: var(--input-disabled-text);
background-color: var(--input-disabled-bg);
Expand Down
6 changes: 5 additions & 1 deletion shell/dialog/AddCustomBadgeDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ export default {
<Card
class="prompt-badge"
:show-highlight-border="false"
:trigger-focus-trap="true"
>
<template #title>
<h4 class="text-default-text">
Expand Down Expand Up @@ -258,7 +259,6 @@ export default {
<Checkbox
v-model:value="badgeAsIcon"
:label="t('clusterBadge.modal.badgeAsIcon')"
:tooltip="t('clusterBadge.modal.maxCharsTooltip')"
/>
Expand Down Expand Up @@ -312,14 +312,18 @@ export default {
/>
<div class="buttons">
<button
role="button"
class="btn role-secondary mr-10"
:aria-label="t('generic.cancel')"
@click="close"
>
{{ t('generic.cancel') }}
</button>
<AsyncButton
:action-label="t('clusterBadge.modal.buttonAction')"
:disabled="!canSubmit"
role="button"
:aria-label="t('generic.cancel')"
@click="apply"
/>
</div>
Expand Down
1 change: 1 addition & 0 deletions shell/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"express": "4.17.1",
"file-saver": "2.0.2",
"floating-vue": "5.2.2",
"focus-trap": "7.6.2",
"frontmatter-markdown-loader": "3.7.0",
"identicon.js": "2.3.3",
"intl-messageformat": "7.8.4",
Expand Down
15 changes: 8 additions & 7 deletions shell/pages/c/_cluster/explorer/ConfigBadge.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,23 @@ export default {
</script>

<template>
<div class="config-badge">
<div
class="config-badge"
>
<div>
<a
<button
class="badge-install btn btn-sm role-secondary"
data-testid="add-custom-cluster-badge"
role="button"
tabindex="0"
@click="customBadgeDialog"
@keyup.space="customBadgeDialog"
>
<i
v-clean-tooltip="tooltip"
class="icon icon-brush-icon"
/>
</a>
</button>
</div>
</div>
</template>
Expand All @@ -55,10 +60,6 @@ export default {
> I {
line-height: inherit;
}
&:focus {
outline: 0;
}
}
</style>
19 changes: 13 additions & 6 deletions shell/pages/c/_cluster/explorer/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -641,12 +641,14 @@ export default {
<div data-testid="clusterProvider__label">
<label>{{ t('glance.provider') }}: </label>
<span v-if="isHarvesterCluster">
<a
<button
class="btn role-link harvester-cluster-link"
role="button"
:aria-label="displayProvider"
@click="goToHarvesterCluster"
>
{{ displayProvider }}
</a>
</button>
</span>
<span v-else>
{{ displayProvider }}
Expand Down Expand Up @@ -682,6 +684,8 @@ export default {
<router-link
:to="{name: 'c-cluster-explorer-tools'}"
class="cluster-tools-link"
role="link"
:aria-label="t('nav.clusterTools')"
>
<span>{{ t('nav.clusterTools') }}</span>
</router-link>
Expand Down Expand Up @@ -871,6 +875,13 @@ export default {
grid-row-gap: 20px;
}
.harvester-cluster-link {
line-height: inherit;
min-height: inherit;
padding: 0;
vertical-align: bottom;
}
@media only screen and (max-width: map-get($breakpoints, "--viewport-9")) {
.extension-card-container {
grid-template-columns: 1fr !important;
Expand Down Expand Up @@ -935,10 +946,6 @@ export default {
line-height: inherit;
margin-right: 4px;
}
&:focus {
outline: 0;
}
}
.cert-table-link {
Expand Down
2 changes: 2 additions & 0 deletions shell/scripts/test-plugins-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ if [ "${SKIP_STANDALONE}" == "false" ]; then
pushd test-app > /dev/null

yarn install
# this is the "same" as doing a yarn dev (in a build sense)
# it's to make sure the dev environment is running properly
FORCE_COLOR=true yarn build | cat

# Add test list component to the test package
Expand Down
12 changes: 12 additions & 0 deletions shell/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8025,6 +8025,13 @@ [email protected]:
"@floating-ui/dom" "~1.1.1"
vue-resize "^2.0.0-alpha.1"

[email protected]:
version "7.6.2"
resolved "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.2.tgz#a501988821ca23d0150a7229eb7a20a3695bdf0e"
integrity sha512-9FhUxK1hVju2+AiQIDJ5Dd//9R2n2RAfJ0qfhF4IHGHgcoEUTMpbTeG/zbEuwaiYXfuAH6XE0/aCyxDdRM+W5w==
dependencies:
tabbable "^6.2.0"

[email protected], follow-redirects@^1.0.0, follow-redirects@^1.14.0:
version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
Expand Down Expand Up @@ -13117,6 +13124,11 @@ symbol-tree@^3.2.4:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==

tabbable@^6.2.0:
version "6.2.0"
resolved "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97"
integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==

table@^6.0.9:
version "6.8.2"
resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58"
Expand Down
Loading

0 comments on commit 1349648

Please sign in to comment.