Skip to content

Commit b7ad517

Browse files
author
Drake Costa
authored
🔨 Refactor app/components to TypeScript (codesandbox#2066)
This PR refactors (nearly) everything under app/components to TypeScript, adding new types and applying coding conventions. Here are some basic rules regarding coding conventions (to be more thoroughly documented at a later date): - Always use Named Exports (here's some good reasons why this is a good idea: https://humanwhocodes.com/blog/2019/01/stop-using-default-exports-javascript-module/) - Write functional components with hooks (makes it much easier to detect unused methods, among numerous other good reasons) - Prefer arrow functions (death to `this`) - Prefer destructuring to property accessors - Components should always be their own file with a Capitalized name matching the component name - Multiple file components should be in a Capitalized folder matching the component name, with an `index.ts` file handling all exports to be consumed by outside components - Prefer `interface` over `type` for typing Props - In general, prop interfaces should follow a IComponentNameProps naming scheme, though this is largely stylistic - Prefer `const SomeComponent: React.FC<ISomeComponentProps> = ({ . . . }) => { }` over `const SomeComponent = ({ . . . }: ISomeComponentProps) => { }` to avoid needing to define common React component props - For styled components, Inline types are fine where their footprint is small, ie: ```typescript const SomeElement = styled.div<{ large: boolean }>` ${({ large }) => css` /* Always wrap style declarations in a single function call and don't forget to use "css" for syntax highlighting! */ `} ` ``` - All type interface definitions should live in a `types.ts` file adjacent to the component to reduce clutter in the component definition - If a component uses GraphQL queries/mutations, all GraphQL documents should live in their files adjacent to the component that uses them, ie: `queries.gql` and `mutations.gql` to reduce clutter in the component definition - All styles should be applied with styled-components and all styled elements should be defined in elements.js to reduce clutter in the component definition - Global styles should be defined using styled-components in a `GlobalStyles.ts` file adjacent to the root component that requires it - When using props in styled components, always wrap all of the styles in a single arrow function to make it easy to destructure props all in one place and always wrap nested template literals with the `css` tagged template to enable style linting/syntax highlighting. - Style rules should be well ordered (to be enforced by stylelint at a later date). In general this means rules should be grouped by category, starting with Position > Box Model > Fonts > Animation > Misc > pseudo-selectors. For now this is low-priority. The general rule of thumb here is: avoid clutter and if you have to scroll a component file, it probably needs to be broken up into smaller pieces. By separating concerns into small, well-organized files, code will be easier to read and thus easier to maintain. That should cover more than what's implemented by this PR. These rules will be applied progressively so as to make the initial code review for refactors easier (as for the most part it will just require some components to be broken up into multiple files). Commit Log: * 🔨 Refactor app/components: Convert files to be refactored to Typescript Changing the file extension of all files to be refactored to `.ts/.tsx, this is to make it easier to compare before and after changes in later commits. Each component will be refactored one at a time in it's own commit for review. The process will go as follows: 1. change extensions (this commit) 2. refactor component files as-is 3. rename files and reorganize files where necessary 4. update all import references across the app * 🔨 Refactor app/components/Alert: Apply Coding Conventions, Make Generic Implemented some minor changes to the Alert component to make it more general-purpose. It now has an additional prop `confirmMesage: string` that controls the confirm button text. The click handler has also been renamed to onConfirm. (Previously these were "Delete" and onDelete) TODO: Update props on all instances of this component. * 🔨 Refactor app/components/ConfirmLink: Apply Coding Conventions * 📝 Add Types to app/components/DelayedAnimation * 🔨 Refactor app/components/DeleteSandboxButton: Apply Coding Conventions TODO: Test to verify that styles are still being applied correctly * 🔨 Refactor app/components/DeploymentIntegration: Apply Conventions TODO: Update renamed props on all instances of this component. * 🔨 Refactor app/components/EditableTags: Apply Conventions TODO: Split out GlobalStyles into separate file, import Template interface to create props interface for this component. * 🧹 Cleanup app/components/GitHubLogo Applied minor changes to conform with project coding style. Perhaps we should move this icon to a separate package along with others like it? Are we even using this one or did we get it from an external library? Maybe we can just delete this altogether. * 🔨 Refactor app/components/GitProgress: Apply Conventions Removed unused prop noAnimation. TODO: Maybe move GitHubLogo and OpagueLogo into this component as subcomponents? Are those two logos being used elsewhere? * 🔨 Refactor app/components/HeaderSearchBar: Apply Conventions Changed the search input to be a controlled component. * 🔨 Refactor app/components/HoverMenu: Apply Conventions @CompuIves can you explain why this component previously was applying an event listener to the root element to call handleViewClick in addition to the native React onClick prop? This may require some additional refactoring if there's something I'm misunderstanding here. * 🔨 Refactor app/components/Integration: Apply Conventions TODO: Update props on component instances. * 🔨 Refactor app/components/IntegrationModal: Apply Conventions TODO: Maybe move this to pages/common/modals? Also maybe move it's dependent sub-components if they aren't being used elsewhere? * 🧹 Cleanup app/components/Loading Minor changes to conform to coding style. * 🔨 Refactor app/components/ModeIcons: Apply Conventions May need further refactoring. TODO: Test to see if this still works the same as before. * 🧹 Cleanup app/components/NetlifyLogo Minor changes to conform to coding style. * 🧹 Cleanup app/components/NowLogo Added props interface and applied coding style. * 🧹 Cleanup app/components/OpaqueLogo Added props interface and applied coding style. * 🔨 Refactor app/components/Overlay: Apply Conventions @CompuIves please review this, I'm not sure that this refactor will work as expected. The original implementation was a bit strange and Transition appears to not like that we were using a boolean in it's item prop. * 🧹 Cleanup app/components/PrivacyStatus Minor stylistic changes, added props interface. * 🧹 Cleanup app/components/ReactIcon Applied code style conventions. Is this icon needed? Can we pull it from a library instead? * 🧹 Cleanup app/components/SandboxList Applied coding style conventions and adjusted types. TODO: Address ignored type errors. See comments. * 🧹 Cleanup app/components/Skeleton Minor code style changes. Added props interface. TODO: Shouldn't Fullscreen have height: 100vh already? Perhaps this should be added there to remove unnecessary style props. * 🧹 Cleanup app/components/SocialInfo Minor coding style changes. Moved repeated link attributes to element.ts * 🔨 Refactor app/components/Stat: Apply Conventions Reorganized and added props interface. TODO: We probably want to add tests for the full component not just it's number formatting function. * 🔨 Refactor app/components/SubscribeForm: Apply Conventions Updated react-stripe-elements from ^v1.7 to ^v3.0.0 injectStripe doesn't appear to want to expose the CheckoutForm props and I'm not sure if there is a way I can work around it. Someone with better TypeScript knowledge than me will have to figure this one out. Refactored all components to apply coding conventions. SubrscribeForm is basically unchanged, but CheckoutForm was re-written using hooks, so it needs to be tested to ensure that it still works. * 🧹 Cleanup app/components/SubTitle Minor coding style changes, added types. * 🧹 Cleanup app/components/Title Minor coding style changes, added types. * 🧹 Cleanup app/components/TypescriptIcon Minor coding style changes. * 🔨 Refactor app/components/UploadProgress: Apply Conventions Removed unused prop noAnimation. Applied coding style conventions, added prop interfaces. * 🧹 Cleanup app/components/ZeitLogo Minor coding style changes. * Update packages/app/src/app/components/DeploymentIntegration/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * Update packages/app/src/app/components/HoverMenu/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * Update packages/app/src/app/components/DeploymentIntegration/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * Update packages/app/src/app/components/HoverMenu/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * Update packages/app/src/app/components/Integration/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * Update packages/app/src/app/components/IntegrationModal/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * Update packages/app/src/app/components/IntegrationModal/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * Update packages/app/src/app/components/Overlay/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * Update packages/app/src/app/components/Overlay/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * Update packages/app/src/app/components/SandboxList/index.tsx Co-Authored-By: Michaël De Boey <[email protected]> * 🔧 Fix suggested change in HoverMenu * 🚧 WIP Resolve Conversations, Fix Build Errors * 🧹 Cleanup Types to follow Coding Conventions * 🔧 Add missing key prop to Overlay items * 🧹 Reorganize files, Update Import References and Props, Fix Types * 🔧 Fix missing key error, add note to remove DOM prop error later * 🔧 Fix DeploymentIntegration not showing DetailInfo Children * Prevent the websocket errors to appear in console * 📦 Add React Display Name Babel Plugin, Deduplicate Cude Component * Convert ContextMenu to types * Fix ContextMenu usage * Move JSX.Element to React.ReactNode
1 parent 5ba9ac9 commit b7ad517

File tree

185 files changed

+2093
-1968
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

185 files changed

+2093
-1968
lines changed

packages/app/babel.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module.exports = {
1818
'babel-plugin-system-import-transformer',
1919
'babel-plugin-macros',
2020
'babel-plugin-styled-components',
21+
'@babel/plugin-transform-react-display-name',
2122
],
2223
},
2324
},

packages/app/config/babel.dev.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,6 @@ module.exports = {
3838
require.resolve('babel-plugin-styled-components'),
3939
require.resolve('babel-plugin-macros'),
4040
require.resolve('babel-plugin-graphql-tag'),
41+
require.resolve('@babel/plugin-transform-react-display-name'),
4142
],
4243
};

packages/app/config/babel.prod.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ module.exports = {
3636
require.resolve('babel-plugin-styled-components'),
3737
require.resolve('babel-plugin-macros'),
3838
require.resolve('babel-plugin-graphql-tag'),
39+
require.resolve('@babel/plugin-transform-react-display-name'),
3940
// Optimization: hoist JSX that never changes out of render()
4041
// Disabled because of issues:
4142
// * https://github.com/facebookincubator/create-react-app/issues/525

packages/app/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"@babel/plugin-proposal-object-rest-spread": "^7.5.5",
3636
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
3737
"@babel/plugin-transform-async-to-generator": "^7.5.0",
38+
"@babel/plugin-transform-react-display-name": "^7.2.0",
3839
"@babel/plugin-transform-runtime": "^7.5.5",
3940
"@babel/plugin-transform-template-literals": "^7.4.4",
4041
"@babel/polyfill": "^7.4.4",
@@ -251,7 +252,7 @@
251252
"react-show": "^3.0.4",
252253
"react-split-pane": "^0.1.87",
253254
"react-spring": "^8.0.25",
254-
"react-stripe-elements": "^1.2.0",
255+
"react-stripe-elements": "^3.0.0",
255256
"react-tagsinput": "^3.19.0",
256257
"react-use": "^9.7.2",
257258
"react-virtualized": "^9.19.1",

packages/app/scripts/start.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ function run(port) {
294294
runDevServer(port, protocol, '/app.html');
295295

296296
if (process.env.LOCAL_SERVER) {
297+
// Sandbox server
297298
const proxy = httpProxy.createProxyServer({});
298299
http
299300
.createServer(function(req, res) {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react';
2+
import { Button } from '@codesandbox/common/lib/components/Button';
3+
import { Container, Title, Text, Buttons } from './elements';
4+
5+
interface IAlertProps {
6+
title: string;
7+
body: string;
8+
confirmMessage?: string;
9+
onCancel: (event: React.MouseEvent<HTMLButtonElement>) => void;
10+
onConfirm: (event: React.MouseEvent<HTMLButtonElement>) => void;
11+
}
12+
13+
export const Alert: React.FC<IAlertProps> = ({
14+
title,
15+
body,
16+
confirmMessage = 'Confirm',
17+
onCancel,
18+
onConfirm,
19+
...props
20+
}) => (
21+
<Container {...props}>
22+
<Title>{title}</Title>
23+
<Text>{body}</Text>
24+
<Buttons>
25+
<Button small block secondary onClick={onCancel}>
26+
Cancel
27+
</Button>
28+
<Button small block danger onClick={onConfirm}>
29+
{confirmMessage}
30+
</Button>
31+
</Buttons>
32+
</Container>
33+
);

packages/app/src/app/components/Alert/elements.js renamed to packages/app/src/app/components/Alert/elements.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
import styled from 'styled-components';
1+
import styled, { css } from 'styled-components';
22

33
export const Container = styled.div`
4-
display: flex;
5-
flex-direction: column;
6-
background-color: ${props => props.theme.background};
7-
color: rgba(255, 255, 255, 0.8);
8-
padding: 1rem;
4+
${({ theme }) => css`
5+
display: flex;
6+
flex-direction: column;
7+
padding: 1rem;
8+
background-color: ${theme.background};
9+
color: rgba(255, 255, 255, 0.8);
10+
`}
911
`;
1012

1113
export const Title = styled.div`
1214
display: flex;
1315
justify-content: center;
14-
font-weight: 500;
15-
font-size: 1.125rem;
1616
margin-top: 0 !important;
1717
margin-bottom: 1rem;
18+
font-size: 1.125rem;
19+
font-weight: 500;
1820
text-transform: uppercase;
1921
`;
2022

@@ -27,6 +29,7 @@ export const Buttons = styled.div`
2729
display: flex;
2830
justify-content: center;
2931
margin-top: 1rem;
32+
3033
button {
3134
display: flex;
3235
justify-content: center;

packages/app/src/app/components/Alert/index.js

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { Alert } from './Alert';

packages/app/src/app/components/CodeEditor/index.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React from 'react';
2-
import Title from 'app/components/Title';
3-
import SubTitle from 'app/components/SubTitle';
4-
import Loadable from 'app/utils/Loadable';
2+
import UIIcon from 'react-icons/lib/md/dvr';
3+
import QuestionIcon from 'react-icons/lib/go/question';
54
import getUI from '@codesandbox/common/lib/templates/configuration/ui';
65
import Centered from '@codesandbox/common/lib/components/flex/Centered';
76
import Margin from '@codesandbox/common/lib/components/spacing/Margin';
@@ -10,14 +9,14 @@ import getDefinition from '@codesandbox/common/lib/templates';
109
import { Sandbox } from '@codesandbox/common/lib/types';
1110
import { getModulePath } from '@codesandbox/common/lib/sandbox/modules';
1211
import Tooltip from '@codesandbox/common/lib/components/Tooltip';
13-
import UIIcon from 'react-icons/lib/md/dvr';
14-
import QuestionIcon from 'react-icons/lib/go/question';
15-
16-
import { Props } from './types';
12+
import { Title } from 'app/components/Title';
13+
import { SubTitle } from 'app/components/SubTitle';
14+
import Loadable from 'app/utils/Loadable';
1715
import ImageViewer from './ImageViewer';
1816
import Configuration from './Configuration';
1917
import VSCode from './VSCode';
2018
import MonacoDiff from './MonacoDiff';
19+
import { Props } from './types';
2120
import { Icons, Icon } from './elements';
2221

2322
const CodeMirror = Loadable(() =>

0 commit comments

Comments
 (0)