Skip to content

Commit c24314d

Browse files
Fabianopbianschmitz
authored andcommitted
Dark scheme overlay (#7052)
1 parent a51729c commit c24314d

22 files changed

+457
-380
lines changed

CHANGELOG-1.x.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -1577,20 +1577,20 @@ Unhandled Promise rejections will now crash tests. You can fix them by explicitl
15771577
After the regular update procedure above, add these line to `<head>` in `public/index.html`:
15781578

15791579
```html
1580-
<meta name="theme-color" content="#000000">
1581-
<!--
1580+
<meta name="theme-color" content="#000000" />
1581+
<!--
15821582
manifest.json provides metadata used when your web app is added to the
15831583
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
15841584
-->
1585-
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
1585+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
15861586
```
15871587

15881588
Add `<noscript>` to `<body>` in `public/index.html`:
15891589

15901590
```html
1591-
<noscript>
1592-
You need to enable JavaScript to run this app.
1593-
</noscript>
1591+
<noscript>
1592+
You need to enable JavaScript to run this app.
1593+
</noscript>
15941594
```
15951595

15961596
Then create a file called `public/manifest.json` that looks like this:

docusaurus/docs/advanced-configuration.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ You can adjust various development and production settings by setting environmen
2323
| INLINE_RUNTIME_CHUNK | 🚫 Ignored | ✅ Used | By default, Create React App will embed the runtime script into `index.html` during the production build. When set to `false`, the script will not be embedded and will be imported as usual. This is normally required when dealing with CSP. |
2424
| IMAGE_INLINE_SIZE_LIMIT | 🚫 Ignored | ✅ Used | By default, images smaller than 10,000 bytes are encoded as a data URI in base64 and inlined in the CSS or JS build artifact. Set this to control the size limit in bytes. Setting it to 0 will disable the inlining of images. |
2525
| EXTEND_ESLINT | ✅ Used | ✅ Used | When set to `true`, ESLint configs that extend `eslint-config-react-app` will be used by `eslint-loader`. Any rules that are set to `"error"` will stop the application from building. |
26-
| TSC_COMPILE_ON_ERROR | ✅ Used | ✅ Used | When set to `true`, you can run and properly build TypeScript projects even if there are TypeScript type check errors. These errors are printed as warnings in the terminal and/or browser console. |
26+
| TSC_COMPILE_ON_ERROR | ✅ Used | ✅ Used | When set to `true`, you can run and properly build TypeScript projects even if there are TypeScript type check errors. These errors are printed as warnings in the terminal and/or browser console. |

packages/create-react-app/createReactApp.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ function createApp(
248248
if (npmInfo.npmVersion) {
249249
console.log(
250250
chalk.yellow(
251-
`You are using npm ${npmInfo.npmVersion} so the project will be bootstrapped with an old unsupported version of tools.\n\n` +
251+
`You are using npm ${
252+
npmInfo.npmVersion
253+
} so the project will be bootstrapped with an old unsupported version of tools.\n\n` +
252254
`Please update to npm 5 or higher for a better, fully supported experience.\n`
253255
)
254256
);
@@ -262,7 +264,9 @@ function createApp(
262264
if (yarnInfo.yarnVersion) {
263265
console.log(
264266
chalk.yellow(
265-
`You are using Yarn ${yarnInfo.yarnVersion} together with the --use-pnp flag, but Plug'n'Play is only supported starting from the 1.12 release.\n\n` +
267+
`You are using Yarn ${
268+
yarnInfo.yarnVersion
269+
} together with the --use-pnp flag, but Plug'n'Play is only supported starting from the 1.12 release.\n\n` +
266270
`Please update to Yarn 1.12 or higher for a better, fully supported experience.\n`
267271
)
268272
);

packages/react-error-overlay/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"eslint-plugin-import": "2.18.2",
5151
"eslint-plugin-jsx-a11y": "6.2.3",
5252
"eslint-plugin-react": "7.14.3",
53-
"flow-bin": "^0.63.1",
53+
"flow-bin": "^0.110.0",
5454
"html-entities": "1.2.1",
5555
"jest": "24.9.0",
5656
"jest-fetch-mock": "2.1.2",

packages/react-error-overlay/src/components/CloseButton.js

+13-8
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,32 @@
66
*/
77

88
/* @flow */
9-
import React from 'react';
10-
import { black } from '../styles';
9+
import React, { useContext } from 'react';
10+
import { ThemeContext } from '../iframeScript';
11+
import type { Theme } from '../styles';
1112

12-
const closeButtonStyle = {
13-
color: black,
13+
const closeButtonStyle = (theme: Theme) => ({
14+
color: theme.closeColor,
1415
lineHeight: '1rem',
1516
fontSize: '1.5rem',
1617
padding: '1rem',
1718
cursor: 'pointer',
1819
position: 'absolute',
1920
right: 0,
2021
top: 0,
21-
};
22+
});
2223

23-
type CloseCallback = () => void;
24-
function CloseButton({ close }: {| close: CloseCallback |}) {
24+
type CloseButtonPropsType = {|
25+
close: () => void,
26+
|};
27+
28+
function CloseButton({ close }: CloseButtonPropsType) {
29+
const theme = useContext(ThemeContext);
2530
return (
2631
<span
2732
title="Click or press Escape to dismiss."
2833
onClick={close}
29-
style={closeButtonStyle}
34+
style={closeButtonStyle(theme)}
3035
>
3136
×
3237
</span>

packages/react-error-overlay/src/components/CodeBlock.js

+16-15
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
*/
77

88
/* @flow */
9-
import React from 'react';
10-
import { redTransparent, yellowTransparent } from '../styles';
9+
import React, { useContext } from 'react';
10+
import { ThemeContext } from '../iframeScript';
1111

1212
const _preStyle = {
1313
position: 'relative',
@@ -20,16 +20,6 @@ const _preStyle = {
2020
borderRadius: '0.25rem',
2121
};
2222

23-
const primaryPreStyle = {
24-
..._preStyle,
25-
backgroundColor: redTransparent,
26-
};
27-
28-
const secondaryPreStyle = {
29-
..._preStyle,
30-
backgroundColor: yellowTransparent,
31-
};
32-
3323
const codeStyle = {
3424
fontFamily: 'Consolas, Menlo, monospace',
3525
};
@@ -39,9 +29,20 @@ type CodeBlockPropsType = {|
3929
codeHTML: string,
4030
|};
4131

42-
function CodeBlock(props: CodeBlockPropsType) {
43-
const preStyle = props.main ? primaryPreStyle : secondaryPreStyle;
44-
const codeBlock = { __html: props.codeHTML };
32+
function CodeBlock({ main, codeHTML }: CodeBlockPropsType) {
33+
const theme = useContext(ThemeContext);
34+
const primaryPreStyle = {
35+
..._preStyle,
36+
backgroundColor: theme.primaryPreBackground,
37+
color: theme.primaryPreColor,
38+
};
39+
const secondaryPreStyle = {
40+
..._preStyle,
41+
backgroundColor: theme.secondaryPreBackground,
42+
color: theme.secondaryPreColor,
43+
};
44+
const preStyle = main ? primaryPreStyle : secondaryPreStyle;
45+
const codeBlock = { __html: codeHTML };
4546

4647
return (
4748
<pre style={preStyle}>

packages/react-error-overlay/src/components/Collapsible.js

+39-44
Original file line numberDiff line numberDiff line change
@@ -6,81 +6,76 @@
66
*/
77

88
/* @flow */
9-
import React, { Component } from 'react';
10-
import { black } from '../styles';
9+
import React, { useState, useContext } from 'react';
10+
import { ThemeContext } from '../iframeScript';
1111

1212
import type { Element as ReactElement } from 'react';
13+
import type { Theme } from '../styles';
1314

1415
const _collapsibleStyle = {
15-
color: black,
1616
cursor: 'pointer',
1717
border: 'none',
1818
display: 'block',
1919
width: '100%',
2020
textAlign: 'left',
21-
background: '#fff',
2221
fontFamily: 'Consolas, Menlo, monospace',
2322
fontSize: '1em',
2423
padding: '0px',
2524
lineHeight: '1.5',
2625
};
2726

28-
const collapsibleCollapsedStyle = {
27+
const collapsibleCollapsedStyle = (theme: Theme) => ({
2928
..._collapsibleStyle,
29+
color: theme.color,
30+
background: theme.background,
3031
marginBottom: '1.5em',
31-
};
32+
});
3233

33-
const collapsibleExpandedStyle = {
34+
const collapsibleExpandedStyle = (theme: Theme) => ({
3435
..._collapsibleStyle,
36+
color: theme.color,
37+
background: theme.background,
3538
marginBottom: '0.6em',
36-
};
39+
});
3740

38-
type Props = {|
41+
type CollapsiblePropsType = {|
3942
children: ReactElement<any>[],
4043
|};
4144

42-
type State = {|
43-
collapsed: boolean,
44-
|};
45-
46-
class Collapsible extends Component<Props, State> {
47-
state = {
48-
collapsed: true,
49-
};
45+
function Collapsible(props: CollapsiblePropsType) {
46+
const theme = useContext(ThemeContext);
47+
const [collapsed, setCollapsed] = useState(true);
5048

51-
toggleCollapsed = () => {
52-
this.setState(state => ({
53-
collapsed: !state.collapsed,
54-
}));
49+
const toggleCollapsed = () => {
50+
setCollapsed(!collapsed);
5551
};
5652

57-
render() {
58-
const count = this.props.children.length;
59-
const collapsed = this.state.collapsed;
60-
return (
61-
<div>
53+
const count = props.children.length;
54+
return (
55+
<div>
56+
<button
57+
onClick={toggleCollapsed}
58+
style={
59+
collapsed
60+
? collapsibleCollapsedStyle(theme)
61+
: collapsibleExpandedStyle(theme)
62+
}
63+
>
64+
{(collapsed ? '▶' : '▼') +
65+
` ${count} stack frames were ` +
66+
(collapsed ? 'collapsed.' : 'expanded.')}
67+
</button>
68+
<div style={{ display: collapsed ? 'none' : 'block' }}>
69+
{props.children}
6270
<button
63-
onClick={this.toggleCollapsed}
64-
style={
65-
collapsed ? collapsibleCollapsedStyle : collapsibleExpandedStyle
66-
}
71+
onClick={toggleCollapsed}
72+
style={collapsibleExpandedStyle(theme)}
6773
>
68-
{(collapsed ? '▶' : '▼') +
69-
` ${count} stack frames were ` +
70-
(collapsed ? 'collapsed.' : 'expanded.')}
74+
{`▲ ${count} stack frames were expanded.`}
7175
</button>
72-
<div style={{ display: collapsed ? 'none' : 'block' }}>
73-
{this.props.children}
74-
<button
75-
onClick={this.toggleCollapsed}
76-
style={collapsibleExpandedStyle}
77-
>
78-
{`▲ ${count} stack frames were expanded.`}
79-
</button>
80-
</div>
8176
</div>
82-
);
83-
}
77+
</div>
78+
);
8479
}
8580

8681
export default Collapsible;

packages/react-error-overlay/src/components/ErrorOverlay.js

+34-39
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
*/
77

88
/* @flow */
9-
import React, { Component } from 'react';
10-
import { black } from '../styles';
9+
import React, { useContext, useEffect } from 'react';
10+
import { ThemeContext } from '../iframeScript';
1111

1212
import type { Node as ReactNode } from 'react';
13+
import type { Theme } from '../styles';
1314

14-
const overlayStyle = {
15+
const overlayStyle = (theme: Theme) => ({
1516
position: 'relative',
1617
display: 'inline-flex',
1718
flexDirection: 'column',
@@ -28,56 +29,50 @@ const overlayStyle = {
2829
whiteSpace: 'pre-wrap',
2930
wordBreak: 'break-word',
3031
lineHeight: 1.5,
31-
color: black,
32-
};
32+
color: theme.color,
33+
});
3334

34-
type Props = {|
35+
type ErrorOverlayPropsType = {|
3536
children: ReactNode,
3637
shortcutHandler?: (eventKey: string) => void,
3738
|};
3839

39-
type State = {|
40-
collapsed: boolean,
41-
|};
40+
let iframeWindow: window = null;
4241

43-
class ErrorOverlay extends Component<Props, State> {
44-
iframeWindow: window = null;
42+
function ErrorOverlay(props: ErrorOverlayPropsType) {
43+
const theme = useContext(ThemeContext);
4544

46-
getIframeWindow = (element: ?HTMLDivElement) => {
45+
const getIframeWindow = (element: ?HTMLDivElement) => {
4746
if (element) {
4847
const document = element.ownerDocument;
49-
this.iframeWindow = document.defaultView;
50-
}
51-
};
52-
53-
onKeyDown = (e: KeyboardEvent) => {
54-
const { shortcutHandler } = this.props;
55-
if (shortcutHandler) {
56-
shortcutHandler(e.key);
48+
iframeWindow = document.defaultView;
5749
}
5850
};
51+
const { shortcutHandler } = props;
5952

60-
componentDidMount() {
61-
window.addEventListener('keydown', this.onKeyDown);
62-
if (this.iframeWindow) {
63-
this.iframeWindow.addEventListener('keydown', this.onKeyDown);
64-
}
65-
}
66-
67-
componentWillUnmount() {
68-
window.removeEventListener('keydown', this.onKeyDown);
69-
if (this.iframeWindow) {
70-
this.iframeWindow.removeEventListener('keydown', this.onKeyDown);
53+
useEffect(() => {
54+
const onKeyDown = (e: KeyboardEvent) => {
55+
if (shortcutHandler) {
56+
shortcutHandler(e.key);
57+
}
58+
};
59+
window.addEventListener('keydown', onKeyDown);
60+
if (iframeWindow) {
61+
iframeWindow.addEventListener('keydown', onKeyDown);
7162
}
72-
}
63+
return () => {
64+
window.removeEventListener('keydown', onKeyDown);
65+
if (iframeWindow) {
66+
iframeWindow.removeEventListener('keydown', onKeyDown);
67+
}
68+
};
69+
}, [shortcutHandler]);
7370

74-
render() {
75-
return (
76-
<div style={overlayStyle} ref={this.getIframeWindow}>
77-
{this.props.children}
78-
</div>
79-
);
80-
}
71+
return (
72+
<div style={overlayStyle(theme)} ref={getIframeWindow}>
73+
{props.children}
74+
</div>
75+
);
8176
}
8277

8378
export default ErrorOverlay;

0 commit comments

Comments
 (0)