@@ -2,20 +2,21 @@ import React from 'react';
2
2
import Link from '../Link/Link' ;
3
3
import './SidebarMobile.scss' ;
4
4
5
- // TODO: Finish updating close and swipe behaviors
6
5
// TODO: Check to make sure all pages are shown and properly sorted
7
6
export default class SidebarMobile extends React . Component {
8
7
_container = null
9
8
_initialTouchPosition = { }
10
9
_lastTouchPosition = { }
11
10
12
11
render ( ) {
13
- let { open } = this . props ;
14
- let openMod = open ? 'sidebar-mobile--visible' : '' ;
12
+ let { isOpen, toggle } = this . props ;
13
+ let openMod = isOpen ? ' sidebar-mobile--visible' : '' ;
14
+
15
+ this . _toggleBodyListener ( isOpen ) ;
15
16
16
17
return (
17
18
< nav
18
- className = { `sidebar-mobile ${ openMod } ` }
19
+ className = { `sidebar-mobile${ openMod } ` }
19
20
ref = { ref => this . _container = ref }
20
21
onTouchStart = { this . _handleTouchStart }
21
22
onTouchMove = { this . _handleTouchMove }
@@ -30,26 +31,17 @@ export default class SidebarMobile extends React.Component {
30
31
< div className = "sidebar-mobile__content" >
31
32
< i
32
33
className = "sidebar-mobile__close icon-cross"
33
- onClick = { this . props . toggle } />
34
+ onClick = { toggle . bind ( null , false ) } />
34
35
35
36
{ this . _getSections ( ) }
36
37
</ div >
37
38
</ nav >
38
39
) ;
39
40
}
40
41
41
- componentDidMount ( ) {
42
- if ( typeof window !== 'undefined' ) {
43
- // window.addEventListener('click', this._handleBodyClick);
44
- window . addEventListener ( 'touchstart' , this . _handleBodyClick ) ;
45
- }
46
- }
47
-
48
- componentWillUnmount ( ) {
49
- if ( typeof window !== 'undefined' ) {
50
- // window.removeEventListener('click', this._handleBodyClick);
51
- window . removeEventListener ( 'touchstart' , this . _handleBodyClick ) ;
52
- }
42
+ _toggleBodyListener ( add ) {
43
+ let actionName = add ? 'addEventListener' : 'removeEventListener' ;
44
+ window [ actionName ] ( 'mousedown' , this . _handleBodyClick ) ;
53
45
}
54
46
55
47
/**
@@ -60,23 +52,22 @@ export default class SidebarMobile extends React.Component {
60
52
_getSections ( ) {
61
53
let pathname = '' ;
62
54
63
- if ( window . location !== undefined ) {
55
+ if ( window && window . location !== undefined ) {
64
56
pathname = window . location . pathname ;
65
57
}
66
58
67
59
return this . props . sections . map ( section => {
68
- let active = pathname === section . url || pathname . includes ( `/${ section . url } ` ) ,
69
- absoluteUrl = ( section . url == '/' ) ? '/' : `/${ section . url } ` ;
60
+ let active = section . url !== '/' && pathname . startsWith ( section . url ) ;
70
61
71
62
return (
72
63
< div
73
64
className = { `sidebar-mobile__section ${ active ? 'sidebar-mobile__section--active' : '' } ` }
74
- key = { absoluteUrl } >
65
+ key = { section . url } >
75
66
< Link
76
67
className = "sidebar-mobile__section-header"
77
- key = { absoluteUrl }
78
- to = { absoluteUrl }
79
- onClick = { this . props . toggle } >
68
+ key = { section . url }
69
+ to = { section . url }
70
+ onClick = { this . props . toggle . bind ( null , false ) } >
80
71
< h3 > { section . title || section . url } </ h3 >
81
72
</ Link >
82
73
@@ -101,14 +92,14 @@ export default class SidebarMobile extends React.Component {
101
92
102
93
return pages . map ( page => {
103
94
let url = `${ page . url } ` ,
104
- active = pathname === url || pathname . includes ( ` ${ url } /` ) ;
95
+ active = pathname === url ;
105
96
106
97
return (
107
98
< Link
108
99
key = { url }
109
100
className = { `sidebar-mobile__page ${ active ? 'sidebar-mobile__page--active' : '' } ` }
110
101
to = { url }
111
- onClick = { this . props . toggle } >
102
+ onClick = { this . props . toggle . bind ( null , false ) } >
112
103
{ page . title }
113
104
</ Link >
114
105
) ;
@@ -120,30 +111,14 @@ export default class SidebarMobile extends React.Component {
120
111
*
121
112
* @param {object } e - Native click event
122
113
*/
123
- // _handleBodyClick = e => {
124
- // if (
125
- // this.props.open &&
126
- // !this._container.contains(e.target)
127
- // ) {
128
- // this._close();
129
- // }
130
- // }
131
-
132
- /**
133
- * Hide the sidebar
134
- *
135
- */
136
- // _close() {
137
- // this._container.classList.remove(
138
- // 'sidebar-mobile--visible'
139
- // );
140
- // }
141
-
142
- // _open() {
143
- // this._container.classList.add(
144
- // 'sidebar-mobile--visible'
145
- // );
146
- // }
114
+ _handleBodyClick = e => {
115
+ if (
116
+ this . props . isOpen &&
117
+ ! this . _container . contains ( e . target )
118
+ ) {
119
+ this . props . toggle ( false ) ;
120
+ }
121
+ }
147
122
148
123
_handleTouchStart = e => {
149
124
this . _initialTouchPosition . x = e . touches [ 0 ] . pageX ;
@@ -159,7 +134,7 @@ export default class SidebarMobile extends React.Component {
159
134
let factor = Math . abs ( yDiff / xDiff ) ;
160
135
161
136
// Factor makes sure horizontal and vertical scroll dont take place together
162
- if ( xDiff > 0 && factor < 0.8 ) {
137
+ if ( xDiff > 0 && factor < 0.8 ) {
163
138
e . preventDefault ( ) ;
164
139
this . _container . style . transform = `translateX(-${ xDiff } px)` ;
165
140
this . _lastTouchPosition . x = e . touches [ 0 ] . pageX ;
@@ -182,14 +157,21 @@ export default class SidebarMobile extends React.Component {
182
157
}
183
158
184
159
_handleTouchEnd = e => {
160
+ const { isOpen } = this . props ;
161
+ const threshold = 20 ;
162
+
185
163
// Free up all the inline styling
186
164
this . _container . classList . remove ( 'no-delay' ) ;
187
165
this . _container . style . transform = '' ;
188
166
189
- if ( this . _initialTouchPosition . x - this . _lastTouchPosition . x > 100 ) {
190
- this . _close ( ) ;
191
- } else if ( this . _lastTouchPosition . x - this . _initialTouchPosition . x > 100 ) {
192
- this . _open ( ) ;
167
+ // are we open?
168
+ if ( isOpen && this . _initialTouchPosition . x - this . _lastTouchPosition . x > threshold ) {
169
+ // this is in top level nav callback
170
+ this . props . toggle ( false ) ;
171
+ } else if ( ! isOpen && this . _lastTouchPosition . x - this . _initialTouchPosition . x > threshold ) {
172
+ this . props . toggle ( true ) ;
173
+ e . preventDefault ( ) ;
174
+ e . stopPropagation ( ) ;
193
175
}
194
176
}
195
177
}
0 commit comments