diff --git a/content/tutorial/nav.yml b/content/tutorial/nav.yml
index f3570cc98..adc5cf3a7 100644
--- a/content/tutorial/nav.yml
+++ b/content/tutorial/nav.yml
@@ -1,6 +1,6 @@
- title: Tutorial
items:
- - id: tutorial
+ - id: before-we-start
title: Before We Start
href: /tutorial/tutorial.html#before-we-start
forceInternal: true
diff --git a/src/templates/components/Sidebar/Section.js b/src/templates/components/Sidebar/Section.js
index e212f03e1..a264ebfdb 100644
--- a/src/templates/components/Sidebar/Section.js
+++ b/src/templates/components/Sidebar/Section.js
@@ -9,88 +9,161 @@
'use strict';
-import React from 'react';
+import React, {Component} from 'react';
import {colors, media} from 'theme';
import MetaTitle from '../MetaTitle';
import ChevronSvg from '../ChevronSvg';
-// TODO Update isActive link as document scrolls past anchor tags
-// Maybe used 'hashchange' along with 'scroll' to set/update active links
+class Section extends Component {
+ constructor(props, context) {
+ super(props, context);
-const Section = ({
- createLink,
- isActive,
- location,
- onLinkClick,
- onSectionTitleClick,
- section,
-}) => (
-
-
- {section.title}
-
-
-
- {section.items.map(item => (
- - {
+ const nextItemTopOffset = itemTopOffsets[i + 1];
+ if (nextItemTopOffset) {
+ return (
+ window.scrollY >= itemTopOffset.offsetTop &&
+ window.scrollY < nextItemTopOffset.offsetTop
+ );
+ }
+ return window.scrollY >= itemTopOffset.offsetTop;
+ });
+ this.setState({
+ activeItemId: item ? item.id : null,
+ });
+ }
+
+ render() {
+ const {
+ createLink,
+ isActive,
+ location,
+ onLinkClick,
+ onSectionTitleClick,
+ section,
+ } = this.props;
+ const {activeItemId} = this.state;
+ return (
+
+
- {createLink({
- item,
- location,
- onLinkClick,
- section,
- })}
+ {section.title}
+
- {item.subitems.map(subitem => (
- -
- {createLink({
- item: subitem,
- location,
- onLinkClick,
- section,
- })}
-
- ))}
-
- )}
-
- ))}
-
-
-);
+ [media.lessThan('small')]: {
+ display: 'none',
+ },
+ }}
+ />
+
+
+ {section.items.map(item => (
+ -
+ {createLink({
+ item,
+ location,
+ onLinkClick,
+ section,
+ isActive: activeItemId === item.id,
+ })}
+
+ {item.subitems && (
+
+ {item.subitems.map(subitem => (
+ -
+ {createLink({
+ item: subitem,
+ location,
+ onLinkClick,
+ section,
+ isActive: activeItemId === subitem.id,
+ })}
+
+ ))}
+
+ )}
+
+ ))}
+
+
+ );
+ }
+}
+
+const _getItemIds = items =>
+ items
+ .map(item => {
+ let subItemIds = [];
+ if (item.subitems) {
+ subItemIds = item.subitems.map(subitem => subitem.id);
+ }
+ return [item.id, ...subItemIds];
+ })
+ .reduce((prev, current) => prev.concat(current));
+
+const _getElementTopOffsetsById = ids =>
+ ids
+ .map(id => {
+ const element = document.getElementById(id);
+ if (!element) {
+ return null;
+ }
+ return {
+ id,
+ offsetTop: element.offsetTop,
+ };
+ })
+ .filter(item => item);
export default Section;
diff --git a/src/utils/createLink.js b/src/utils/createLink.js
index 88bac8251..a2871d5fb 100644
--- a/src/utils/createLink.js
+++ b/src/utils/createLink.js
@@ -65,15 +65,22 @@ const createLinkDocs = ({item, location, section}) => {
);
};
-const createLinkTutorial = ({item, location, onLinkClick, section}) => {
- const isActive = isItemActive(location, item);
+const createLinkTutorial = ({
+ item,
+ location,
+ onLinkClick,
+ section,
+ isActive,
+}) => {
+ const active =
+ typeof isActive === 'boolean' ? isActive : isItemActive(location, item);
return (
- {isActive && }
+ {active && }
{item.title}
);