styled-componentsは素晴らしいCSSinJSライブラリであり多くのプロジェクトが使っていると思いますが、既存のプロジェクトにすぐに導入するのは難しいです。
しかし、styled-styleを使うことでステップ・バイ・ステップにstyled-componentsなあのリーダブルなコンポーネントに変更していけます。
akameco/styled-style: css modules like styled-components
インストール
$ yarn add styled-style
使い方
CreateReactAppのコードをstyledStyleで書き直すと以下のようになります。
// @flow
import * as React from 'react'
import { styledStyle } from 'styled-style'
import styles from './App.module.css'
import logo from './logo.svg'
const { div, header, h1, p, img } = styledStyle(styles)
const Wrapper = div('wrapper')
const Header = header('header')
const Title = h1('title')
const Intro = p('intro')
const Logo = img('logo')
function App() {
return (
<Wrapper>
<Header>
<Logo src={logo} alt="logo" />
<Title>Welcome to React</Title>
</Header>
<Intro>
To get started, edit <code>src/App.js</code> and save to reload.
</Intro>
</Wrapper>
)
}
export default App
styledStyle
にcssオブジェクトを渡し、div
やh1
といったタグを取り出します。あとは、クラスを指定します。
render
内にclassName
が出てこないので、非常に読みやすくなります。
副産物としてはcssに未定義なクラスにアクセスすると開発時のみエラーを表示します。
なので、タイポの検知にも活用できます。
以下、サンプルレポジトリです。
TypeSciprtサポート
nju33さんからPRをいただき、TypeScriptをサポートしています🎉
以下のように書けます。
ちょっとcall-time generic parameters
が便利すぎる。
import {styledStyle} from 'styled-style'
import styles from './style.module.css'
const { div, button } = styledStyle(styles)
const Center = div('center')
const Button = button('btn')
const PrimaryButton = button<{color: string}>([
'btn',
'primary',
p => p.color === 'primary' && 'primary',
])
// button('foo')
// Argument of type '"foo"' is not assignable to parameter of type 'Selector<"center" | "btn" | "primary", {}>'
// <PrimaryButton />
// => Property 'color' is missing in type '{}'
気持ち
styled-componentsの作者のMax Stoiberさんにnice言われたのでハッピーです😳
Haha nice, I like it!
— Max Stoiber (@mxstbr) February 4, 2018
よかったら是非スターお願いします🤩
何かあればTwitterまたはコメント欄までフィードバックお願いします。
styled-styleをpublishしました🎉
— 𝔸𝕂𝔸𝕄𝔼@アルバイト.js (@akameco) February 4, 2018
css-modulesからCSSinJSへ橋渡し。classNameにさよならしてstyled-componentsのようなreadableなコンポーネントにhttps://t.co/DVtbOErvik pic.twitter.com/GQX0tf6gkw
フルサンプル
.center {
display: flex;
justify-content: center;
align-items: center;
}
.btn {
border-radius: 3px;
padding: 0.25em 1em;
margin: 0 1em;
background: transparent;
color: palevioletred;
border: 2px solid palevioletred;
}
.primary {
background: palevioletred;
color: white;
}
import { styledStyle } from 'styled-style'
import styles from './styles.module.css'
const { div, button } = styledStyle(styles)
const Center = div('center')
const Button = button('btn')
const PrimaryButton = button(['btn', 'primary'])
render(
<Center>
<Button>Normal Button</Button>
<PrimaryButton>Primary Button</PrimaryButton>
</Center>
)
Passed props
const Button = button(['btn', p => p.color === 'primary' && 'primary'])
render(
<div>
<Button>Normal Button</Button>
<Button color="primary">Primary Button</Button>
</div>
)