Skip to content

Commit ee37ed4

Browse files
authored
React hooks (codesandbox#1505)
* start * small issues * update names * Update yarn.lock * Set description at compile time * Add picked modal * Fix building * Fix sandbox modal loading * Fix lint * Force deploy * Tweak title and description * ad header * ad header * ad header * small fixes * responsive * Update yarn.lock
1 parent 31d4484 commit ee37ed4

File tree

11 files changed

+276
-51
lines changed

11 files changed

+276
-51
lines changed

packages/homepage/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ node_modules
66
public/
77
.DS_Store
88
yarn-error.log
9+
.env

packages/homepage/gatsby-config.js

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require('dotenv').config();
2+
13
module.exports = {
24
siteMetadata: {
35
title: `CodeSandbox`,
@@ -25,25 +27,8 @@ module.exports = {
2527
{
2628
resolve: `gatsby-remark-images`,
2729
options: {
28-
// It's important to specify the maxWidth (in pixels) of
29-
// the content container as this plugin uses this as the
30-
// base for generating different widths of each image.
3130
maxWidth: 740,
32-
// Remove the default behavior of adding a link to each
33-
// image.
3431
linkImagesToOriginal: true,
35-
// Analyze images' pixel density to make decisions about
36-
// target image size. This is what GitHub is doing when
37-
// embedding images in tickets. This is a useful setting
38-
// for documentation pages with a lot of screenshots.
39-
// It can have unintended side effects on high pixel
40-
// density artworks.
41-
//
42-
// Example: A screenshot made on a retina screen with a
43-
// resolution of 144 (e.g. Macbook) and a width of 100px,
44-
// will be rendered at 50px.
45-
//
46-
// Defaults to false.
4732
sizeByPixelDensity: true,
4833
},
4934
},
@@ -91,5 +76,19 @@ module.exports = {
9176
fonts: [`Poppins:600,700,800`, `source sans pro:300,400,500,600,700`],
9277
},
9378
},
79+
{
80+
resolve: `gatsby-source-airtable`,
81+
options: {
82+
apiKey: 'keyJugfwdJzOyL7Aa',
83+
tables: [
84+
{
85+
baseId: `app7kKUn5uIviyA1f`,
86+
tableName: `Table`,
87+
tableView: `Grid view`,
88+
queryName: `starters`,
89+
},
90+
],
91+
},
92+
},
9493
],
9594
};

packages/homepage/gatsby-node.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,6 @@ exports.onCreateWebpackConfig = ({
186186
},
187187
];
188188

189-
config.resolve.modules = [
190-
...config.resolve.modules,
191-
'node_modules',
192-
'src',
193-
'standalone-packages',
194-
];
195-
196189
// This will completely replace the webpack config with the modified object.
197190
actions.replaceWebpackConfig(config);
198191
};

packages/homepage/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"gatsby-remark-embed-youtube": "^0.0.7",
2525
"gatsby-remark-images": "^1.5.34",
2626
"gatsby-remark-prismjs": "^1.2.11",
27+
"gatsby-source-airtable": "^2.0.2",
2728
"gatsby-source-filesystem": "^2.0.10",
2829
"gatsby-transformer-remark": "^2.1.15",
2930
"gatsby-transformer-sharp": "^2.1.9",
@@ -36,6 +37,7 @@
3637
"react-router-dom": "^4.2.2",
3738
"react-slick": "^0.23.2",
3839
"react-spring": "^6.1.10",
40+
"react-text-loop": "^2.0.1",
3941
"react-transition-group": "^2.2.1",
4042
"react-typography": "^0.16.13",
4143
"slick-carousel": "^1.8.1",
@@ -53,12 +55,14 @@
5355
"scripts": {
5456
"build": "gatsby build",
5557
"build:clean": "rimraf public",
58+
"start:dev": "LOCAL_SERVER=1 LOCAL_DEV=1 gatsby develop",
5659
"start": "gatsby develop",
5760
"lint": "eslint .",
5861
"format": "prettier --trailing-comma es5 --single-quote --write 'src/**/*.js'",
5962
"test": "echo \"Todo: no test specified\" && exit 0"
6063
},
6164
"devDependencies": {
65+
"dotenv": "^6.2.0",
6266
"extract-text-webpack-plugin": "1.0.1",
6367
"gatsby-plugin-remove-trailing-slashes": "^2.0.6",
6468
"gatsby-source-medium": "^2.0.2",
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from 'react';
2+
import TextLoop from 'react-text-loop';
3+
import styled from 'styled-components';
4+
5+
const ShuffleWords = styled.section`
6+
color: white;
7+
font-size: 2em;
8+
font-family: 'dank mono', 'dm', monospace;
9+
text-align: center;
10+
margin-top: 2rem;
11+
margin-bottom: 6rem;
12+
text-align: center;
13+
14+
@media screen and (max-width: 900px) {
15+
font-size: 1.5rem;
16+
}
17+
18+
@media screen and (max-width: 700px) {
19+
font-size: 1.2rem;
20+
}
21+
`;
22+
23+
const shuffle = a => {
24+
for (let i = a.length - 1; i > 0; i--) {
25+
const j = Math.floor(Math.random() * (i + 1));
26+
[a[i], a[j]] = [a[j], a[i]];
27+
}
28+
return a;
29+
};
30+
31+
const words = [
32+
'State',
33+
'Effect',
34+
'Ref',
35+
'Context',
36+
'Reducer',
37+
'Memo',
38+
'Callback',
39+
'ImperativeHandle',
40+
'LayoutEffect',
41+
'DebugValue',
42+
];
43+
44+
export default () => (
45+
<ShuffleWords>
46+
import {'{ '}
47+
use
48+
<TextLoop interval={1500}>{shuffle(words).map(word => word)}</TextLoop>{' '}
49+
{' }'} from {"'"}
50+
react
51+
{"'"}
52+
</ShuffleWords>
53+
);

packages/homepage/src/pages/explore.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,6 @@ export default class Explore extends React.PureComponent {
9292
});
9393
};
9494

95-
selectSandbox = ({ id, title, description, screenshotUrl }) => {
96-
this.setState({
97-
selectedSandbox: { id, title, description, screenshotUrl },
98-
});
99-
};
100-
10195
openPreviousSandbox = currentIndex => () => {
10296
this.openSandbox(currentIndex - 1);
10397
};
@@ -106,6 +100,12 @@ export default class Explore extends React.PureComponent {
106100
this.openSandbox(currentIndex + 1);
107101
};
108102

103+
selectSandbox = ({ id, title, description, screenshotUrl }) => {
104+
this.setState({
105+
selectedSandbox: { id, title, description, screenshotUrl },
106+
});
107+
};
108+
109109
navigateToNextSandbox = () => {
110110
this.setState(state => ({
111111
featuredSandboxIndex: state.featuredSandboxIndex + 1,
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import React from 'react';
2+
import { graphql } from 'gatsby';
3+
4+
import TitleAndMetaTags from '../components/TitleAndMetaTags';
5+
import PageContainer from '../components/PageContainer';
6+
import { Heading2 } from '../components/headings';
7+
8+
import Layout from '../components/layout';
9+
import SandboxModal from '../screens/explore/SandboxModal';
10+
import ShuffleWords from './_shuffleWords';
11+
import WideSandbox from '../screens/explore/WideSandbox';
12+
import { Container, Sandboxes } from './_explore.elements';
13+
14+
export default class extends React.PureComponent {
15+
state = {
16+
sandboxes: this.props.data.allAirtable.edges.map(s => ({
17+
...s.node.data,
18+
title: s.node.data.title,
19+
})),
20+
renderModal: false,
21+
};
22+
23+
componentDidMount() {
24+
// We need to do this for SSR, the modal can't be rendered when using SSR,
25+
// we cannot just put a check in `render` because that would mean that client
26+
// render and server render are not the same. So we force a rerender.
27+
// eslint-disable-next-line
28+
this.setState({ renderModal: true });
29+
}
30+
31+
openSandbox = index => {
32+
const sandbox = this.state.sandboxes[index];
33+
const { id, title, description } = sandbox;
34+
35+
this.setState({
36+
selectedSandbox: {
37+
id,
38+
title,
39+
description,
40+
screenshotUrl: sandbox.screenshot_url,
41+
},
42+
});
43+
};
44+
45+
openPreviousSandbox = currentIndex => () => {
46+
this.openSandbox(currentIndex - 1);
47+
};
48+
49+
openNextSandbox = currentIndex => () => {
50+
this.openSandbox(currentIndex + 1);
51+
};
52+
53+
selectSandbox = ({ id, title, description, screenshotUrl }) => {
54+
this.setState({
55+
selectedSandbox: { id, title, description, screenshotUrl },
56+
});
57+
};
58+
59+
getCurrentIndex = () =>
60+
this.state.selectedSandbox
61+
? this.state.sandboxes.findIndex(
62+
s => this.state.selectedSandbox.id === s.id
63+
)
64+
: -1;
65+
66+
closeModal = () => {
67+
this.setState({ selectedSandbox: undefined });
68+
};
69+
70+
render() {
71+
const { sandboxes, selectedSandbox } = this.state;
72+
73+
const currentIndex = this.getCurrentIndex();
74+
75+
return (
76+
<Layout>
77+
<Container>
78+
<TitleAndMetaTags
79+
description="A showcase of the amazing uses for React Hooks!"
80+
title="React Hooks Examples - CodeSandbox"
81+
/>
82+
83+
{this.state.renderModal && (
84+
<SandboxModal
85+
onClose={this.closeModal}
86+
sandboxId={selectedSandbox && selectedSandbox.id}
87+
screenshotUrl={selectedSandbox && selectedSandbox.screenshotUrl}
88+
title={selectedSandbox && selectedSandbox.title}
89+
description={selectedSandbox && selectedSandbox.description}
90+
openPreviousSandbox={
91+
currentIndex > 0 &&
92+
currentIndex !== -1 &&
93+
this.openPreviousSandbox(currentIndex)
94+
}
95+
openNextSandbox={
96+
currentIndex < this.state.sandboxes.length - 1 &&
97+
currentIndex !== -1 &&
98+
this.openNextSandbox(currentIndex)
99+
}
100+
/>
101+
)}
102+
103+
<PageContainer as="main" width={1440}>
104+
<Heading2
105+
css={`
106+
text-align: center;
107+
`}
108+
>
109+
React Hooks Examples
110+
</Heading2>
111+
<ShuffleWords />
112+
<Sandboxes>
113+
{sandboxes.map(sandbox => (
114+
<WideSandbox
115+
key={sandbox.id}
116+
pickSandbox={this.selectSandbox}
117+
sandbox={sandbox}
118+
/>
119+
))}
120+
</Sandboxes>
121+
</PageContainer>
122+
</Container>
123+
</Layout>
124+
);
125+
}
126+
}
127+
export const query = graphql`
128+
{
129+
allAirtable {
130+
edges {
131+
node {
132+
data {
133+
id
134+
title
135+
description
136+
template
137+
}
138+
}
139+
}
140+
}
141+
}
142+
`;

packages/homepage/src/screens/explore/SandboxModal.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
TemplateLogo,
3131
StyledRightArrow,
3232
StyledLeftArrow,
33-
SandboxInfoContianer,
33+
SandboxInfoContainer,
3434
} from './_SandboxModal.elements';
3535

3636
export default class SandboxModal extends React.PureComponent {
@@ -123,6 +123,8 @@ export default class SandboxModal extends React.PureComponent {
123123
listenForInitialized = e => {
124124
if (e && e.data === 'ready') {
125125
this.resolveFrameInitializedPromise();
126+
127+
this.fetchSandbox();
126128
}
127129
};
128130

@@ -191,7 +193,7 @@ export default class SandboxModal extends React.PureComponent {
191193
)}
192194
</Spring>
193195

194-
<SandboxInfoContianer>
196+
<SandboxInfoContainer>
195197
<SandboxInfo>
196198
<SandboxTitle>{this.props.title}</SandboxTitle>
197199
<SandboxDescription>{this.props.description}</SandboxDescription>
@@ -218,7 +220,7 @@ export default class SandboxModal extends React.PureComponent {
218220
</Spring>
219221
)}
220222
</StatsContainer>
221-
</SandboxInfoContianer>
223+
</SandboxInfoContainer>
222224
<Footer>
223225
{sandbox ? (
224226
<FooterInfo>

packages/homepage/src/screens/explore/WideSandbox.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,21 @@ export default class WideSandbox extends React.PureComponent {
2323
imageLoaded: false,
2424
};
2525

26-
getTitle = () =>
27-
this.props.sandbox.picks[0].title || this.props.sandbox.title;
26+
getTitle = () => {
27+
if ((this.props.sandbox.picks || []).length !== 0) {
28+
return this.props.sandbox.picks[0].title;
29+
}
30+
31+
return this.props.sandbox.title;
32+
};
2833

29-
getDescription = () =>
30-
this.props.sandbox.picks[0].description || this.props.sandbox.description;
34+
getDescription = () => {
35+
if ((this.props.sandbox.picks || []).length !== 0) {
36+
return this.props.sandbox.picks[0].description;
37+
}
38+
39+
return this.props.sandbox.description;
40+
};
3141

3242
toggleOpen = () => {
3343
this.props.pickSandbox({
@@ -55,7 +65,6 @@ export default class WideSandbox extends React.PureComponent {
5565
</Container>
5666
);
5767
}
58-
5968
const template = getTemplate(sandbox.template);
6069
const Icon = getIcon(sandbox.template);
6170

0 commit comments

Comments
 (0)