From dea59ec5af6f7c550edfea6fe578835f12fba397 Mon Sep 17 00:00:00 2001 From: Adam Fahy Date: Mon, 30 Mar 2020 12:03:21 -0400 Subject: [PATCH] Fixes 100vh not working as expected in Mobile Safari --- src/App.tsx | 55 ++++++++++++++------- src/Components/AppBar.tsx | 77 ++++++++++-------------------- src/Components/LocationDetails.tsx | 1 - src/Components/Map.tsx | 2 +- src/utils/getViewportHeight.tsx | 8 ++++ 5 files changed, 74 insertions(+), 69 deletions(-) create mode 100644 src/utils/getViewportHeight.tsx diff --git a/src/App.tsx b/src/App.tsx index 6e4c85b..b32e05b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,11 +14,11 @@ import Header from './Components/Header'; import DataUpdateSnackbar from './Components/DataUpdateSnackbar'; import LegalModal from './Components/LegalModal'; import theme from './theme'; +import getViewportHeight from './utils/getViewportHeight'; import { trackLocationPrompt, trackDrawerStatus } from './utils/tracking'; // Layout Component styles const LayoutContainer = styled.div` - height: 100vh; width: 100vw; display: flex; flex-direction: column; @@ -35,13 +35,14 @@ const SidebarContainer = styled.div` `; const MapContainer = styled.div` - height: 100%; + flex-basis: 100%; + flex-grow: 1; position: relative; `; const AppBarContainer = styled.div` z-index: 120; - position: sticky; + position: relative; `; export interface LabelMap { @@ -83,6 +84,7 @@ interface AppState { drawerOpen: boolean; currentPlace: any; viewState: any; + viewportHeight: number; } interface GeolocationCoordinates { @@ -97,6 +99,8 @@ interface GeolocationCoordinates { export const SearchContext = React.createContext(defaultFilters); const geocoderContainerRef = React.createRef(); +let windowListener: any; // store event handler for resize events + const dataLayer = (window as any).dataLayer || []; (window as any).dataLayer = (window as any).dataLayer || []; @@ -105,6 +109,7 @@ export class App extends React.Component<{}, AppState> { super(props); this.state = { + viewportHeight: 0, filters: defaultFilters, currentPlace: null, drawerOpen: false, @@ -124,6 +129,20 @@ export class App extends React.Component<{}, AppState> { } catch (e) { console.error('failed to locate user', e); } + + // detect resize events and set viewport height + windowListener = window.addEventListener('resize', () => this.setHeight()); + this.setHeight(); + } + + componentWillUnmount(): void { + window.removeEventListener('resize', windowListener); + } + + // set height using js, as 100vh doesn't work as expected in mobile safari + setHeight(): void { + const viewportHeight = getViewportHeight(); + this.setState({ viewportHeight }); } locateUser() { @@ -184,7 +203,13 @@ export class App extends React.Component<{}, AppState> { } render() { - const { currentPlace, filters, drawerOpen, viewState } = this.state; + const { + currentPlace, + filters, + drawerOpen, + viewState, + viewportHeight, + } = this.state; const toggleDrawer = () => { this.setState({ drawerOpen: !drawerOpen }); trackDrawerStatus(drawerOpen); @@ -193,7 +218,7 @@ export class App extends React.Component<{}, AppState> { return ( - + @@ -230,19 +255,17 @@ export class App extends React.Component<{}, AppState> { }} geocoderContainerRef={geocoderContainerRef} /> - - {currentPlace === null ? ( - '' - ) : ( - { - this.setState({ currentPlace: null }); - }} - /> - )} + {currentPlace !== null && ( + { + this.setState({ currentPlace: null }); + }} + /> + )} + - createStyles({ - text: { - padding: theme.spacing(2, 2, 0), - }, - paper: { - paddingBottom: 50, - }, - list: { - marginBottom: theme.spacing(2), - }, - subheader: { - backgroundColor: theme.palette.background.paper, - }, - appBar: { - top: 'auto', - bottom: 0, - height: '60px', - }, - grow: { - flexGrow: 1, - }, - fabButton: { - position: 'absolute', - zIndex: 1, - top: -30, - left: 0, - right: 0, - margin: '0 auto', - }, - searchContainer: { - position: 'relative', - }, - }) -); +const SearchContainer = styled.div` + position: relative; +`; + +const ActionButtonContainer = styled.div` + position: absolute; + z-index: 1; + top: -24px; + left: 50%; + transform: translate(-50%, 0); +`; + +const Spacer = styled.div` + flex-grow: 1; + flex-basis: 100%; +`; type AppBarProps = { geocoderContainerRef: any; @@ -54,24 +33,20 @@ type AppBarProps = { }; const AppBar = (props: AppBarProps) => { - const classes = useStyles(); - const { geocoderContainerRef, toggleDrawer } = props; return ( - + -
+ - - - + + + + + -
+ createStyles({ diff --git a/src/Components/Map.tsx b/src/Components/Map.tsx index eccbd95..5c5b24e 100644 --- a/src/Components/Map.tsx +++ b/src/Components/Map.tsx @@ -53,7 +53,7 @@ const Map = (props: MapProps) => { return ( 'cursor'} onViewStateChange={setViewState} diff --git a/src/utils/getViewportHeight.tsx b/src/utils/getViewportHeight.tsx new file mode 100644 index 0000000..f651e0f --- /dev/null +++ b/src/utils/getViewportHeight.tsx @@ -0,0 +1,8 @@ +// calculate browser height +const getViewportHeight = (): number => + (document && + document.documentElement && + document.documentElement.clientHeight) || + window.innerHeight; + +export default getViewportHeight;