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,38 @@ 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+ /** Close dropdown when clicking outside */
38+ useEffect ( ( ) => {
39+ function handleClickOutside ( event ) {
40+ if (
41+ projectOptionsVisible &&
42+ sidebarOptionsRef . current &&
43+ ! sidebarOptionsRef . current . contains ( event . target )
44+ ) {
45+ setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 300 ) ;
46+ }
47+ }
3748
38- const onBlurComponent = ( ) => {
39- setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 200 ) ;
40- } ;
49+ if ( projectOptionsVisible ) {
50+ document . addEventListener ( 'mousedown' , handleClickOutside ) ;
51+ } else {
52+ document . removeEventListener ( 'mousedown' , handleClickOutside ) ;
53+ }
54+
55+ return ( ) => {
56+ document . removeEventListener ( 'mousedown' , handleClickOutside ) ;
57+ } ;
58+ } , [ projectOptionsVisible , dispatch ] ) ;
4159
4260 const toggleProjectOptions = ( e ) => {
4361 e . preventDefault ( ) ;
4462 if ( projectOptionsVisible ) {
4563 dispatch ( closeProjectOptions ( ) ) ;
4664 } else {
47- sidebarOptionsRef . current ?. focus ( ) ;
4865 dispatch ( openProjectOptions ( ) ) ;
4966 }
5067 } ;
@@ -65,69 +82,61 @@ export default function SideBar() {
6582 dispatch ( collapseSidebar ( ) ) ;
6683 dispatch ( closeProjectOptions ( ) ) ;
6784 } }
68- >
69- { ' ' }
70- </ button >
85+ />
7186 ) }
7287 < section className = { sidebarClass } >
73- < header
74- className = "sidebar__header"
75- onContextMenu = { toggleProjectOptions }
76- >
88+ < header className = "sidebar__header" >
7789 < h3 className = "sidebar__title" >
7890 < span > { t ( 'Sidebar.Title' ) } </ span >
7991 </ h3 >
80- < div className = "sidebar__icons" >
92+ < div className = "sidebar__icons" ref = { sidebarOptionsRef } >
8193 < button
8294 aria-label = { t ( 'Sidebar.ToggleARIA' ) }
8395 className = "sidebar__add"
8496 tabIndex = "0"
85- ref = { sidebarOptionsRef }
8697 onClick = { toggleProjectOptions }
87- onBlur = { onBlurComponent }
8898 >
8999 < PlusIcon focusable = "false" aria-hidden = "true" />
90100 </ 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- } }
99- onBlur = { onBlurComponent }
100- >
101- { t ( 'Sidebar.AddFolder' ) }
102- </ button >
103- </ li >
104- < li >
105- < button
106- onMouseDown = { ( e ) => e . preventDefault ( ) }
107- aria-label = { t ( 'Sidebar.AddFileARIA' ) }
108- onClick = { ( ) => {
109- dispatch ( newFile ( rootFile . id ) ) ;
110- } }
111- onBlur = { onBlurComponent }
112- >
113- { t ( 'Sidebar.AddFile' ) }
114- </ button >
115- </ li >
116- { isAuthenticated && (
101+ { projectOptionsVisible && (
102+ < ul className = "sidebar__project-options" >
103+ < li >
104+ < button
105+ aria-label = { t ( 'Sidebar.AddFolderARIA' ) }
106+ onClick = { ( ) => {
107+ dispatch ( newFolder ( rootFile . id ) ) ;
108+ setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 300 ) ;
109+ } }
110+ >
111+ { t ( 'Sidebar.AddFolder' ) }
112+ </ button >
113+ </ li >
117114 < li >
118115 < button
119- onMouseDown = { ( e ) => e . preventDefault ( ) }
120- aria-label = { t ( 'Sidebar.UploadFileARIA' ) }
116+ aria-label = { t ( 'Sidebar.AddFileARIA' ) }
121117 onClick = { ( ) => {
122- dispatch ( openUploadFileModal ( rootFile . id ) ) ;
118+ dispatch ( newFile ( rootFile . id ) ) ;
119+ setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 300 ) ;
123120 } }
124- onBlur = { onBlurComponent }
125121 >
126- { t ( 'Sidebar.UploadFile ' ) }
122+ { t ( 'Sidebar.AddFile ' ) }
127123 </ button >
128124 </ li >
129- ) }
130- </ ul >
125+ { isAuthenticated && (
126+ < li >
127+ < button
128+ aria-label = { t ( 'Sidebar.UploadFileARIA' ) }
129+ onClick = { ( ) => {
130+ dispatch ( openUploadFileModal ( rootFile . id ) ) ;
131+ setTimeout ( ( ) => dispatch ( closeProjectOptions ( ) ) , 300 ) ;
132+ } }
133+ >
134+ { t ( 'Sidebar.UploadFile' ) }
135+ </ button >
136+ </ li >
137+ ) }
138+ </ ul >
139+ ) }
131140 </ div >
132141 </ header >
133142 < ConnectedFileNode id = { rootFile . id } canEdit = { canEditProject } />
0 commit comments