import { defineComponent } from 'vue';
+import { DEFAULT_FOCUS_TRAP_OPTS, useBasicSetupFocusTrap } from '@shell/composables/focusTrap';
export default defineComponent({
name: 'AppModal',
@@ -56,6 +57,20 @@ export default defineComponent({
name: {
type: String,
default: '',
+ },
+ /**
+ * trigger focus trap
+ */
+ triggerFocusTrap: {
+ type: Boolean,
+ default: false,
+ },
+ /**
+ * forcefully set return focus element
+ */
+ returnFocus: {
+ type: String,
+ default: '',
}
},
computed: {
@@ -85,6 +100,19 @@ export default defineComponent({
};
}
},
+ setup(props) {
+ if (props.triggerFocusTrap) {
+ let opts:any = DEFAULT_FOCUS_TRAP_OPTS;
+
+ if (props.returnFocus) {
+ opts = {
+ ...DEFAULT_FOCUS_TRAP_OPTS,
+ setReturnFocus: props.returnFocus
+ };
+ }
+ useBasicSetupFocusTrap('#modal-container-element', opts);
+ }
+ },
mounted() {
document.addEventListener('keydown', this.handleEscapeKey);
},
@@ -134,6 +162,7 @@ export default defineComponent({
>
diff --git a/shell/components/Tabbed/index.vue b/shell/components/Tabbed/index.vue
index 25eb101fe3f..b0ee2d9f4e0 100644
--- a/shell/components/Tabbed/index.vue
+++ b/shell/components/Tabbed/index.vue
@@ -276,12 +276,11 @@ export default {
:data-testid="`btn-${tab.name}`"
:aria-controls="'#' + tab.name"
:aria-selected="tab.active"
- :aria-label="tab.labelDisplay"
+ :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)"
+ @keyup.enter.space="select(tab.name, $event)"
>
{{ tab.labelDisplay }}
{
+ focusEl = typeof focusElement === 'string' ? document.querySelector(focusElement) as HTMLElement : focusElement;
+
+ focusTrapInstance = createFocusTrap(focusEl, opts);
+
+ nextTick(() => {
+ focusTrapInstance.activate();
+ });
+ });
+
+ onBeforeUnmount(() => {
+ if (Object.keys(focusTrapInstance).length) {
+ focusTrapInstance.deactivate();
+ }
+ });
+}
+
+export function useWatcherBasedSetupFocusTrapWithDestroyIncluded(watchVar:any, focusElement: string | HTMLElement, opts:any = DEFAULT_FOCUS_TRAP_OPTS) {
+ let focusTrapInstance: FocusTrap;
+ let focusEl;
+
+ watch(watchVar, (neu) => {
+ if (neu) {
+ nextTick(() => {
+ focusEl = typeof focusElement === 'string' ? document.querySelector(focusElement) as HTMLElement : focusElement;
+
+ focusTrapInstance = createFocusTrap(focusEl, opts);
+
+ nextTick(() => {
+ focusTrapInstance.activate();
+ });
+ });
+ } else if (!neu && Object.keys(focusTrapInstance).length) {
+ focusTrapInstance.deactivate();
+ }
+ });
+}
+
+export function useWatcherBasedSetupFocusTrap(watchVar:any, focusElement: string | HTMLElement, opts:any = DEFAULT_FOCUS_TRAP_OPTS) {
+ let focusTrapInstance: FocusTrap;
+ let focusEl;
+
+ watch(watchVar, (neu) => {
+ if (neu) {
+ nextTick(() => {
+ focusEl = typeof focusElement === 'string' ? document.querySelector(focusElement) as HTMLElement : focusElement;
+
+ focusTrapInstance = createFocusTrap(focusEl, opts);
+ nextTick(() => {
+ focusTrapInstance.activate();
+ });
+ });
+ }
+ }, { immediate: true });
+
+ onBeforeUnmount(() => {
+ if (Object.keys(focusTrapInstance).length) {
+ focusTrapInstance.deactivate();
+ }
+ });
+}
diff --git a/shell/pages/c/_cluster/explorer/ConfigBadge.vue b/shell/pages/c/_cluster/explorer/ConfigBadge.vue
index 100d1b1bbc2..ad8fc81ccfb 100644
--- a/shell/pages/c/_cluster/explorer/ConfigBadge.vue
+++ b/shell/pages/c/_cluster/explorer/ConfigBadge.vue
@@ -24,9 +24,7 @@ export default {
-
+