@@ -2,6 +2,9 @@ import React from 'react';
2
2
import Link from '../link/link' ;
3
3
import './sidebar-mobile-style' ;
4
4
5
+ let initialTouchPosition = { } ;
6
+ let lastTouchPosition = { } ;
7
+
5
8
export default class SidebarMobile extends React . Component {
6
9
constructor ( props ) {
7
10
super ( props ) ;
@@ -11,11 +14,26 @@ export default class SidebarMobile extends React.Component {
11
14
12
15
render ( ) {
13
16
return (
14
- < nav className = "sidebar-mobile" ref = { ref => this . container = ref } >
15
- < i className = "sidebar-mobile__close icon-cross"
16
- onClick = { this . _close . bind ( this ) } />
17
+ < nav
18
+ className = "sidebar-mobile"
19
+ ref = { ref => this . container = ref }
20
+ onTouchStart = { this . _handleTouchStart . bind ( this ) }
21
+ onTouchMove = { this . _handleTouchMove . bind ( this ) }
22
+ onTouchEnd = { this . _handleTouchEnd . bind ( this ) } >
23
+
24
+ < div
25
+ className = "sidebar-mobile__toggle"
26
+ onTouchStart = { this . _handleTouchStart . bind ( this ) }
27
+ onTouchMove = { this . _handleOpenerTouchMove . bind ( this ) }
28
+ onTouchEnd = { this . _handleTouchEnd . bind ( this ) } />
17
29
18
- { this . _getSections ( ) }
30
+ < div className = "sidebar-mobile__content" >
31
+ < i
32
+ className = "sidebar-mobile__close icon-cross"
33
+ onClick = { this . _close . bind ( this ) } />
34
+
35
+ { this . _getSections ( ) }
36
+ </ div >
19
37
</ nav >
20
38
) ;
21
39
}
@@ -42,7 +60,7 @@ export default class SidebarMobile extends React.Component {
42
60
_getSections ( ) {
43
61
return this . props . sections . map ( section => (
44
62
< div key = { section . url } >
45
- < h3 className = " sidebar-mobile__section" > { section . title } </ h3 >
63
+ < h3 className = ' sidebar-mobile__section' > { section . title } </ h3 >
46
64
{ this . _getPages ( section . pages ) }
47
65
</ div >
48
66
) ) ;
@@ -70,8 +88,7 @@ export default class SidebarMobile extends React.Component {
70
88
key = { url }
71
89
className = { `sidebar-mobile__page ${ active ? 'sidebar-mobile__page--active' : '' } ` }
72
90
to = { url }
73
- onClick = { this . _close . bind ( this ) }
74
- >
91
+ onClick = { this . _close . bind ( this ) } >
75
92
{ page . title }
76
93
</ Link >
77
94
) ;
@@ -101,4 +118,58 @@ export default class SidebarMobile extends React.Component {
101
118
'sidebar-mobile--visible'
102
119
) ;
103
120
}
104
- }
121
+
122
+ _open ( ) {
123
+ this . container . classList . add (
124
+ 'sidebar-mobile--visible'
125
+ ) ;
126
+ }
127
+
128
+ _handleTouchStart ( e ) {
129
+ initialTouchPosition . x = e . touches [ 0 ] . pageX ;
130
+ initialTouchPosition . y = e . touches [ 0 ] . pageY ;
131
+
132
+ // For instant transform along with the touch
133
+ this . container . classList . add ( 'no-delay' ) ;
134
+ }
135
+
136
+ _handleTouchMove ( e ) {
137
+ let xDiff = initialTouchPosition . x - e . touches [ 0 ] . pageX ;
138
+ let yDiff = initialTouchPosition . y - e . touches [ 0 ] . pageY ;
139
+ let factor = Math . abs ( yDiff / xDiff ) ;
140
+
141
+ // Factor makes sure horizontal and vertical scroll dont take place together
142
+ if ( xDiff > 0 && factor < 0.8 ) {
143
+ e . preventDefault ( ) ;
144
+ this . container . style . transform = `translateX(-${ xDiff } px)` ;
145
+ lastTouchPosition . x = e . touches [ 0 ] . pageX ;
146
+ lastTouchPosition . y = e . touches [ 0 ] . pageY ;
147
+ }
148
+ }
149
+
150
+ _handleOpenerTouchMove ( e ) {
151
+ let xDiff = e . touches [ 0 ] . pageX - initialTouchPosition . x ;
152
+ let yDiff = initialTouchPosition . y - e . touches [ 0 ] . pageY ;
153
+ let factor = Math . abs ( yDiff / xDiff ) ;
154
+
155
+ // Factor makes sure horizontal and vertical scroll dont take place together
156
+ if ( xDiff > 0 && xDiff < 295 && factor < 0.8 ) {
157
+ e . preventDefault ( ) ;
158
+ this . container . style . transform = `translateX(calc(-100% + ${ xDiff } px))` ;
159
+ lastTouchPosition . x = e . touches [ 0 ] . pageX ;
160
+ lastTouchPosition . y = e . touches [ 0 ] . pageY ;
161
+ }
162
+ }
163
+
164
+ _handleTouchEnd ( e ) {
165
+ // Free up all the inline styling
166
+ this . container . classList . remove ( 'no-delay' ) ;
167
+ this . container . style = '' ;
168
+
169
+ if ( initialTouchPosition . x - lastTouchPosition . x > 100 ) {
170
+ this . _close ( ) ;
171
+ } else if ( lastTouchPosition . x - initialTouchPosition . x > 100 ) {
172
+ this . _open ( ) ;
173
+ }
174
+ }
175
+ }
0 commit comments