Refactored Installation page to no longer use tabs (#11050)
Brian Vaughn committed
Oct 2, 2017 at 15:45 UTC
75ad1a9cd685faf3865ab9fb52fb71e3ebdcabae
3 files changed
+9
-333
docs/docs/installation.md
+9
-104
@@ -11,114 +11,24 @@ redirect_from:
11
- "docs/environments.html"
12
next: hello-world.html
13
---
14
-<style>
15
- .tab-hidden {
16
- display: none;
17
- }
18
-</style>
14
15
React is flexible and can be used in a variety of projects. You can create new apps with it, but you can also gradually introduce it into an existing codebase without doing a rewrite.
16
22
-<div class="toggler">
23
- <style>
24
- .toggler li {
25
- display: inline-block;
26
- position: relative;
27
- top: 1px;
28
- padding: 10px;
29
- margin: 0px 2px 0px 2px;
30
- border-bottom-color: transparent;
31
- border-radius: 3px 3px 0px 0px;
32
- color: #373940;
33
- background-color: transparent;
34
- font-size: 0.99em;
35
- cursor: pointer;
36
- opacity: 0.5;
37
- }
38
- .toggler li:active {
39
- opacity: 1;
40
- }
41
- .toggler li:first-child {
42
- margin-left: 0;
43
- }
44
- .toggler li:last-child {
45
- margin-right: 0;
46
- }
47
- .toggler ul {
48
- display: inline-block;
49
- list-style-type: none;
50
- margin: 0;
51
- border-bottom: 1px solid #ececec;
52
- cursor: default;
53
- margin: 0 -15px;
54
- padding: 0 15px;
55
- }
56
- @media screen and (max-width: 960px) {
57
- .toggler li,
58
- .toggler li:first-child,
59
- .toggler li:last-child {
60
- display: block;
61
- border-radius: 3px;
62
- margin: 2px 0px 2px 0px;
63
- }
64
- }
65
- .display-target-fiddle .toggler .button-fiddle:focus,
66
- .display-target-newapp .toggler .button-newapp:focus,
67
- .display-target-existingapp .toggler .button-existingapp:focus {
68
- opacity: 1;
69
- }
70
- .display-target-fiddle .toggler .button-fiddle,
71
- .display-target-newapp .toggler .button-newapp,
72
- .display-target-existingapp .toggler .button-existingapp {
73
- opacity: 1;
74
- font-weight: 700;
75
- }
76
- section {
77
- display: none;
78
- }
79
- .display-target-fiddle .fiddle,
80
- .display-target-newapp .newapp,
81
- .display-target-existingapp .existingapp {
82
- display: block;
83
- }
84
- </style>
85
- <script>
86
- document.querySelector('.toggler').parentElement.className += ' display-target-fiddle';
87
- </script>
88
- <span>Which of these options best describes what you want to do?</span>
89
- <br />
90
- <br />
91
- <ul role="tablist" >
92
- <li id="fiddle" class="button-fiddle" aria-selected="false" role="tab" tabindex="0" aria-controls="fiddletab"
93
- onclick="display('target', 'fiddle')" onkeyup="keyToggle(event, 'fiddle', 'existingapp', 'newapp')">
94
- Try React
95
- </li>
96
- <li id="newapp" class="button-newapp" aria-selected="false" role="tab" tabindex="-1" aria-controls="newapptab"
97
- onclick="display('target', 'newapp')" onkeyup="keyToggle(event, 'newapp', 'fiddle', 'existingapp')">
98
- Create a New App
99
- </li>
100
- <li id="existingapp" class="button-existingapp" aria-selected="false" role="tab" tabindex="-1" aria-controls="existingapptab"
101
- onclick="display('target', 'existingapp')" onkeyup="keyToggle(event, 'existingapp', 'newapp', 'fiddle')">
102
- Add React to an Existing App
103
- </li>
104
- </ul>
105
-</div>
106
-
107
-<div>
108
-<section id="fiddletab" role="tabpanel" class="fiddle">
109
-
110
-### Trying Out React
17
+Here are a couple of ways to get started:
18
+
19
+* [Try React](#trying-out-react)
20
+* [Create a New App](#creating-a-new-application)
21
+* [Add React to an Existing App](#adding-react-to-an-existing-application)
22
+
23
+## Trying Out React
24
25
If you're just interested in playing around with React, you can use CodePen. Try starting from [this Hello World example code](http://codepen.io/gaearon/pen/rrpgNB?editors=0010). You don't need to install anything; you can just modify the code and see if it works.
26
27
If you prefer to use your own text editor, you can also <a href="https://raw.githubusercontent.com/facebook/react/master/docs/downloads/single-file-example.html" download="hello.html">download this HTML file</a>, edit it, and open it from the local filesystem in your browser. It does a slow runtime code transformation, so don't use it in production.
28
29
If you want to use it for a full application, there are two popular ways to get started with React: using Create React App, or adding it to an existing application.
117
-</section>
30
119
-<section id="newapptab" role="tabpanel" class="newapp">
120
-
121
-### Creating a New Application
31
+## Creating a New Application
32
33
[Create React App](http://github.com/facebookincubator/create-react-app) is the best way to start building a new React single page application. It sets up your development environment so that you can use the latest JavaScript features, provides a nice developer experience, and optimizes your app for production.
34
@@ -133,11 +43,8 @@ npm start
43
Create React App doesn't handle backend logic or databases; it just creates a frontend build pipeline, so you can use it with any backend you want. It uses build tools like Babel and webpack under the hood, but works with zero configuration.
44
45
When you're ready to deploy to production, running `npm run build` will create an optimized build of your app in the `build` folder. You can learn more about Create React App [from its README](https://github.com/facebookincubator/create-react-app#create-react-app-) and the [User Guide](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#table-of-contents).
136
-</section>
137
-
138
-<section id="existingapptab" role="tabpanel" class="existingapp">
46
140
-### Adding React to an Existing Application
47
+## Adding React to an Existing Application
48
49
You don't need to rewrite your app to start using React.
50
@@ -249,5 +156,3 @@ We also recommend to verify that the CDN you are using sets the `Access-Control-
156

157
158
This enables a better [error handling experience](/blog/2017/07/26/error-handling-in-react-16.html) in React 16 and later.
252
-</section>
253
-</div>
www/gatsby-node.js
-9
@@ -33,7 +33,6 @@ exports.createPages = async ({graphql, boundActionCreators}) => {
33
const docsTemplate = resolve('./src/templates/docs.js');
34
const tutorialTemplate = resolve('./src/templates/tutorial.js');
35
const homeTemplate = resolve('./src/templates/home.js');
36
- const installationTemplate = resolve('./src/templates/installation.js');
36
37
const allMarkdown = await graphql(
38
`
@@ -69,14 +68,6 @@ exports.createPages = async ({graphql, boundActionCreators}) => {
68
slug,
69
},
70
});
72
- } else if (slug === 'docs/installation.html') {
73
- createPage({
74
- path: slug,
75
- component: installationTemplate,
76
- context: {
77
- slug,
78
- },
79
- });
71
} else if (slug === 'docs/error-decoder.html') {
72
// No-op so far as markdown templates go.
73
// Error codes are managed by a page (which gets created automatically).
www/src/templates/installation.js
deleted
-220
@@ -1,220 +0,0 @@
1
-/**
2
- * Copyright (c) 2013-present, Facebook, Inc.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @emails react-core
8
-*/
9
-
10
-'use strict';
11
-
12
-import Container from 'components/Container';
13
-import Flex from 'components/Flex';
14
-import MarkdownHeader from 'components/MarkdownHeader';
15
-import NavigationFooter from 'templates/components/NavigationFooter';
16
-import PropTypes from 'prop-types';
17
-import React, {Component} from 'react';
18
-import StickyResponsiveSidebar from 'components/StickyResponsiveSidebar';
19
-import TitleAndMetaTags from 'components/TitleAndMetaTags';
20
-import {createLinkDocs} from 'utils/createLink';
21
-import findSectionForPath from 'utils/findSectionForPath';
22
-import {sectionListDocs} from 'utils/sectionList';
23
-import {sharedStyles} from 'theme';
24
-import createOgUrl from 'utils/createOgUrl';
25
-
26
-// HACK: copied from 'installation.md'
27
-// TODO: clean this up.
28
-function setSelected(value) {
29
- var tabs = document.querySelectorAll('li[role="tab"]');
30
- for (var i = 0; i < tabs.length; ++i) {
31
- var tab = tabs[i];
32
- if (tab.className === 'button-' + value) {
33
- tabs[i].setAttribute('aria-selected', 'true');
34
- tabs[i].setAttribute('tabindex', '0');
35
- } else {
36
- tabs[i].setAttribute('aria-selected', 'false');
37
- tabs[i].setAttribute('tabindex', '-1');
38
- }
39
- }
40
-}
41
-
42
-function keyToggle(e, value, prevTab, nextTab) {
43
- // left arrow <-
44
- if (e.keyCode === 37) {
45
- document.getElementById(prevTab).focus();
46
- display('target', prevTab);
47
- }
48
- // right arrow ->
49
- if (e.keyCode === 39) {
50
- document.getElementById(nextTab).focus();
51
- display('target', nextTab);
52
- }
53
-}
54
-
55
-function display(type, value) {
56
- setSelected(value);
57
- var container = document.getElementsByTagName('section')[0].parentNode
58
- .parentNode;
59
- container.className =
60
- 'display-' +
61
- type +
62
- '-' +
63
- value +
64
- ' ' +
65
- container.className.replace(RegExp('display-' + type + '-[a-z]+ ?'), '');
66
-}
67
-
68
-var foundHash = false;
69
-function selectTabForHashLink(location) {
70
- var hashLinks = document.querySelectorAll('a.anchor');
71
- for (var i = 0; i < hashLinks.length && !foundHash; ++i) {
72
- if (location && hashLinks[i].hash === location.hash) {
73
- var parent = hashLinks[i].parentElement;
74
- while (parent) {
75
- if (parent.tagName === 'SECTION') {
76
- var target = null;
77
- if (parent.className.indexOf('fiddle') > -1) {
78
- target = 'fiddle';
79
- } else if (parent.className.indexOf('newapp') > -1) {
80
- target = 'newapp';
81
- } else if (parent.className.indexOf('existingapp') > -1) {
82
- target = 'existingapp';
83
- } else {
84
- break; // assume we don't have anything.
85
- }
86
- display('target', target);
87
- foundHash = true;
88
- break;
89
- }
90
- parent = parent.parentElement;
91
- }
92
- }
93
- }
94
-}
95
-
96
-// HACK Expose toggle functions global for markup-defined event handlers.
97
-// Don't acceess the 'window' object without checking first though,
98
-// Because it would break the (Node only) Gatsby build step.
99
-if (typeof window !== 'undefined') {
100
- window.keyToggle = keyToggle;
101
- window.display = display;
102
-}
103
-
104
-class InstallationPage extends Component {
105
- componentDidMount() {
106
- const location = this.props.location;
107
- // If we are coming to the page with a hash in it (i.e. from a search, for example), try to get
108
- // us as close as possible to the correct platform and dev os using the hashtag and section walk up.
109
- if (location && location.hash !== '' && location.hash !== 'content') {
110
- // content is default
111
- // Hash links are added a bit later so we wait for them.
112
- // HACK we don't have a window object if/when Gatsby executes this in node
113
- if (
114
- typeof window !== 'undefined' &&
115
- typeof window.addEventListener === 'function'
116
- ) {
117
- window.addEventListener(
118
- 'DOMContentLoaded',
119
- selectTabForHashLink.bind(null, location),
120
- );
121
- }
122
- }
123
- display('target', 'fiddle');
124
- }
125
-
126
- render() {
127
- const {data, location} = this.props;
128
- const {markdownRemark} = data;
129
-
130
- return (
131
- <Flex
132
- direction="column"
133
- grow="1"
134
- shrink="0"
135
- halign="stretch"
136
- css={{
137
- width: '100%',
138
- flex: '1 0 auto',
139
- position: 'relative',
140
- zIndex: 0,
141
- }}>
142
- <TitleAndMetaTags
143
- title="Installation - React"
144
- ogUrl={createOgUrl(markdownRemark.fields.slug)}
145
- />
146
- <div css={{flex: '1 0 auto'}}>
147
- <Container>
148
- <div css={sharedStyles.articleLayout.container}>
149
- <Flex type="article" direction="column" grow="1" halign="stretch">
150
- <MarkdownHeader title={markdownRemark.frontmatter.title} />
151
-
152
- <div css={sharedStyles.articleLayout.content}>
153
- <div
154
- css={[sharedStyles.markdown]}
155
- dangerouslySetInnerHTML={{__html: markdownRemark.html}}
156
- />
157
- {markdownRemark.fields.path &&
158
- <div css={{marginTop: 80}}>
159
- <a
160
- css={sharedStyles.articleLayout.editLink}
161
- href={`https://github.com/facebook/react/tree/master/docs/${markdownRemark.fields.path}`}>
162
- Edit this page
163
- </a>
164
- </div>}
165
- </div>
166
- </Flex>
167
-
168
- <div css={sharedStyles.articleLayout.sidebar}>
169
- <StickyResponsiveSidebar
170
- createLink={createLinkDocs}
171
- defaultActiveSection={findSectionForPath(
172
- location.pathname,
173
- sectionListDocs,
174
- )}
175
- location={location}
176
- sectionList={sectionListDocs}
177
- title="Installation"
178
- />
179
- </div>
180
- </div>
181
- </Container>
182
- </div>
183
-
184
- {/* TODO Read prev/next from index map, not this way */}
185
- {(markdownRemark.frontmatter.next || markdownRemark.frontmatter.prev) &&
186
- <NavigationFooter
187
- location={location}
188
- next={markdownRemark.frontmatter.next}
189
- prev={markdownRemark.frontmatter.prev}
190
- />}
191
- </Flex>
192
- );
193
- }
194
-}
195
-
196
-InstallationPage.propTypes = {
197
- data: PropTypes.shape({markdownRemark: PropTypes.object.isRequired})
198
- .isRequired,
199
- location: PropTypes.object.isRequired,
200
-};
201
-
202
-// eslint-disable-next-line no-undef
203
-export const pageQuery = graphql`
204
- query InstallationMarkdown($slug: String!) {
205
- markdownRemark(fields: { slug: { eq: $slug } }) {
206
- html
207
- frontmatter {
208
- title
209
- next
210
- prev
211
- }
212
- fields {
213
- path
214
- slug
215
- }
216
- }
217
- }
218
-`;
219
-
220
-export default InstallationPage;