diff --git a/package.json b/package.json index d80a8de7..c267adf9 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "sanitize.css": "^5.0.0", "sharetribe-scripts": "1.0.14", "sharetribe-sdk": "git+ssh://git@github.com/sharetribe/sharetribe-sdk-js#acec122c4c1279bfecb411b027f7bb8928b6b44b", + "smoothscroll-polyfill": "^0.4.0", "source-map-support": "^0.5.0", "url": "^0.11.0" }, diff --git a/src/Routes.js b/src/Routes.js index 8452babb..3983245a 100644 --- a/src/Routes.js +++ b/src/Routes.js @@ -37,7 +37,36 @@ const callLoadData = props => { } }; +const setPageScrollPosition = location => { + if (!location.hash) { + // No hash, scroll to top + window.scroll({ + top: 0, + left: 0, + }); + } else { + const el = document.querySelector(location.hash); + if (el) { + // Found element with the given fragment identifier, scrolling + // to that element. + // + // NOTE: This isn't foolproof. It works when navigating within + // the application between pages and within a single page. It + // also works with the initial page load. However, it doesn't + // seem work work properly when refreshing the page, at least + // not in Chrome. + // + // TODO: investigate why the scrolling fails on refresh + el.scrollIntoView({ + block: 'start', + behavior: 'smooth', + }); + } + } +}; + const handleLocationChanged = (dispatch, location) => { + setPageScrollPosition(location); const url = canonicalRoutePath(routeConfiguration(), location); dispatch(locationChanged(location, url)); }; diff --git a/src/components/Page/Page.js b/src/components/Page/Page.js index fda88e49..51b1a900 100644 --- a/src/components/Page/Page.js +++ b/src/components/Page/Page.js @@ -14,11 +14,6 @@ import facebookImage from '../../assets/saunatimeFacebook-1200x630.jpg'; import twitterImage from '../../assets/saunatimeTwitter-600x314.jpg'; import css from './Page.css'; -const scrollToTop = () => { - // Todo: this might need fine tuning later - window.scrollTo(0, 0); -}; - const preventDefault = e => { e.preventDefault(); }; @@ -34,8 +29,6 @@ const twitterPageURL = siteTwitterHandle => { class PageComponent extends Component { componentDidMount() { - this.historyUnlisten = this.props.history.listen(() => scrollToTop()); - // By default a dropped file is loaded in the browser window as a // file URL. We want to prevent this since it might loose a lot of // data the user has typed but not yet saved. Preventing requires @@ -45,9 +38,6 @@ class PageComponent extends Component { } componentWillUnmount() { - if (this.historyUnlisten) { - this.historyUnlisten(); - } document.removeEventListener('dragover', preventDefault); document.removeEventListener('drop', preventDefault); } diff --git a/src/index.js b/src/index.js index 3ef4df4d..77091f26 100644 --- a/src/index.js +++ b/src/index.js @@ -95,6 +95,7 @@ if (typeof window !== 'undefined') { const store = configureStore(initialState, sdk, analyticsHandlers); setupStripe(); + require('smoothscroll-polyfill').polyfill(); render(store); if (config.dev) { diff --git a/yarn.lock b/yarn.lock index e35907f3..9f058338 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7270,6 +7270,10 @@ slide@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" +smoothscroll-polyfill@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.0.tgz#dcda9fe6e9f5d660b886b79be043d40c68fe57d2" + sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"