Skip to content

Commit 4eb1b69

Browse files
authored
Merge pull request #16 from jedmao/css-in-js
feat: introduce CSS in JS via Linaria
2 parents 6dd6ef0 + 637e3d6 commit 4eb1b69

File tree

23 files changed

+138
-76
lines changed

23 files changed

+138
-76
lines changed

.gitignore

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
node_modules
22
coverage
33
generator-tsx-*
4-
generators/**/*.js
5-
generators/**/*.d.ts
4+
generators/*.js
5+
generators/*.d.ts
6+
generators/*/*.js
7+
generators/*/*.d.ts
68
package
79
.yo-rc.json

.vscode/settings.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
"**/.hg": true,
1010
"**/CVS": true,
1111
"**/.DS_Store": true,
12-
"generators/**/*.js": true,
13-
"generators/**/*.d.ts": true
12+
"generators/*.js": true,
13+
"generators/*.d.ts": true,
14+
"generators/*/*.js": true,
15+
"generators/*/*.d.ts": true
1416
},
1517
"search.exclude": {
1618
"**/coverge": true,

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ See [Design Goals](https://github.com/adobe/generator-tsx/wiki/Design-Goals).
2222
- [Router](https://github.com/ReactTraining/react-router)
2323
- [Testing Library](https://github.com/testing-library/react-testing-library#react-testing-library)
2424
- [react-intl](https://github.com/formatjs/react-intl)
25+
- CSS in JS via [Linaria](https://linaria.now.sh/)
2526

2627
## Installation
2728

generators/app/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export = class extends Generator {
8585
'.gitignore',
8686
'.markdownlint.json',
8787
'.travis.yml',
88+
'config',
8889
'tsconfig.json',
8990
].forEach(filename => {
9091
this.fs.copy(
@@ -124,6 +125,7 @@ export = class extends Generator {
124125
)
125126
this.npmInstall(
126127
[
128+
'@craco/craco@5',
127129
'@jedmao/tsconfig',
128130
'@types/fetch-mock@^7',
129131
'@types/jest@^24',
@@ -137,9 +139,12 @@ export = class extends Generator {
137139
'@types/redux-logger@^3',
138140
'@types/redux-mock-store@^1',
139141
'@types/webpack-env@^1',
142+
// TODO: https://github.com/callstack/linaria/issues/420
143+
'core-js@2',
140144
'fetch-mock@^7',
141145
'husky@^2',
142146
'jest-fetch-mock@^2',
147+
'linaria@1',
143148
'lint-staged@^8',
144149
'prettier@^1',
145150
'react-scripts@^3',

generators/app/templates/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@
2121
npm-debug.log*
2222
yarn-debug.log*
2323
yarn-error.log*
24+
25+
# linaria
26+
src/.linaria_cache

generators/app/templates/.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"search.exclude": {
77
"**/build": true,
88
"**/coverge": true,
9-
"**/node_modules": true
9+
"**/node_modules": true,
10+
"src/.linaria_cache": true
1011
}
1112
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const babelJest = require('babel-jest')
2+
3+
module.exports = babelJest.createTransformer({
4+
presets: [require.resolve('babel-preset-react-app'), 'linaria/babel'],
5+
babelrc: false,
6+
configFile: false,
7+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const { loaderByName, getLoader } = require('@craco/craco')
2+
const transformBabelLoader = require('./transformBabelLoader')
3+
4+
module.exports = {
5+
webpack: {
6+
configure: webpackConfig => {
7+
const lm = getLoader(webpackConfig, loaderByName('babel-loader'))
8+
const loader = lm.match.loader
9+
webpackConfig.module.rules[2].oneOf[1] = transformBabelLoader(loader)
10+
return webpackConfig
11+
},
12+
},
13+
jest: {
14+
configure: jestConfig => {
15+
jestConfig.transform['^.+\\.(js|jsx|ts|tsx)$'] = require.resolve(
16+
'./babelTransform.js',
17+
)
18+
return jestConfig
19+
},
20+
},
21+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module.exports = loader => ({
2+
test: loader.test,
3+
include: loader.include,
4+
rules: [
5+
{
6+
loader: loader.loader,
7+
options: {
8+
presets: [loader.options.presets[0], 'linaria/babel'],
9+
},
10+
},
11+
{
12+
loader: 'linaria/loader',
13+
options: {
14+
cacheDirectory: 'src/.linaria_cache',
15+
sourceMap: process.env.NODE_ENV !== 'production',
16+
babelOptions: {
17+
presets: loader.options.presets,
18+
},
19+
},
20+
},
21+
],
22+
})

generators/app/templates/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
"homepage": "https://github.com/<%= githubUsername %>/<%= appname %>#readme",
1414
"scripts": {
1515
"clean": "rimraf coverage build *.log*",
16-
"start": "react-scripts start",
16+
"start": "craco start",
1717
"prebuild": "rimraf build",
18-
"build": "react-scripts build",
19-
"test": "react-scripts test",
18+
"build": "craco build",
19+
"test": "craco test",
2020
"eject": "react-scripts eject",
2121
"check-types": "tsc --noEmit",
2222
"precover": "rimraf coverage",
@@ -65,6 +65,7 @@
6565
"lcov"
6666
]
6767
},
68+
"cracoConfig": "config/craco.config.js",
6869
"eslintConfig": {
6970
"extends": "react-app",
7071
"globals": {

generators/app/templates/src/components/Home/Home.module.css

Lines changed: 0 additions & 26 deletions
This file was deleted.

generators/app/templates/src/components/Home/Home.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { styled } from 'linaria/react'
12
import React, { useEffect } from 'react'
23
import Helmet from 'react-helmet'
34
import { FormattedMessage, FormattedHTMLMessage } from 'react-intl'
@@ -8,7 +9,6 @@ import useTheme from 'helpers/useTheme'
89
import Theme from 'models/Theme'
910
import RootState from 'store/RootState'
1011

11-
import styles from './Home.module.css'
1212
import logo from './logo.svg'
1313

1414
interface StateProps extends Pick<RootState, 'cart'> {
@@ -31,12 +31,12 @@ const Home: React.FC<HomeProps & StateProps & DispatchProps> = ({
3131
}, [getCart])
3232
useTheme(theme)
3333
return (
34-
<div className={styles.root}>
34+
<Root>
3535
<Helmet>
3636
<title>Home</title>
3737
</Helmet>
38-
<header className={styles.header}>
39-
<img src={logo} className={styles.logo} alt="logo" />
38+
<Header>
39+
<Logo src={logo} alt="logo" />
4040
<p>
4141
<FormattedHTMLMessage id="home.instructions" />
4242
</p>
@@ -48,8 +48,8 @@ const Home: React.FC<HomeProps & StateProps & DispatchProps> = ({
4848
<FormattedMessage id="home.learn" />
4949
</a>
5050
{JSON.stringify(cart.subtotal.amount)}
51-
</header>
52-
</div>
51+
</Header>
52+
</Root>
5353
)
5454
}
5555

@@ -62,3 +62,29 @@ export default connect<StateProps, DispatchProps, void, RootState>(
6262
getCart: fetchCart,
6363
},
6464
)(Home)
65+
66+
const Root = styled.div`
67+
text-align: center;
68+
`
69+
70+
const Header = styled.div`
71+
display: flex;
72+
flex-direction: column;
73+
align-items: center;
74+
justify-content: center;
75+
font-size: calc(10px + 2vmin);
76+
`
77+
78+
const Logo = styled.img`
79+
animation: spin infinite 20s linear;
80+
height: 40vmin;
81+
pointer-events: none;
82+
@keyframes spin {
83+
from {
84+
transform: rotate(0deg);
85+
}
86+
to {
87+
transform: rotate(360deg);
88+
}
89+
}
90+
`

generators/app/templates/src/helpers/resolveFetch.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
/*eslint-disable no-throw-literal*/
2-
import { Omit } from 'ts-essentials'
3-
42
import ResponseError from 'models/ResponseError'
53
import ResponsePayload from 'models/ResponsePayload'
64

@@ -61,5 +59,5 @@ export default async function resolveFetch<TBody extends any>(
6159
* Intentionally omit non-TBody props from the result type,
6260
* because errors have already been dealt with.
6361
*/
64-
return (responsePayload as Omit<typeof responsePayload, 'errors'>) as TBody
62+
return (responsePayload as unknown) as TBody
6563
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/// <reference types="react-scripts" />

generators/app/templates/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"allowUnusedLabels": false,
77
"alwaysStrict": true,
88
"baseUrl": "src",
9-
"declaration": true,
109
"esModuleInterop": true,
1110
"forceConsistentCasingInFileNames": true,
1211
"isolatedModules": true,

generators/component/expected/barBaz/QuxQuux/QuxQuux.module.css

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1+
import { styled } from 'linaria/react'
12
import React from 'react'
23
import { connect } from 'react-redux'
34

45
import RootState from 'store/RootState'
56

6-
import styles from './QuxQuux.module.css'
7-
87
interface StateProps {}
98

109
interface DispatchProps {}
1110

1211
export interface QuxQuuxProps {}
1312

1413
const QuxQuux: React.FC<QuxQuuxProps & StateProps & DispatchProps> = () => (
15-
<div className={styles.root}>content</div>
14+
<Root>content</Root>
1615
)
1716

1817
export default connect<StateProps, DispatchProps, void, RootState>(null)(QuxQuux)
18+
19+
const Root = styled.div`
20+
display: block;
21+
`

generators/component/index.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ describe('tsx:component', () => {
2222
'barBaz/QuxQuux/index.ts',
2323
'barBaz/QuxQuux/QuxQuux.tsx',
2424
'barBaz/QuxQuux/QuxQuux.test.tsx',
25-
'barBaz/QuxQuux/QuxQuux.module.css',
2625
]
2726
for (const filename of expectedFiles) {
2827
assert.fileContent(

generators/component/index.ts

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,19 @@ export = class extends Generator {
2929
const parts = this.options.name.split('/').map(camelCase)
3030
const name = sentenceCase(parts[parts.length - 1])
3131
parts.splice(-1, 1, name)
32-
;['index.ts', 'Foo.tsx', 'Foo.test.tsx', 'Foo.module.css'].forEach(
33-
filename => {
34-
this.fs.copyTpl(
35-
this.templatePath(filename),
36-
this.destinationPath(
37-
`src/components/${parts.join('/')}/${filename.replace(
38-
/^Foo/,
39-
name,
40-
)}`,
41-
),
42-
{
32+
;['index.ts', 'Foo.tsx', 'Foo.test.tsx'].forEach(filename => {
33+
this.fs.copyTpl(
34+
this.templatePath(filename),
35+
this.destinationPath(
36+
`src/components/${parts.join('/')}/${filename.replace(
37+
/^Foo/,
4338
name,
44-
},
45-
)
46-
},
47-
)
39+
)}`,
40+
),
41+
{
42+
name,
43+
},
44+
)
45+
})
4846
}
4947
}

generators/component/templates/Foo.module.css

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1+
import { styled } from 'linaria/react'
12
import React from 'react'
23
import { connect } from 'react-redux'
34

45
import RootState from 'store/RootState'
56

6-
import styles from './<%= name %>.module.css'
7-
87
interface StateProps {}
98

109
interface DispatchProps {}
1110

1211
export interface <%= name %>Props {}
1312

1413
const <%= name %>: React.FC<<%= name %>Props & StateProps & DispatchProps> = () => (
15-
<div className={styles.root}>content</div>
14+
<Root>content</Root>
1615
)
1716

1817
export default connect<StateProps, DispatchProps, void, RootState>(null)(<%= name %>)
18+
19+
const Root = styled.div`
20+
display: block;
21+
`

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)