Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Gatsby Docs Update] Fixed iOS overscroll issues, and redesigned mobile sidebar button to … #10761

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions www/src/components/Flex/Flex.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {createElement} from 'glamor/react';
const Flex = ({
basis = 'auto',
children,
className,
direction = 'row',
grow = 0,
halign = 'flex-start',
Expand All @@ -30,6 +31,7 @@ const Flex = ({
createElement(
type,
{
className,
css: {
display: 'flex',
flexDirection: direction,
Expand Down
11 changes: 11 additions & 0 deletions www/src/components/LayoutHeader/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,19 @@ import logoSvg from 'icons/logo.svg';
// This is how the previous Jekyll site determined version though.
const {version} = require('../../../../package.json');

import {css} from 'glamor';

css.global('#header', {
transition: 'transform 0.2s ease',
});

css.global('.is-menu-open #header', {
transform: 'translateY(-100%)',
});
Copy link
Contributor

@bvaughn bvaughn Sep 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to avoid global styles for this. I suggest we pass an isOpen prop do this component instead and (probably) expose a toggle function to the sticky sidebar via context. (I'll be happy to help implement this change.)


const Header = ({location}) => (
<header
id="header"
css={{
backgroundColor: colors.darker,
color: colors.white,
Expand Down
8 changes: 6 additions & 2 deletions www/src/components/MarkdownPage/MarkdownPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ const MarkdownPage = ({
flex: '1 0 auto',
position: 'relative',
zIndex: 0,
overflow: 'auto', // This is required for the mobile footer layout
}}>
<TitleAndMetaTags
title={`${titlePrefix}${titlePostfix}`}
Expand All @@ -57,7 +56,12 @@ const MarkdownPage = ({
<div css={{flex: '1 0 auto'}}>
<Container>
<div css={sharedStyles.articleLayout.container}>
<Flex type="article" direction="column" grow="1" halign="stretch">
<Flex
type="article"
direction="column"
grow="1"
halign="stretch"
className="disable-scrolling">
<MarkdownHeader title={titlePrefix} />

{(date || hasAuthors) &&
Expand Down
114 changes: 102 additions & 12 deletions www/src/components/StickyResponsiveSidebar/StickyResponsiveSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,80 @@ class StickyResponsiveSidebar extends Component {
open: false,
};
this.toggleOpen = this._toggleOpen.bind(this);
this.handleDocumentTouchMove = this._handleDocumentTouchMove.bind(this);
this.handleSidebarTouchStart = this._handleSidebarTouchStart.bind(this);
}

componentDidMount() {
document.addEventListener('touchmove', this.handleDocumentTouchMove);
document
.querySelector('.scrollable')
.addEventListener('touchstart', this.handleSidebarTouchStart);
Copy link
Contributor

@bvaughn bvaughn Sep 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strong initial dislike to all of the global handlers/selectors here. If we have to do this, I think we should wrap it up in a separate component rather than mix it into the sticky component.

Ideally we could do this in a more "React" way (with props/refs) but I'd have to think about that a bit more. Might be harder to do.

Copy link
Contributor

@flarnie flarnie Sep 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit:
I see you did add a comment and link below - still might be good to comment here too.


It might be possible to make it a bit more 'React' ish. For now we could start by adding a comment and linking to the blog post that describes this fix for the iOS overscroll bug. (http://blog.christoffer.online/2015-06-10-six-things-i-learnt-about-ios-rubberband-overflow-scrolling/)

}

componentWillUnmount() {
document.removeEventListener('touchmove', this.handleDocumentTouchMove);
document
.querySelector('.scrollable')
.removeEventListener('touchstart', this.handleSidebarTouchStart);
document.documentElement.classList.remove('is-menu-open');
}

_toggleOpen() {
document.documentElement.classList[this.state.open ? 'remove' : 'add'](
'is-menu-open',
);
this.setState({open: !this.state.open});
}

isMenuOpen() {
return (
this.state.open &&
window.matchMedia(media.greaterThan('small').replace('@media ', ''))
);
}

// Prevent background scroll
// http://blog.christoffer.online/2015-06-10-six-things-i-learnt-about-ios-rubberband-overflow-scrolling/
_handleDocumentTouchMove(evt) {
if (!this.isMenuOpen()) {
return;
}

let isTouchMoveAllowed = true;
let target = evt.target;

while (target !== null) {
if (target.classList && target.classList.contains('disable-scrolling')) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}

if (!isTouchMoveAllowed) {
evt.preventDefault();
}
}

// Remove iOS Rubber Effect
// http://blog.christoffer.online/2015-06-10-six-things-i-learnt-about-ios-rubberband-overflow-scrolling/
_handleSidebarTouchStart(evt) {
if (!this.isMenuOpen()) {
return;
}

const top = evt.currentTarget.scrollTop;
const totalScroll = evt.currentTarget.scrollHeight;
const currentScroll = top + evt.currentTarget.offsetHeight;

if (top === 0) {
evt.currentTarget.scrollTop = 1;
} else if (currentScroll === totalScroll) {
evt.currentTarget.scrollTop = top - 1;
}
}

render() {
const {title} = this.props;
const {open} = this.state;
Expand Down Expand Up @@ -60,9 +128,10 @@ class StickyResponsiveSidebar extends Component {
return (
<div>
<div
className="scrollable"
style={{
opacity: menuOpacity,
transition: 'opacity 0.5s ease',
transition: 'opacity 0.2s ease',
}}
css={{
[media.lessThan('small')]: smallScreenSidebarStyles,
Expand Down Expand Up @@ -106,7 +175,7 @@ class StickyResponsiveSidebar extends Component {
<div
style={{
transform: `translate(0px, ${menuOffset}px)`,
transition: 'transform 0.5s ease',
transition: 'transform 0.2s 0.05s ease',
}}
css={{
marginTop: 60,
Expand All @@ -124,24 +193,35 @@ class StickyResponsiveSidebar extends Component {
},

[media.greaterThan('small')]: {
tranform: 'none !important',
transform: 'none !important',
},
}}>
<Sidebar {...this.props} />
<div
css={{
[media.lessThan('small')]: {
// Extra scrolling space for iOS Safari
paddingBottom: this.state.open ? 150 : 0,
},
}}>
<Sidebar {...this.props} />
</div>
</div>
</div>
<div
css={{
backgroundColor: colors.darker,
bottom: 0,
bottom: 44, // iOS Safari's inert "bottom 44px"
color: colors.brand,
display: 'none', // gets overriden at small screen sizes
left: 0,
left: 20,
cursor: 'pointer',
position: 'fixed',
right: 0,
width: '100%',
right: 20,
zIndex: 3,
maxWidth: 150,
marginLeft: 'auto',
borderRadius: 100,
border: '1px solid rgba(255, 255, 255, 0.1)',
[media.lessThan('small')]: smallScreenBottomBarStyles,
}}
onClick={this.toggleOpen}>
Expand All @@ -168,17 +248,18 @@ class StickyResponsiveSidebar extends Component {
alignSelf: 'center',
display: 'flex',
flexDirection: 'column',
color: colors.white,
}}>
<ChevronSvg
cssProps={{
transform: `translate(0, ${iconOffset}px) rotate(180deg)`,
transition: 'transform 0.5s ease',
transition: 'transform 0.2s 0.05s ease',
}}
/>
<ChevronSvg
cssProps={{
transform: `translate(0, ${0 - iconOffset}px)`,
transition: 'transform 0.5s ease',
transition: 'transform 0.2s 0.05s ease',
}}
/>
</div>
Expand All @@ -189,14 +270,23 @@ class StickyResponsiveSidebar extends Component {
<div
style={{
transform: `translate(0, ${labelOffset}px)`,
transition: 'transform 0.5s ease',
transition: 'transform 0.2s 0.05s ease',
}}>
<div
css={{
height: 40,
lineHeight: '40px',
}}>
{title}
<span
css={{
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
maxWidth: 90,
display: 'inline-block',
overflow: 'hidden',
}}>
{title}
</span>
</div>
<div
css={{
Expand Down
2 changes: 1 addition & 1 deletion www/src/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default class HTML extends Component {
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
content="width=device-width, initial-scale=1.0,viewport-fit=cover"
/>
<link rel="icon" href="/favicon.ico" />
{this.props.headComponents}
Expand Down
15 changes: 15 additions & 0 deletions www/src/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ const sharedStyles = {
marginTop: 40,
marginBottom: 120,

// Prevent a horizontal scroll bar in iOS Safari
[media.lessThan('small')]: {
overflowX: 'hidden',
marginLeft: -20,
marginRight: -20,
paddingLeft: 20,
paddingRight: 20,
},

[media.greaterThan('medium')]: {
marginTop: 50,
},
Expand Down Expand Up @@ -188,6 +197,12 @@ const sharedStyles = {
marginRight: -30,
paddingLeft: 15,
paddingRight: 15,

[media.size('xsmall')]: {
marginLeft: -20,
marginRight: -20,
borderRadius: 0,
},
},

'& a:not(.anchor):not(.gatsby-resp-image-link)': linkStyle,
Expand Down