styled-componentsで再利用可能なグリッドレイアウトを作る

やること

Reactでコンポーネントを組み立ててUI作っていくのも楽なんですが、 styled-componentsでグリッドレイアウトのコンポーネントを作って、 それらを組み合わせて使うと非常に楽だということに気がつきました。

一度作ったやつを取っておけば再利用することもできますし:open_hands_tone2:

styled-componentsで書いたcssの記述も整理しやすいですし、おすすめです。 GitHub参考 => https://github.com/yutaro1204/styled-components-demo

前提

・styled-componentの使い方 ・CSSでのdisplay: grid;の使い方

TypeScriptでReactのコンポーネントを書いていきますので、tsxを使います。

導入

まず気楽にcreate-react-appを使います。

$ npx create-react-app app-name --typescript

create-react-appが入っている場合はnpxは不要です。

styled-componentsをインストールします。

$ yarn add styled-components @types/styled-components

アプリを立ち上げます。デフォルトはhttp://localhost:3000となります。

$ yarn start

コーディング

最終的にこんな感じの構造になります。

app-name/src
├── App.css
├── App.test.tsx
├── App.tsx
├── components
│   ├── Header.tsx // 追加
│   ├── Main.tsx // 追加
│   └── Sidepane.tsx // 追加
├── index.css
├── index.tsx
├── logo.svg
├── modules
│   └── styled-components.ts // 追加
├── react-app-env.d.ts
└── serviceWorker.ts

デフォルトで入っているsrcディレクトリ配下にmodulesディレクトリみたいなのを作って、 styled-components用のファイルを作成します。

// styled-components.ts

import style from 'styled-components'

const styledComponents = {
  LayoutStyles: {
    Body: {
      Grid: style.div`
        display: grid;
        grid-template-columns: 300px 1fr;
        grid-template-rows: 80px 1fr;
      `
    },
    Header: {
      Grid: style.div`
        grid-column: 1 / 3;
        grid-row: 1 / 2;
        display: grid;
        grid-template-columns: 40px 1fr 1fr 1fr 1fr 40px;
        background-color: #008080;
      `,
      // 状況によってgrid-columnの値を変化させる
      Item: style.div`
        grid-column: ${ ({theme}) => theme.column };
        max-height: 80px;
      `
    },
    Main: {
      Grid: style.div`
        grid-column: 2 / 3;
        grid-row: 2 / 3;
        display: grid;
        grid-template-columns: 100px 1fr 1fr 1fr 1fr 100px;
        height: calc(100vh - 80px);
        overflow-y: scroll;
        background-color: #ffe4c4;
      `,
      Item: style.div`
        grid-column: ${ ({theme}) => theme.column };
        grid-row: ${ ({theme}) => theme.row };
        height: 200px;
      `,
    },
    Sidepane: {
      Grid: style.div`
        grid-column: 1 / 2;
        grid-row: 2 / 3;
        height: calc(100vh - 80px);
        overflow-y: scroll;
        background-color: #696969;
      `,
      Item: style.div`
        width: 100%;
        height: 200px;
      `
    }
  },
  ComponentStyles: {
    // As you prefer...
  }
}

export default styledComponents

ここでは、LayoutStylesにBodyやHeaderなどのCSS情報をまとめたものと、 その他の細かいコンポーネントCSS情報をComponentsStylesにまとめるようにしています(ここには何も書いていません)。

上のstyled-components.tsに従ってtsxを書き換えるとこんな感じになりました:point_down_tone2:

// App.tsx

import React from 'react'

import styledComponents from './modules/styled-components'

import Header from './components/Header'
import Sidepane from './components/Sidepane'
import Main from './components/Main'

const BodyGrid = styledComponents.LayoutStyles.Body.Grid

const App: React.FC = () => {
  return (
    <BodyGrid>
      <Header />
      <Sidepane />
      <Main />
    </BodyGrid>
  )
}

export default App

んで、参考までにこのHeaderコンポーネントとなっているHeader.tsxはこんな感じに:point_down_tone2:

// Header.tsx

import React from 'react'
import styledComponents from '../modules/styled-components'

const HeaderGrid = styledComponents.LayoutStyles.Header.Grid
const HeaderItem = styledComponents.LayoutStyles.Header.Item

const Header: React.FC = () => {
  return (
    <HeaderGrid>
      <HeaderItem theme={{ column: '2 / 3' }}>
        <p>Grid1</p>
      </HeaderItem>
      <HeaderItem theme={{ column: '3 / 4' }}>
        <p>Grid2</p>
      </HeaderItem>
      <HeaderItem theme={{ column: '4 / 5' }}>
        <p>Grid3</p>
      </HeaderItem>
      <HeaderItem theme={{ column: '5 / 6' }}>
        <p>Grid4</p>
      </HeaderItem>
    </HeaderGrid>
  )
}

export default Header

おんなじ要領でHeader、Sidepane、Mainを組み合わせると、こんな感じになります。

Screenshot 0031-06-02 at 9.46.36 PM.png

ちょっと地味ですが、ここから色々装飾すればそれなりになるかと:information_desk_person:

styled-componentsとreactDnDをつかってなんか作りたい今日この頃。。。