From d05054a5fccf09e0b40b3873630d51125212d81b Mon Sep 17 00:00:00 2001 From: tugcekucukoglu Date: Fri, 17 Nov 2023 21:10:06 +0300 Subject: [PATCH] Fixed #4841 - TreeSelect: Accessibility Improvements --- components/lib/treeselect/TreeSelect.vue | 69 +++++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/components/lib/treeselect/TreeSelect.vue b/components/lib/treeselect/TreeSelect.vue index 56bf6d987..285e78178 100644 --- a/components/lib/treeselect/TreeSelect.vue +++ b/components/lib/treeselect/TreeSelect.vue @@ -43,8 +43,19 @@ - +
+
+
@@ -161,11 +183,15 @@ export default { this.$emit('blur', event); }, onClick(event) { + if (this.disabled) { + return; + } + if (!this.disabled && (!this.overlay || !this.overlay.contains(event.target))) { if (this.overlayVisible) this.hide(); else this.show(); - this.$refs.focusInput.focus(); + DomHandler.focus(this.$refs.focusInput); } }, onSelectionChange(keys) { @@ -186,6 +212,16 @@ export default { onNodeToggle(keys) { this.expandedKeys = keys; }, + onFirstHiddenFocus(event) { + const focusableEl = event.relatedTarget === this.$refs.focusInput ? DomHandler.getFirstFocusableElement(this.overlay, ':not([data-p-hidden-focusable="true"])') : this.$refs.focusInput; + + DomHandler.focus(focusableEl); + }, + onLastHiddenFocus(event) { + const focusableEl = event.relatedTarget === this.$refs.focusInput ? DomHandler.getLastFocusableElement(this.overlay, ':not([data-p-hidden-focusable="true"])') : this.$refs.focusInput; + + DomHandler.focus(focusableEl); + }, onKeyDown(event) { switch (event.code) { case 'ArrowDown': @@ -199,7 +235,10 @@ export default { case 'Escape': this.onEscapeKey(event); + break; + case 'Tab': + this.onTabKey(event); break; default: @@ -235,11 +274,30 @@ export default { event.preventDefault(); } }, + onTabKey(event, pressedInInputText = false) { + if (!pressedInInputText) { + if (this.overlayVisible && this.hasFocusableElements()) { + DomHandler.focus(this.$refs.firstHiddenFocusableElementOnOverlay); + + event.preventDefault(); + } else { + if (this.focusedOptionIndex !== -1) { + this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]); + } + } + } + }, + hasFocusableElements() { + return DomHandler.getFocusableElements(this.overlay, ':not([data-p-hidden-focusable="true"])').length > 0; + }, onOverlayEnter(el) { ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay); DomHandler.addStyles(el, { position: 'absolute', top: '0', left: '0' }); this.alignOverlay(); + this.focus(); + }, + onOverlayAfterEnter() { this.bindOutsideClickListener(); this.bindScrollListener(); this.bindResizeListener(); @@ -256,6 +314,13 @@ export default { onOverlayAfterLeave(el) { ZIndexUtils.clear(el); }, + focus() { + let focusableElements = DomHandler.getFocusableElements(this.overlay); + + if (focusableElements && focusableElements.length > 0) { + focusableElements[0].focus(); + } + }, alignOverlay() { if (this.appendTo === 'self') { DomHandler.relativePosition(this.overlay, this.$el);