1- import React , { useRef } from 'react' ;
1+ import React , { useRef , useEffect } from 'react' ;
22import classNames from 'classnames' ;
33import { useTranslation } from 'react-i18next' ;
44import { useDispatch , useSelector } from 'react-redux' ;
@@ -30,21 +30,37 @@ export default function SideBar() {
3030 ) ;
3131 const isExpanded = useSelector ( ( state ) => state . ide . sidebarIsExpanded ) ;
3232 const canEditProject = useSelector ( selectCanEditSketch ) ;
33+ const isAuthenticated = useSelector ( getAuthenticated ) ;
3334
3435 const sidebarOptionsRef = useRef ( null ) ;
3536
36- const isAuthenticated = useSelector ( getAuthenticated ) ;
37+ useEffect ( ( ) => {
38+ function handleClickOutside ( event ) {
39+ if (
40+ projectOptionsVisible &&
41+ sidebarOptionsRef . current &&
42+ ! sidebarOptionsRef . current . contains ( event . target )
43+ ) {
44+ setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 300 ) ;
45+ }
46+ }
3747
38- const onBlurComponent = ( ) => {
39- setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 200 ) ;
40- } ;
48+ if ( projectOptionsVisible ) {
49+ document . addEventListener ( 'mousedown' , handleClickOutside ) ;
50+ } else {
51+ document . removeEventListener ( 'mousedown' , handleClickOutside ) ;
52+ }
53+
54+ return ( ) => {
55+ document . removeEventListener ( 'mousedown' , handleClickOutside ) ;
56+ } ;
57+ } , [ projectOptionsVisible , dispatch ] ) ;
4158
4259 const toggleProjectOptions = ( e ) => {
4360 e . preventDefault ( ) ;
4461 if ( projectOptionsVisible ) {
4562 dispatch ( closeProjectOptions ( ) ) ;
4663 } else {
47- sidebarOptionsRef . current ?. focus ( ) ;
4864 dispatch ( openProjectOptions ( ) ) ;
4965 }
5066 } ;
@@ -65,9 +81,7 @@ export default function SideBar() {
6581 dispatch ( collapseSidebar ( ) ) ;
6682 dispatch ( closeProjectOptions ( ) ) ;
6783 } }
68- >
69- { ' ' }
70- </ button >
84+ />
7185 ) }
7286 < section className = { sidebarClass } >
7387 < header
@@ -77,60 +91,54 @@ export default function SideBar() {
7791 < h3 className = "sidebar__title" >
7892 < span > { t ( 'Sidebar.Title' ) } </ span >
7993 </ h3 >
80- < div className = "sidebar__icons" >
94+ < div className = "sidebar__icons" ref = { sidebarOptionsRef } >
8195 < button
8296 aria-label = { t ( 'Sidebar.ToggleARIA' ) }
8397 className = "sidebar__add"
8498 tabIndex = "0"
85- ref = { sidebarOptionsRef }
8699 onClick = { toggleProjectOptions }
87- onBlur = { onBlurComponent }
88100 >
89101 < PlusIcon focusable = "false" aria-hidden = "true" />
90102 </ button >
91- < ul className = "sidebar__project-options" >
92- < li >
93- < button
94- onMouseDown = { ( e ) => e . preventDefault ( ) }
95- aria-label = { t ( 'Sidebar.AddFolderARIA' ) }
96- onClick = { ( ) => {
97- dispatch ( newFolder ( rootFile . id ) ) ;
98- setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 0 ) ;
99- } }
100- onBlur = { onBlurComponent }
101- >
102- { t ( 'Sidebar.AddFolder' ) }
103- </ button >
104- </ li >
105- < li >
106- < button
107- onMouseDown = { ( e ) => e . preventDefault ( ) }
108- aria-label = { t ( 'Sidebar.AddFileARIA' ) }
109- onClick = { ( ) => {
110- dispatch ( newFile ( rootFile . id ) ) ;
111- setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 0 ) ;
112- } }
113- onBlur = { onBlurComponent }
114- >
115- { t ( 'Sidebar.AddFile' ) }
116- </ button >
117- </ li >
118- { isAuthenticated && (
103+ { projectOptionsVisible && (
104+ < ul className = "sidebar__project-options" >
105+ < li >
106+ < button
107+ aria-label = { t ( 'Sidebar.AddFolderARIA' ) }
108+ onClick = { ( ) => {
109+ dispatch ( newFolder ( rootFile . id ) ) ;
110+ setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 300 ) ;
111+ } }
112+ >
113+ { t ( 'Sidebar.AddFolder' ) }
114+ </ button >
115+ </ li >
119116 < li >
120117 < button
121- onMouseDown = { ( e ) => e . preventDefault ( ) }
122- aria-label = { t ( 'Sidebar.UploadFileARIA' ) }
118+ aria-label = { t ( 'Sidebar.AddFileARIA' ) }
123119 onClick = { ( ) => {
124- dispatch ( openUploadFileModal ( rootFile . id ) ) ;
125- setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 0 ) ;
120+ dispatch ( newFile ( rootFile . id ) ) ;
121+ setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 300 ) ;
126122 } }
127- onBlur = { onBlurComponent }
128123 >
129- { t ( 'Sidebar.UploadFile ' ) }
124+ { t ( 'Sidebar.AddFile ' ) }
130125 </ button >
131126 </ li >
132- ) }
133- </ ul >
127+ { isAuthenticated && (
128+ < li >
129+ < button
130+ aria-label = { t ( 'Sidebar.UploadFileARIA' ) }
131+ onClick = { ( ) => {
132+ dispatch ( openUploadFileModal ( rootFile . id ) ) ;
133+ setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 300 ) ;
134+ } }
135+ >
136+ { t ( 'Sidebar.UploadFile' ) }
137+ </ button >
138+ </ li >
139+ ) }
140+ </ ul >
141+ ) }
134142 </ div >
135143 </ header >
136144 < ConnectedFileNode id = { rootFile . id } canEdit = { canEditProject } />
0 commit comments