From 00c77800c9f5390de26feceb7fec06e06e90236e Mon Sep 17 00:00:00 2001 From: Andrej Badin Date: Fri, 20 May 2016 02:41:21 -0700 Subject: [PATCH] Improve Docs navigation on handheld devices. Summary: Fixes #7519 JS detects handheld device by sniffing UA string (very primitive detection). If on handheld device, event listener is registered. Event handler toggles Docs Navigation overlay after clicking on "Docs" nav button. Original Docs Navigation panel is taken out of the natural page flow using pure CSS and is styled to look "good" on device. As a result of this, Navigation overlay is ONLY visible when you are at Docs page, otherwise "Docs" nav button takes you Docs page first. iPhone/iPad previews ![iphone](https://cloud.githubusercontent.com/assets/829963/15409630/f1a64b1a-1e15-11e6-92eb-f85c5cd06754.gif) ![ipad](https://cloud.githubusercontent.com/assets/829963/15409631/f1a6f952-1e15-11e6-8f5c-6f89f54e6814.gif) Closes https://github.com/facebook/react-native/pull/7640 Differential Revision: D3325440 Pulled By: vjeux fbshipit-source-id: a06b21d743d56bfea5db5b750836856c3af9bbe2 --- website/core/DocsSidebar.js | 43 ++++--- website/core/HeaderLinks.js | 5 +- website/src/react-native/css/react-native.css | 105 +++++++++++++++--- website/src/react-native/js/scripts.js | 18 +++ 4 files changed, 133 insertions(+), 38 deletions(-) diff --git a/website/core/DocsSidebar.js b/website/core/DocsSidebar.js index d8640e40d..7b643aba9 100644 --- a/website/core/DocsSidebar.js +++ b/website/core/DocsSidebar.js @@ -69,32 +69,31 @@ var DocsSidebar = React.createClass({ }, getLink: function(metadata) { - if (metadata.permalink.match(/^https?:/)) { - return metadata.permalink; - } - return metadata.permalink + '#content'; + return metadata.permalink; }, render: function() { return
- {this.getCategories().map((category) => -
-

{category.name}

- -
- )} +
+ {this.getCategories().map((category) => +
+

{category.name}

+ +
+ )} +
; } }); diff --git a/website/core/HeaderLinks.js b/website/core/HeaderLinks.js index b5dbffde9..2cb72850b 100644 --- a/website/core/HeaderLinks.js +++ b/website/core/HeaderLinks.js @@ -14,7 +14,7 @@ var AlgoliaDocSearch = require('AlgoliaDocSearch'); var HeaderLinks = React.createClass({ linksInternal: [ - {section: 'docs', href: 'docs/getting-started.html', text: 'Docs'}, + {section: 'docs', href: 'docs/getting-started.html', text: 'Docs', target: '.nav-docs'}, {section: 'support', href: 'support.html', text: 'Support'}, {section: 'showcase', href: 'showcase.html', text: 'Showcase'}, {section: 'blog', href: 'blog/', text: 'Blog'}, @@ -30,7 +30,8 @@ var HeaderLinks = React.createClass({
  • + className={link.section === this.props.section ? 'active' : ''} + data-target={link.target}> {link.text}
  • diff --git a/website/src/react-native/css/react-native.css b/website/src/react-native/css/react-native.css index 8ba8d434a..c768d8370 100644 --- a/website/src/react-native/css/react-native.css +++ b/website/src/react-native/css/react-native.css @@ -481,6 +481,92 @@ h1:hover .hash-link, h2:hover .hash-link, h3:hover .hash-link, h4:hover .hash-li border-bottom: 0; } +@media screen and (max-device-width: 960px) { + .nav-docs { + position: fixed; + z-index: 90; + top: 0; + left: 0; + width: 100%; + height: 100%; + margin: 0; + padding: 53px 0 0 0; + background: #3B3738; + /* Transition these properties */ + transition: opacity 0.3s, visibility 0.3s; + visibility: hidden; + opacity: 0; + } + + .nav-docs-viewport { + border-top: 1px solid rgb(5, 165, 209); + height: 100%; + padding: 25px; + overflow: scroll; + -webkit-overflow-scrolling: touch; + top: -30px; + position: relative; + transition: top 0.3s; + } + + /* Active state */ + .nav-docs.in { + visibility: visible; + opacity: 1; + } + + .nav-docs.in .nav-docs-viewport { + top: 0; + } + + .nav-docs * { + -webkit-font-smoothing: antialiased; + } + + .nav-docs-section + .nav-docs-section { + margin-top: 50px; + } + + .nav-docs-section li { + margin: 5px 0; + } + + .nav-docs-section h3, + .nav-docs-section a { + color: white; + } + + .nav-docs-section h3 { + border-bottom: 1px solid white; + margin-bottom: 10px; + opacity: 0.3; + } + + .nav-docs-section a { + margin-right: 25px; + font-size: 120%; + padding: 5px 0; + } + + .nav-docs-section a.active { + border-bottom-style: solid; + border-bottom-width: 1px; + color: rgb(5, 165, 209); + } +} + +@media screen and (min-device-width: 641px) and (max-device-width: 1024px) { + .nav-docs-section ul { + display: flex; + flex-wrap: wrap; + } + + /* Display 2 columns on tablet */ + .nav-docs-section li { + width: 50%; + } +} + .nav-blog li { margin-bottom: 5px; } @@ -999,13 +1085,13 @@ small code, li code, p code { outline: none; } -@media screen and (max-width: 960px) { - .nav-main { - position: static; +@media screen and (max-width: 680px) { + .container { + padding-top: 100px; } - .container { - padding-top: 0; + .nav-docs { + padding-top: 103px; } } @@ -1345,15 +1431,6 @@ div[data-twttr-id] iframe { border: none; padding: 0; } - .nav-docs h3 { - margin: 0; - } - .nav-docs { - float: none; - width: auto; - margin-top: -8px; - margin-bottom: 20px; - } h1 { font-size: 30px; line-height: 30px; diff --git a/website/src/react-native/js/scripts.js b/website/src/react-native/js/scripts.js index 9bed77965..0932c31ff 100644 --- a/website/src/react-native/js/scripts.js +++ b/website/src/react-native/js/scripts.js @@ -7,6 +7,10 @@ document.addEventListener('DOMContentLoaded', init); function init() { + if (isMobile()) { + document.querySelector('.nav-site-wrapper a[data-target]').addEventListener('click', toggleTargetNav); + } + var backdrop = document.querySelector('.modal-backdrop'); if (!backdrop) return; @@ -42,4 +46,18 @@ modal.classList.remove('modal-open'); } + function toggleTargetNav(event) { + var target = document.body.querySelector(event.target.getAttribute('data-target')); + + if (target) { + event.preventDefault(); + target.classList.toggle('in'); + } + } + + // Primitive mobile detection + function isMobile() { + return ( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ); + } + }());