Skip to content

Commit 04de542

Browse files
author
alexlee-dev
committed
📱 Responsive
1 parent cbc8138 commit 04de542

5 files changed

Lines changed: 103 additions & 22 deletions

File tree

website/src/client/App.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,18 @@ import * as React from 'react';
33
import Info from './components/Info';
44
import Demo from './components/Demo';
55

6+
import useMedia from './hooks/useMedia';
7+
68
const App: React.SFC<{}> = () => {
9+
const row = useMedia(
10+
['(min-width: 1000px)', '(min-width: 600px)'],
11+
['row', ''],
12+
'',
13+
);
14+
715
return (
816
<div className="container">
9-
<div className="row full-height">
17+
<div className={`${row} full-height`}>
1018
<Info />
1119
<Demo />
1220
</div>

website/src/client/components/Demo.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ import entry from '../demo/entry';
55
import startApplication from '../demo/startApplication';
66

77
import { buttonContainerHeights } from '../constants';
8+
import useMedia from '../hooks/useMedia';
89

910
const Demo: React.SFC<{}> = () => {
11+
const columnSize = useMedia(
12+
['(min-width: 1000px)', '(min-width: 600px)'],
13+
['column-60', ''],
14+
'',
15+
);
1016
const [currentDemo, setCurrentDemo] = React.useState('entry');
1117
const [applicationCreated, setApplicationCreated] = React.useState(false);
1218
const [applicationStarted, setApplicationStarted] = React.useState(false);
@@ -16,7 +22,7 @@ const Demo: React.SFC<{}> = () => {
1622
}, []);
1723

1824
return (
19-
<div className="column column-60 flex-center">
25+
<div className={`column ${columnSize} flex-center`}>
2026
<div id="demo" />
2127
<div
2228
id="demo-button-container"
Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,40 @@
11
import * as React from 'react';
22
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
33
import { faBox, faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
4+
import useMedia from '../hooks/useMedia';
45

5-
const Info: React.SFC<{}> = () => (
6-
<div className="column column-40 flex-center">
7-
<h1 className="purple">create-cli-application</h1>
8-
<blockquote className="blue-quote">
9-
A bootstrapper for creating a cli application with Node.
10-
</blockquote>
11-
<span className="badge">
12-
<FontAwesomeIcon icon={faBox} />
13-
<span className="margin-left-sm">15.6kb gzipped</span>
14-
</span>
15-
<a
16-
className="purple"
17-
href="https://github.com/alexlee-dev/create-cli-application"
18-
rel="noopener noreferrer"
19-
target="_blank"
6+
const Info: React.SFC<{}> = () => {
7+
const columnSize = useMedia(
8+
['(min-width: 1000px)', '(min-width: 600px)'],
9+
['column-40', ''],
10+
'',
11+
);
12+
13+
return (
14+
<div
15+
className={`column ${columnSize} flex-center ${
16+
columnSize === '' && 'margin-bottom-md margin-top-lg'
17+
}`}
2018
>
21-
<FontAwesomeIcon icon={faExternalLinkAlt} />
22-
<span className="margin-left-sm">View Documentation</span>
23-
</a>
24-
</div>
25-
);
19+
<h1 className="purple">create-cli-application</h1>
20+
<blockquote className="blue-quote">
21+
A bootstrapper for creating a cli application with Node.
22+
</blockquote>
23+
<span className="badge">
24+
<FontAwesomeIcon icon={faBox} />
25+
<span className="margin-left-sm">15.6kb gzipped</span>
26+
</span>
27+
<a
28+
className="purple"
29+
href="https://github.com/alexlee-dev/create-cli-application"
30+
rel="noopener noreferrer"
31+
target="_blank"
32+
>
33+
<FontAwesomeIcon icon={faExternalLinkAlt} />
34+
<span className="margin-left-sm">View Documentation</span>
35+
</a>
36+
</div>
37+
);
38+
};
2639

2740
export default Info;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { useState, useEffect } from 'react';
2+
3+
/**
4+
* Use media query hook.
5+
* @param queries Media Queries.
6+
* @param values Values for each query.
7+
* @param defaultValue Default value to fallback to.
8+
*/
9+
const useMedia = (
10+
queries: string[],
11+
values: any[],
12+
defaultValue?: any,
13+
): any => {
14+
// Array containing a media query list for each query
15+
const mediaQueryLists = queries.map((q) => window.matchMedia(q));
16+
17+
// Function that gets value based on matching media query
18+
const getValue = () => {
19+
// Get index of first media query that matches
20+
const index = mediaQueryLists.findIndex((mql) => mql.matches);
21+
// Return related value or defaultValue if none
22+
return typeof values[index] !== 'undefined' ? values[index] : defaultValue;
23+
};
24+
25+
// State and setter for matched value
26+
const [value, setValue] = useState(getValue);
27+
28+
useEffect(
29+
() => {
30+
// Event listener callback
31+
// Note: By defining getValue outside of useEffect we ensure that it has ...
32+
// ... current values of hook args (as this hook callback is created once on mount).
33+
const handler = () => setValue(getValue);
34+
// Set a listener for each media query with above handler as callback.
35+
mediaQueryLists.forEach((mql) => mql.addListener(handler));
36+
// Remove listeners on cleanup
37+
return () =>
38+
mediaQueryLists.forEach((mql) => mql.removeListener(handler));
39+
},
40+
[], // Empty array ensures effect is only run on mount and unmount
41+
);
42+
43+
return value;
44+
};
45+
46+
export default useMedia;

website/src/client/index.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@
2222
margin-left: 10px;
2323
}
2424

25+
.margin-bottom-md {
26+
margin-bottom: 50px;
27+
}
28+
29+
.margin-top-lg {
30+
margin-top: 100px;
31+
}
32+
2533
.blue {
2634
color: #00d3ff;
2735
}

0 commit comments

Comments
 (0)