Skip to content

Commit 590cd22

Browse files
markbrocatoleotoll
andauthored
Fix bug where offline warning message was not shown in the AppBar. (#33)
* Fix bug where offline warning message was not shown in the AppBar. Also moved AppBar to using useScrollTrigger for hiding. * Fetch search suggestions the first time it opens. * Fix failing test * Update src/AppBar.js Co-Authored-By: Leo <36849323+leotoll@users.noreply.github.com> * added test for profile * Fix for homepage with query params * fetchFromAPI tests * Add PWA tests * SearchProvider test change Co-authored-by: Leo <36849323+leotoll@users.noreply.github.com>
1 parent 68c6950 commit 590cd22

13 files changed

Lines changed: 332 additions & 367 deletions

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-storefront",
3-
"version": "7.2.0",
3+
"version": "7.2.1",
44
"description": "Build and deploy e-commerce progressive web apps (PWAs) in record time.",
55
"module": "./index.js",
66
"license": "Apache-2.0",

src/AppBar.js

Lines changed: 51 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1,179 +1,84 @@
1-
import React, { useState, useEffect, useRef, useContext } from 'react'
2-
import PropTypes from 'prop-types'
3-
import clsx from 'clsx'
4-
import { Toolbar } from '@material-ui/core'
1+
import React, { useContext } from 'react'
52
import { makeStyles } from '@material-ui/core/styles'
6-
import { useAmp } from 'next/amp'
3+
import { AppBar as MUIAppBar, Container, Toolbar, useScrollTrigger, Slide } from '@material-ui/core'
4+
import PropTypes from 'prop-types'
75
import PWAContext from './PWAContext'
86

9-
export const styles = theme => ({
7+
const useStyles = makeStyles(theme => ({
108
/**
11-
* Styles applied to the root element when user is not `offline`.
9+
* Styles applied to the root element.
1210
*/
1311
root: {
14-
height: 64,
15-
boxSizing: 'content-box',
16-
position: 'relative',
12+
boxSizing: 'border-box',
13+
backgroundColor: theme.palette.background.default,
14+
boxShadow: 'none',
15+
borderBottom: `1px solid ${theme.palette.divider}`,
1716
zIndex: theme.zIndex.modal + 10,
17+
height: theme.headerHeight,
18+
display: 'flex',
19+
flexDirection: 'column',
20+
alignItems: 'stretch',
1821
},
19-
2022
/**
21-
* Styles applied to the root element when Amp is used.
23+
* Styles applied to the spacer that fills the height behind the floating toolbar.
2224
*/
23-
withAmp: {
24-
zIndex: theme.zIndex.amp.modal + 1,
25+
spacer: {
26+
boxSizing: 'border-box',
27+
height: theme.headerHeight,
2528
},
26-
27-
/**
28-
* Styles applied to the offline warning element.
29-
*/
30-
offline: {
31-
textAlign: 'center',
32-
backgroundColor: '#f34c4c',
33-
color: 'white',
34-
},
35-
3629
/**
3730
* Styles applied to the `Toolbar` element.
3831
*/
3932
toolbar: {
40-
height: '64px',
41-
maxWidth: theme.maxWidth,
33+
justifyContent: 'space-between',
34+
alignItems: 'center',
4235
flex: 1,
4336
},
44-
45-
/**
46-
* Styles applied to the element wrapped around the `Toolbar`.
47-
*/
48-
wrap: {
49-
borderBottom: `1px solid ${theme.palette.divider}`,
50-
position: 'absolute',
51-
top: 0,
52-
left: 0,
53-
right: 0,
54-
backgroundColor: theme.palette.background.paper,
55-
zIndex: theme.zIndex.modal + 10,
56-
display: 'flex',
57-
justifyContent: 'center',
58-
},
59-
6037
/**
61-
* Styles applied to the `Toolbar` wrapper when the `AppBar` is unstuck.
62-
*/
63-
unstuck: {
64-
transform: 'translateY(-100%)',
65-
},
66-
67-
/**
68-
* Styles applied to the `Toolbar` wrapper element when the user has scrolled and the `AppBar`
69-
* will animate back into place.
70-
*/
71-
animate: {
72-
transition: 'transform .15s ease-in',
73-
},
74-
75-
/**
76-
* Styles applied to the `Toolbar` wrapper element the user has scrolled and the `AppBar` is hidden.
77-
*/
78-
hidden: {
79-
position: 'fixed',
80-
zIndex: theme.zIndex.modal + 10,
81-
boxShadow: theme.shadows[2],
82-
top: 0,
83-
left: 0,
84-
right: 0,
85-
},
86-
87-
/**
88-
* Styles applied to the `Toolbar` wrapper element when [`fixed`](#prop-fixed) is `true`.
38+
* Styles applied to the offline warning element.
8939
*/
90-
fixed: {
91-
position: 'fixed',
40+
offline: {
41+
textAlign: 'center',
42+
backgroundColor: '#f34c4c',
43+
zIndex: 999999,
44+
width: '100vw',
45+
color: 'white',
9246
},
93-
})
94-
95-
const useStyles = makeStyles(styles, { name: 'RSFAppBar' })
47+
}))
9648

97-
export default function AppBar({ classes, children, fixed, offlineWarning }) {
49+
export default function AppBar({ children, style, fixed, offlineWarning, classes }) {
50+
const trigger = useScrollTrigger()
9851
classes = useStyles({ classes })
9952

100-
const [state, applyState] = useState({
101-
stuck: false,
102-
hidden: false,
103-
animate: false,
104-
})
105-
const { stuck, hidden, animate } = state
106-
const setState = newState => applyState({ ...state, ...newState })
107-
const lastScrollY = useRef()
108-
const unstickAt = useRef()
109-
const stickAt = useRef()
11053
const { offline } = useContext(PWAContext)
111-
const items = React.Children.toArray(children)
112-
113-
const onScroll = () => {
114-
const height = 64,
115-
{ scrollY } = window,
116-
unstickBufferZone = 30
11754

118-
if (scrollY === 0) {
119-
setState({ hidden: false, stuck: false, animate: false })
120-
} else if (scrollY > height && !hidden) {
121-
setState({ hidden: true })
122-
}
123-
124-
if (scrollY < stickAt.current && !stuck) {
125-
stickAt.current = null
126-
unstickAt.current = scrollY + unstickBufferZone
127-
setState({ stuck: true })
128-
} else if (scrollY > unstickAt.current && stuck) {
129-
unstickAt.current = null
130-
stickAt.current = scrollY - unstickBufferZone
131-
setState({ stuck: false })
132-
}
133-
134-
if (lastScrollY.current > scrollY && stuck) {
135-
unstickAt.current = scrollY + unstickBufferZone
136-
}
137-
138-
if (lastScrollY.current < scrollY && !stuck) {
139-
stickAt.current = scrollY - unstickBufferZone
140-
}
55+
let appBar = (
56+
<MUIAppBar
57+
className={classes.root}
58+
style={{
59+
...style,
60+
}}
61+
>
62+
<Toolbar disableGutters className={classes.toolbar}>
63+
{children}
64+
</Toolbar>
65+
</MUIAppBar>
66+
)
14167

142-
lastScrollY.current = scrollY
68+
if (!fixed) {
69+
appBar = (
70+
<Slide in={!trigger}>
71+
{appBar}
72+
</Slide>
73+
)
14374
}
14475

145-
useEffect(() => {
146-
if (!fixed) {
147-
window.addEventListener('scroll', onScroll, { passive: true })
148-
return () => window.removeEventListener('scroll', onScroll, { passive: true })
149-
}
150-
}, [state])
151-
152-
useEffect(() => {
153-
if (hidden && !animate) {
154-
setTimeout(() => setState({ animate: true }), 100)
155-
}
156-
}, [hidden])
157-
15876
return (
159-
<div>
77+
<>
78+
<div className={classes.spacer} />
16079
{offline && <div className={classes.offline}>{offlineWarning}</div>}
161-
<div className={clsx({ [classes.root]: true, [classes.withAmp]: useAmp() })}>
162-
<div
163-
className={clsx({
164-
[classes.wrap]: true,
165-
[classes.fixed]: fixed,
166-
[classes.hidden]: hidden,
167-
[classes.unstuck]: hidden && !stuck,
168-
[classes.animate]: animate && window.scrollY > 0,
169-
})}
170-
>
171-
<Toolbar disableGutters classes={{ root: classes.toolbar }}>
172-
{items}
173-
</Toolbar>
174-
</div>
175-
</div>
176-
</div>
80+
{appBar}
81+
</>
17782
)
17883
}
17984

src/PWA.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useMemo, useRef } from 'react'
1+
import React, { useEffect, useMemo, useRef, useState } from 'react'
22
import PWAContext from './PWAContext'
33
import PropTypes from 'prop-types'
44
import ErrorBoundary from './ErrorBoundary'
@@ -28,12 +28,14 @@ const useStyles = makeStyles(styles, { name: 'RSFPWA' })
2828
export default function PWA({ children, errorReporter }) {
2929
useStyles()
3030
const thumbnail = useRef(null)
31+
const [offline, setOffline] = useState(typeof navigator !== 'undefined' && !navigator.onLine)
3132

3233
const context = useMemo(
3334
() => ({
3435
thumbnail,
36+
offline,
3537
}),
36-
[],
38+
[offline],
3739
)
3840

3941
// enable client-side navigation when the user clicks a simple HTML anchor element
@@ -42,17 +44,16 @@ export default function PWA({ children, errorReporter }) {
4244
useEffect(() => {
4345
context.hydrating = false
4446

45-
// const handleOnline = () => (app.offline = false)
46-
// const handleOffline = () => (app.offline = true)
47+
const handleOnline = () => setOffline(false)
48+
const handleOffline = () => setOffline(true)
4749

48-
// app.offline = !navigator.onLine
49-
// window.addEventListener('online', handleOnline)
50-
// window.addEventListener('offline', handleOffline)
50+
window.addEventListener('online', handleOnline)
51+
window.addEventListener('offline', handleOffline)
5152

52-
// return () => {
53-
// window.removeEventListener('online', handleOnline)
54-
// window.removeEventListener('offline', handleOffline)
55-
// }
53+
return () => {
54+
window.removeEventListener('online', handleOnline)
55+
window.removeEventListener('offline', handleOffline)
56+
}
5657
}, [])
5758

5859
return (

src/drawer/DrawerCloseButton.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const styles = theme => ({
3737
right: '10px',
3838
top: '-28px',
3939
zIndex: 1,
40+
color: 'white',
4041
},
4142
/**
4243
* Styles applied to hide the `Fab` button when [`open`](#prop-open) is `false`.

src/props/fetchFromAPI.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export default function fetchFromAPI({ req, asPath }) {
3030
const protocol = server ? (host.startsWith('localhost') ? 'http://' : 'https://') : ''
3131

3232
if (asPath === '/') asPath = ''
33+
if (asPath.startsWith('/?')) asPath = asPath.substring(1)
3334

3435
let uri = `/api${asPath}`
3536

src/search/SearchDrawer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default function SearchDrawer({ DrawerComponent, classes, open, onClose,
1919
classes = useStyles({ classes })
2020

2121
return (
22-
<SearchProvider onClose={onClose}>
22+
<SearchProvider onClose={onClose} open={open}>
2323
<DrawerComponent classes={classes} open={open} anchor="bottom" onClose={onClose} fullscreen>
2424
{children}
2525
</DrawerComponent>

src/search/SearchProvider.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ import useNavigationEvent from '../hooks/useNavigationEvent'
88

99
const fetch = fetchLatest(_fetch)
1010

11-
export default function SearchProvider({ children, initialGroups, onClose }) {
11+
export default function SearchProvider({ children, initialGroups, onClose, open }) {
1212
const [state, setState] = useState({
1313
groups: initialGroups,
1414
loading: true,
1515
})
1616

1717
useEffect(() => {
18-
if (state.groups == null) {
18+
if (open && state.groups == null) {
1919
fetchSuggestions('')
2020
}
21-
}, [])
21+
}, [open])
2222

2323
useNavigationEvent(onClose)
2424

@@ -69,6 +69,7 @@ export default function SearchProvider({ children, initialGroups, onClose }) {
6969
}
7070

7171
SearchProvider.propTypes = {
72+
open: PropTypes.bool,
7273
initialGroups: PropTypes.array,
7374
onClose: PropTypes.func,
7475
}

src/search/SearchSuggestions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import React, { useContext } from 'react'
22
import { makeStyles } from '@material-ui/core/styles'
3-
import PropTypes from 'prop-types'
43
import SearchSuggestionGroup from './SearchSuggestionGroup'
54
import SearchContext from './SearchContext'
65
import LoadMask from '../LoadMask'
76

87
export const styles = theme => ({
98
root: {
109
flex: 1,
10+
position: 'relative',
1111
overflowY: 'auto',
1212
},
1313
group: {

0 commit comments

Comments
 (0)