@@ -348,6 +348,7 @@ export default {
348348 <aside id =" app-sidebar-vue"
349349 ref =" sidebar"
350350 class =" app-sidebar"
351+ :aria-labelledby =" `app-sidebar-vue-${uid}__header`"
351352 @keydown.esc.stop =" isMobile && closeSidebar()" >
352353 <header :class =" {
353354 'app-sidebar-header--with-figure': hasFigure,
@@ -403,11 +404,13 @@ export default {
403404 <div class =" app-sidebar-header__mainname-container" >
404405 <!-- main name -->
405406 <h2 v-show =" !nameEditable"
407+ :id =" `app-sidebar-vue-${uid}__header`"
408+ ref =" header"
406409 v-linkify =" {text: name, linkify: linkifyName}"
407410 :aria-label =" title"
408411 :title =" title"
409412 class =" app-sidebar-header__mainname"
410- :tabindex =" nameEditable ? 0 : undefined "
413+ :tabindex =" nameEditable ? 0 : -1 "
411414 @click.self =" editName" >
412415 {{ name }}
413416 </h2 >
@@ -492,6 +495,7 @@ import Focus from '../../directives/Focus/index.js'
492495import Linkify from ' ../../directives/Linkify/index.js'
493496import Tooltip from ' ../../directives/Tooltip/index.js'
494497import { useIsSmallMobile } from ' ../../composables/useIsMobile/index.js'
498+ import GenRandomId from ' ../../utils/GenRandomId.js'
495499import { getTrapStack } from ' ../../utils/focusTrap.js'
496500import { t } from ' ../../l10n.js'
497501
@@ -650,6 +654,7 @@ export default {
650654
651655 setup () {
652656 return {
657+ uid: GenRandomId (),
653658 isMobile: useIsSmallMobile (),
654659 }
655660 },
@@ -661,6 +666,7 @@ export default {
661666 favoriteTranslated: t (' Favorite' ),
662667 isStarred: this .starred ,
663668 focusTrap: null ,
669+ elementToReturnFocus: null ,
664670 }
665671 },
666672
@@ -686,7 +692,16 @@ export default {
686692 },
687693 },
688694
695+ created () {
696+ this .preserveElementToReturnFocus ()
697+ },
698+
689699 mounted () {
700+ // Focus sidebar on open only if it was opened by a user interaction
701+ if (this .elementToReturnFocus ) {
702+ this .focus ()
703+ }
704+
690705 this .toggleFocusTrap ()
691706 },
692707
@@ -697,6 +712,23 @@ export default {
697712 },
698713
699714 methods: {
715+ preserveElementToReturnFocus () {
716+ // Save the element that had focus before the sidebar was opened to return back on close
717+ if (document .activeElement && document .activeElement !== document .body ) {
718+ this .elementToReturnFocus = document .activeElement
719+
720+ // Special case for menus (NcActions)
721+ // If a sidebar was opened from a menu item, we want to return focus to the menu trigger instead of the item
722+ if (this .elementToReturnFocus .getAttribute (' role' ) === ' menuitem' ) {
723+ const menu = this .elementToReturnFocus .closest (' [role="menu"]' )
724+ if (menu) {
725+ const menuTrigger = document .querySelector (` [aria-controls="${ menu .id } "]` )
726+ this .elementToReturnFocus = menuTrigger
727+ }
728+ }
729+ }
730+ },
731+
700732 initFocusTrap () {
701733 if (this .focusTrap ) {
702734 return
@@ -721,7 +753,7 @@ export default {
721753 /**
722754 * Activate focus trap if it is currently needed, otherwise deactivate
723755 */
724- toggleFocusTrap () {
756+ toggleFocusTrap () {
725757 if (this .isMobile ) {
726758 this .initFocusTrap ()
727759 this .focusTrap .activate ()
@@ -761,6 +793,10 @@ export default {
761793 * @type {HTMLElement}
762794 */
763795 this .$emit (' closed' , element)
796+
797+ // Return focus to the element that had focus before the sidebar was opened
798+ this .elementToReturnFocus ? .focus ({ focusVisible: true })
799+ this .elementToReturnFocus = null
764800 },
765801
766802 /**
@@ -820,6 +856,25 @@ export default {
820856 }
821857 },
822858
859+ /**
860+ * Focus the sidebar
861+ * @public
862+ */
863+ focus () {
864+ this .$refs .header .focus ()
865+ },
866+
867+ /**
868+ * Focus the active tab
869+ * @public
870+ */
871+ focusActiveTabContent () {
872+ // If a tab is focused then probably a new trigger element moved the focus to the sidebar
873+ this .preserveElementToReturnFocus ()
874+
875+ this .$refs .tabs .focusActiveTabContent ()
876+ },
877+
823878 /**
824879 * Emit name change event to parent component
825880 *
0 commit comments