@@ -10,8 +10,10 @@ import AppsManager from 'lib/AppsManager';
1010import AppsMenu from 'components/Sidebar/AppsMenu.react' ;
1111import AppName from 'components/Sidebar/AppName.react' ;
1212import FooterMenu from 'components/Sidebar/FooterMenu.react' ;
13- import React , { useState } from 'react ' ;
13+ import isInsidePopover from 'lib/isInsidePopover ' ;
1414import ParseApp from 'lib/ParseApp' ;
15+ import Pin from 'components/Sidebar/Pin.react' ;
16+ import React , { useEffect , useState } from 'react' ;
1517import SidebarHeader from 'components/Sidebar/SidebarHeader.react' ;
1618import SidebarSection from 'components/Sidebar/SidebarSection.react' ;
1719import SidebarSubItem from 'components/Sidebar/SidebarSubItem.react' ;
@@ -29,7 +31,46 @@ const Sidebar = ({
2931 primaryBackgroundColor,
3032 secondaryBackgroundColor
3133} , { currentApp } ) => {
34+ const collapseWidth = 980 ;
3235 const [ appsMenuOpen , setAppsMenuOpen ] = useState ( false ) ;
36+ const [ collapsed , setCollapsed ] = useState ( false ) ;
37+ const [ fixed , setFixed ] = useState ( true ) ;
38+ let currentWidth = window . innerWidth ;
39+
40+ const windowResizeHandler = ( ) => {
41+ if ( window . innerWidth <= collapseWidth && currentWidth > collapseWidth ) {
42+ if ( document . body . className . indexOf ( ' expanded' ) === - 1 ) {
43+ document . body . className += ' expanded' ;
44+ }
45+ setCollapsed ( true ) ;
46+ setFixed ( false ) ;
47+ } else if ( window . innerWidth > collapseWidth && currentWidth <= collapseWidth ) {
48+ document . body . className = document . body . className . replace ( ' expanded' , '' ) ;
49+ setCollapsed ( false ) ;
50+ setFixed ( true ) ;
51+ }
52+ // Update window width
53+ currentWidth = window . innerWidth ;
54+ }
55+
56+ useEffect ( ( ) => {
57+ window . addEventListener ( 'resize' , windowResizeHandler ) ;
58+
59+ return ( ) => {
60+ window . removeEventListener ( 'resize' , windowResizeHandler ) ;
61+ }
62+ } ) ;
63+
64+ const sidebarClasses = [ styles . sidebar ] ;
65+ if ( fixed ) {
66+ document . body . className = document . body . className . replace ( ' expanded' , '' ) ;
67+ } else if ( ! fixed && collapsed ) {
68+ sidebarClasses . push ( styles . collapsed ) ;
69+ if ( document . body . className . indexOf ( ' expanded' ) === - 1 ) {
70+ document . body . className += ' expanded' ;
71+ }
72+ }
73+
3374 const _subMenu = subsections => {
3475 if ( ! subsections ) {
3576 return null ;
@@ -54,25 +95,40 @@ const Sidebar = ({
5495 ) ;
5596 }
5697
57- const apps = [ ] . concat ( AppsManager . apps ( ) ) . sort ( ( a , b ) => ( a . name < b . name ? - 1 : ( a . name > b . name ? 1 : 0 ) ) ) ;
98+ const onPinClick = ( ) => {
99+ if ( fixed ) {
100+ setFixed ( false ) ;
101+ setCollapsed ( true ) ;
102+ setAppsMenuOpen ( false ) ;
103+ } else {
104+ setFixed ( true ) ;
105+ setCollapsed ( false ) ;
106+ }
107+ } ;
58108
59109 let sidebarContent ;
60110 if ( appsMenuOpen ) {
111+ const apps = [ ] . concat ( AppsManager . apps ( ) ) . sort ( ( a , b ) => ( a . name < b . name ? - 1 : ( a . name > b . name ? 1 : 0 ) ) ) ;
61112 sidebarContent = (
62113 < AppsMenu
63114 apps = { apps }
64115 current = { currentApp }
116+ onPinClick = { onPinClick }
65117 onSelect = { ( ) => setAppsMenuOpen ( false ) } />
66118 ) ;
67119 } else {
120+ const topContent = collapsed
121+ ? < Pin onClick = { onPinClick } />
122+ : appSelector && (
123+ < div className = { styles . apps } >
124+ < AppName name = { currentApp . name } onClick = { ( ) => setAppsMenuOpen ( true ) } onPinClick = { onPinClick } />
125+ </ div >
126+ ) || undefined ;
127+
68128 sidebarContent = (
69129 < >
70- { appSelector && (
71- < div className = { styles . apps } >
72- < AppName name = { currentApp . name } onClick = { ( ) => setAppsMenuOpen ( true ) } />
73- </ div >
74- ) }
75130 < div className = { styles . content } >
131+ { topContent }
76132 { sections . map ( ( {
77133 name,
78134 icon,
@@ -84,15 +140,15 @@ const Sidebar = ({
84140 return (
85141 < SidebarSection
86142 key = { name }
87- name = { name }
143+ name = { collapsed ? null : name }
88144 icon = { icon }
89145 style = { style }
90146 link = { prefix + link }
91147 active = { active }
92148 primaryBackgroundColor = { primaryBackgroundColor }
93149 secondaryBackgroundColor = { secondaryBackgroundColor }
94150 >
95- { active ? _subMenu ( subsections ) : null }
151+ { ! collapsed && active ? _subMenu ( subsections ) : null }
96152 </ SidebarSection >
97153 ) ;
98154 } ) }
@@ -101,16 +157,39 @@ const Sidebar = ({
101157 )
102158 }
103159
104- return < div className = { styles . sidebar } >
105- < SidebarHeader />
106- { sidebarContent }
107- < div className = { styles . footer } >
108- < a target = '_blank' href = 'http://parseplatform.org/' > Open Source Hub</ a >
109- < a target = '_blank' href = 'https://github.com/parse-community' > GitHub</ a >
110- < a target = '_blank' href = 'http://docs.parseplatform.org/' > Docs</ a >
111- < FooterMenu />
160+ return (
161+ < div
162+ className = { sidebarClasses . join ( ' ' ) }
163+ onMouseEnter = {
164+ ! fixed && collapsed
165+ ? ( ) => setCollapsed ( false )
166+ : undefined
167+ }
168+ onMouseLeave = {
169+ ! collapsed && ! fixed
170+ ? ( e => {
171+ if ( ! isInsidePopover ( e . relatedTarget ) ) {
172+ setAppsMenuOpen ( false ) ;
173+ setCollapsed ( true ) ;
174+ }
175+ } )
176+ : undefined
177+ }
178+ >
179+ < SidebarHeader isCollapsed = { ! appsMenuOpen && collapsed } />
180+ { sidebarContent }
181+ < div className = { styles . footer } >
182+ { ! collapsed && (
183+ < >
184+ < a target = '_blank' href = 'http://parseplatform.org/' > Open Source Hub</ a >
185+ < a target = '_blank' href = 'https://github.com/parse-community' > GitHub</ a >
186+ < a target = '_blank' href = 'http://docs.parseplatform.org/' > Docs</ a >
187+ </ >
188+ ) }
189+ < FooterMenu isCollapsed = { ! appsMenuOpen && collapsed } />
190+ </ div >
112191 </ div >
113- </ div >
192+ ) ;
114193}
115194
116195Sidebar . contextTypes = {
0 commit comments