@@ -550,7 +550,8 @@ export default {
550550 As a simple solution - render it in the content to keep correct position.
551551 -->
552552 <Teleport v-if =" ncContentSelector && !open && !noToggle" :to =" ncContentSelector" >
553- <NcButton :aria-label =" t('Open sidebar')"
553+ <NcButton ref =" toggle"
554+ :aria-label =" t('Open sidebar')"
554555 class =" app-sidebar__toggle"
555556 :class =" toggleClasses"
556557 variant =" tertiary"
@@ -570,6 +571,12 @@ export default {
570571 'app-sidebar-header--compact': compact,
571572 }"
572573 class =" app-sidebar-header" >
574+ <!-- a11y fallback for empty content -->
575+ <NcAppSidebarHeader v-if =" empty"
576+ class =" app-sidebar-header__mainname--hidden"
577+ :name
578+ tabindex =" -1" />
579+
573580 <!-- container for figure and description, allows easy switching to compact mode -->
574581 <div class =" app-sidebar-header__info" >
575582 <!-- sidebar header illustration/figure -->
@@ -618,17 +625,13 @@ export default {
618625 <div class =" app-sidebar-header__name-container" >
619626 <div class =" app-sidebar-header__mainname-container" >
620627 <!-- main name -->
621- <h2 v-show =" !nameEditable"
622- :id =" `app-sidebar-vue-${uid}__header`"
623- ref =" header"
624- v-linkify =" {text: name, linkify: linkifyName}"
625- :aria-label =" title"
626- :title =" title"
628+ <NcAppSidebarHeader v-show =" !nameEditable"
627629 class =" app-sidebar-header__mainname"
630+ :name
631+ :linkify =" linkifyName"
632+ :title
628633 :tabindex =" nameEditable ? 0 : -1"
629- @click.self =" editName" >
630- {{ name }}
631- </h2 >
634+ @click.self =" editName" />
632635 <template v-if =" nameEditable " >
633636 <form v-click-outside =" () => onSubmitName()"
634637 class =" app-sidebar-header__mainname-form"
@@ -706,13 +709,14 @@ export default {
706709<script >
707710import NcAppSidebarTabs from ' ./NcAppSidebarTabs.vue'
708711import NcActions from ' ../NcActions/index.js'
712+ import NcAppSidebarHeader from ' ../NcAppSidebarHeader/index.ts'
709713import NcButton from ' ../NcButton/index.ts'
710714import NcEmptyContent from ' ../NcEmptyContent/index.js'
711715import NcLoadingIcon from ' ../NcLoadingIcon/index.js'
712716import Focus from ' ../../directives/Focus/index.js'
713- import Linkify from ' ../../directives/Linkify/index.ts'
714717import { vOnClickOutside as ClickOutside } from ' @vueuse/components'
715718import { createFocusTrap } from ' focus-trap'
719+ import { provide , ref , warn } from ' vue'
716720import { useIsSmallMobile } from ' ../../composables/useIsMobile/index.js'
717721import { createElementId } from ' ../../utils/createElementId.ts'
718722import { getTrapStack } from ' ../../utils/focusTrap.ts'
@@ -730,6 +734,7 @@ export default {
730734
731735 components: {
732736 NcActions,
737+ NcAppSidebarHeader,
733738 NcAppSidebarTabs,
734739 NcButton,
735740 NcLoadingIcon,
@@ -743,7 +748,6 @@ export default {
743748
744749 directives: {
745750 Focus,
746- Linkify,
747751 ClickOutside,
748752 },
749753
@@ -922,9 +926,13 @@ export default {
922926 ],
923927
924928 setup () {
929+ const headerRef = ref (null )
930+ provide (' NcAppSidebar:header:ref' , headerRef)
931+
925932 return {
926933 uid: createElementId (),
927934 isMobile: useIsSmallMobile (),
935+ headerRef,
928936 }
929937 },
930938
@@ -1135,7 +1143,16 @@ export default {
11351143 * @public
11361144 */
11371145 focus () {
1138- (this .$refs .header ?? this .$refs .toggle )? .focus ()
1146+ if (! this .open && ! this .noToggle ) {
1147+ this .$refs .toggle .$el .focus ()
1148+ return
1149+ }
1150+
1151+ try {
1152+ this .headerRef .focus ()
1153+ } catch {
1154+ warn (' NcAppSidebar should have focusable header for accessibility reasons. Use NcAppSidebarHeader component.' )
1155+ }
11391156 },
11401157
11411158 /**
@@ -1497,6 +1514,17 @@ $top-buttons-spacing: 6px;
14971514 }
14981515 }
14991516
1517+ // Hidden a11y fallback
1518+ .app - sidebar- header__mainname-- hidden {
1519+ position: absolute;
1520+ top: 0 ;
1521+ inset- inline- start: 0 ;
1522+ margin: 0 ;
1523+ width: 1px ;
1524+ height: 1px ;
1525+ overflow: hidden;
1526+ }
1527+
15001528 // sidebar description slot
15011529 & __description {
15021530 display: flex;
0 commit comments