1- import { defineComponent , h , onBeforeUnmount , onMounted , ref } from 'vue'
1+ import { defineComponent , h , onBeforeUnmount , onMounted , onUpdated , ref , watch } from 'vue'
2+ import { CBackdrop } from '../backdrop'
23
34const CSidebar = defineComponent ( {
45 name : 'CSidebar' ,
@@ -66,16 +67,22 @@ const CSidebar = defineComponent({
6667 /**
6768 * Toggle the visibility of sidebar component.
6869 */
69- visible : {
70- type : Boolean ,
71- default : undefined ,
72- } ,
70+ visible : Boolean ,
7371 } ,
7472 emits : [ 'visible-change' ] ,
75- setup ( props , { slots, emit } ) {
73+ setup ( props , { attrs, slots, emit } ) {
74+ const mobile = ref ( )
75+ const inViewport = ref ( )
7676 const sidebarRef = ref ( )
7777 const visible = ref ( )
7878
79+ const handleClick = ( event : Event ) => {
80+ const target = event . target as HTMLElement
81+ target . closest ( 'a.nav-link:not(.nav-group-toggle)' )
82+ ? ( visible . value = false )
83+ : ( visible . value = true )
84+ }
85+
7986 const options = {
8087 rootMargin : '0px' ,
8188 threshold : 1.0 ,
@@ -86,22 +93,44 @@ const CSidebar = defineComponent({
8693 onMounted ( ( ) => {
8794 const callback = ( entries : IntersectionObserverEntry [ ] ) => {
8895 entries . forEach ( ( entry ) => {
89- if ( entry . isIntersecting !== props . visible || typeof visible . value === 'undefined' ) {
90- visible . value = entry . isIntersecting
91- emit ( 'visible-change' , visible . value )
92- }
96+ inViewport . value = entry . isIntersecting
97+ emit ( 'visible-change' , entry . isIntersecting )
9398 } )
9499 }
95100
96101 observer = new IntersectionObserver ( callback , options )
97102 observer . observe ( sidebarRef . value )
103+
104+ mobile . value = Boolean ( getComputedStyle ( sidebarRef . value ) . getPropertyValue ( '--cui-is-mobile' ) )
105+ } )
106+
107+ onUpdated ( ( ) => {
108+ mobile . value = Boolean ( getComputedStyle ( sidebarRef . value ) . getPropertyValue ( '--cui-is-mobile' ) )
109+
110+ if ( mobile . value ) {
111+ window . addEventListener ( 'click' , handleClick )
112+ } else {
113+ window . removeEventListener ( 'click' , handleClick )
114+ }
98115 } )
99116
100117 onBeforeUnmount ( ( ) => {
101118 observer . disconnect ( )
102119 } )
103120
104- return ( ) =>
121+ watch (
122+ ( ) => props . visible ,
123+ ( ) => {
124+ if ( props . visible === true && inViewport . value === false ) {
125+ visible . value = true
126+ }
127+ if ( props . visible === false && inViewport . value === true ) {
128+ visible . value = false
129+ }
130+ } ,
131+ )
132+
133+ return ( ) => [
105134 h (
106135 'div' ,
107136 {
@@ -116,14 +145,24 @@ const CSidebar = defineComponent({
116145 } `] : props . selfHiding ,
117146 [ `sidebar-${ props . size } ` ] : props . size ,
118147 'sidebar-narrow-unfoldable' : props . unfoldable ,
119- show : props . visible === true && visible . value === false ,
120- hide : props . visible === false && visible . value === true ,
148+ show : visible . value === true ,
149+ hide : visible . value === false ,
121150 } ,
151+ attrs . class ,
122152 ] ,
123153 ref : sidebarRef ,
124154 } ,
125155 slots . default && slots . default ( ) ,
126- )
156+ ) ,
157+ mobile . value &&
158+ h ( CBackdrop , {
159+ class : 'sidebar-backdrop d-none' ,
160+ visible : props . visible ,
161+ onClick : ( ) => {
162+ visible . value = false
163+ } ,
164+ } ) ,
165+ ]
127166 } ,
128167} )
129168
0 commit comments