あなたのアプリを右の道をスタート!特長は、スタイルシステム、スタイルのコンポーネントと入力スクリプト


アプリの代入として、より一貫したタイポグラフィ/テーマを実装する必要がありました.あなたのアプリケーションを介して一貫性が不可欠であり、また、多くの時間を節約できます.ので、代わりに、フォントの家族、あなたの余白、またはあなたのプライマリの色を設定するには、これらのボタンをリファクタリングの場合は、これを開始することができますし、もはや心配しないでください.これにアプローチする方法について多くの記事がありました、そして、それは新しい何かでありません、しかし、それについて書くことは私が練習したことを学んだものを置く優れた運動のようです.これらの記事を読んでいる間、私は遭遇したstyled-system , 簡単にあなたのコンポーネントのために利用できる小道具を作ることができる印象的なライブラリ.この図書館はこの記事の基礎になります.記事は記事の最後に記載されます.
私はあなたのアプリのためのスタイルガイドの基礎を設定する方法については、チュートリアルでは、この手順をお楽しみください.我々は、ストーリーブックのスタイルガイドショーケースまであなたのアプリを作成すると起動から、ゼロからすべてを行うつもりです.始めましょう!
あなたがこれを何千回もやったのでセットアップを通して空想しないならば、ここでは、この記事が書かれる方法です
この記事の書き方
  • Setup
  • Theme structure
  • Dynamic component
  • Setting up the typography styles and components
  • Reference story in Storybook
  • Wrapping up
  • Sources
  • セットアップ

    アプリを作成し、余分なパッケージをインストールする


    作成反応アプリは反応アプリのための素晴らしいスタートです、我々はTypescript すべての素晴らしい機能を取得するにはnpx create-react-app react-styleguide --typescript必要なパッケージをインストールします.yarn add styled-components @types/styled-components styled-system @types/styled-system react-router-dom次に、devの依存関係を追加します.yarn add -D prettier eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react eslint-config-prettier eslint-plugin-prettier最後に我々がインストールする必要がありますstorybookです.ストーリーブック私たちのテーマ(タイポグラフィ、色、スペース、ブレークポイント)のリファレンスショーケースを作成するために使用されます.npx -p @storybook/cli sb init --type reactStoryBookは、あなたのコンポーネントをプロトタイプに使用できる便利なツールです.私はストーリーブック駆動の開発についての記事を書いても前に物語の基礎を紹介します.あなたはそれを読むことができますhere .

    プリセット&エスニック設定


    私たちはコードを素敵できちんとしたものにしたいのでprettier and eslint 我々の通路に我々を保つために.これらは以前の手順で既にインストールされていましたが、今は設定しなければなりません.
    eslint ( eslinrc )の設定は以下のようになります.
    {
          "parser": "@typescript-eslint/parser",
          "extends": [
            "eslint:recommended",
            "plugin:react/recommended",
            "plugin:@typescript-eslint/recommended",
            "prettier/@typescript-eslint",
            "plugin:prettier/recommended"
          ],
          "parserOptions": {
            "ecmaVersion": 2018,
            "sourceType": "module",
            "ecmaFeatures": {
              "jsx": true
            }
          },
          "rules": {
            "prettier/prettier": [
              "error",
              {
                "singleQuote": true
              }
            ],
            "react/prop-types": "off",
            "@typescript-eslint/no-explicit-any": "error"
          },
          "settings": {
            "react": {
              "version": "detect"
            }
          }
        }
    
    そして、このようなprettier (. prettierrc )
    {
      "trailingComma": "es5",
      "tabWidth": 2,
      "singleQuote": true,
      "printWidth": 140
    }
    
    どちらのファイルもプロジェクトのルートで作成する必要があります.

    物語のセットアップ


    幸運にも、我々のために、StoryBookは現在、typescriptで箱から働きます.我々はちょうど将来の使用のためにいくつかのことを設定する必要があります.我々は、我々のthemeproviderとルータ(リンクのために)を設定します.次のコードをペーストでコピーできます.ジェイ.絵本フォルダ.
    import { addDecorator, configure } from '@storybook/react';
    import { ThemeProvider } from 'styled-components';
    import React from 'react';
    import { Router } from 'react-router-dom';
    import { createBrowserHistory } from 'history';
    
    const history = createBrowserHistory();
    
    addDecorator(story => (
      <ThemeProvider theme={{}}>
        <Router history={history}>{story()}</Router>
      </ThemeProvider>
    ));
    
    configure(require.context('../src', true, /\.stories\.tsx$/), module);
    
    このファイルでいくつかのことをします.
  • セットアップThemeProvider 今のところ空のオブジェクトで、我々はまだテーマがないので
  • セットアップRouter , 我々のLink コンポーネントはストーリーブックで中断しません
  • 変更するcontext 機能なので、それを拾う.tsx ファイル.
  • フォルダの変更context 関数はストーリーを検索します(コンポーネントと一緒に話を続けるのが好きです)
  • 次に、ストーリーブック(0 - welcome . stories . js)から提供するデモストーリーの拡張機能を変更することができますjs to tsx そして、我々の中にそれを動かしてくださいsrc すべてが動作しているかどうかを確認するフォルダ.走ってみるyarn storybook , そして、あなたが下の画面を参照する場合は、あなたの童話の設定が完了している.グッドジョブ!🔥

    あなたがこれを見ないならば、心配しないでください、私はあなたを得ました.あなたは、私がチェックポイントとして作ったこのブランチをクローンすることができますbranch だから、チュートリアルに従って続行することができます

    今、我々は手を汚すために準備ができています、我々のテーマ構造から始めましょう!

    テーマ構造の作成

    Our theme is the skeleton of the app, this is where we define our standards ( most of them ) and how these should be used. We are heavily relying on styled-system for this. There are a few things we want to define in our theme:

    • Space
    • Breakpoints ( for responsive fonts )
    • Colors
    Let's start by making a folder in our src folder called styleguide. In this folder, we can create a defaulTheme.ts . In this file, we will define our theme. This theme will have the structure of the type provided by styled-system . You can read the specification of the theme here
    私たちはこの記事のためにこれらのすべてのプロパティを使用することはありません、それはあまりにも多くの仕事とおそらく少し退屈な読み取りになります.それで、我々はスペース、ブレークポイントと色だけを設定することによってそれを単純にし続けるつもりです.

    スペース


    あなたのスペースを定義するポイントは、あなたのアプリケーションの場所のすべての一貫性のないピクセルを避けるためです.定義済みのスペース値を使用すると、より予測可能な結果を持つことになります.しかし、私はこのように説明された幾何学的な進行が好きですarticle Tシャツサイズアプローチと組み合わさりました.このように見えます.
    export interface Space {
      NONE: number;
      XS: number;
      S: number;
      M: number;
      L: number;
      XL: number;
      XXL: number;
    }
    
    export const space: Space = {
      NONE: 0,
      XS: 2,
      S: 4,
      M: 8,
      L: 16,
      XL: 32,
      XXL: 64,
    };
    
    

    ブレークポイント


    次はブレークポイントです.これらのブレークポイントは主に応答フォントで使用されます.
    export const breakpoints: string[] = ['319px', '424px', '767px', '1023px'];
    


    これらの色は非常に独断的です、そして、あなたはあなたの色をあなたが望む方法をセットアップすることができます.私は、ちょうどあなたに彼らを準備する方法の考えを与えます.スタイルシステムが使用するCSSTYPEを使用していることに注意してください.
    import * as CSS from 'csstype';
    
    export interface ThemeColors {
      primary: CSS.ColorProperty;
      link: CSS.ColorProperty;
      success: CSS.ColorProperty;
      warning: CSS.ColorProperty;
      error: CSS.ColorProperty;
      heading: CSS.ColorProperty;
      text: CSS.ColorProperty;
      disabled: CSS.ColorProperty;
      border: CSS.ColorProperty;
    }
    
    export const colors: ThemeColors = {
      primary: '#423EA2',
      link: '#1890ff',
      success: '#52c41a',
      warning: '#faad14',
      error: '#e84118',
      heading: '#423EA2',
      text: '#000',
      disabled: '#f5222d',
      border: '#423EA2',
    };
    
    
    最後に、私たちのデフォルトテーマ.TS
    import { Theme } from 'styled-system';
    import { colors } from './colors';
    import { space } from './space';
    
    export const breakpoints: string[] = ['319px', '424px', '767px', '1023px'];
    
    export const defaultTheme: Theme = {
      space: {
        ...space,
      },
      breakpoints,
      colors: {
        ...colors,
      },
    };
    
    
    これらを定義すると、次のようなコンポーネントでそれらを使用できます.
    
    const Button = styled.button`
      background-color: ${({ theme }) => theme.colors.primary};
      padding: ${({ theme }) => theme.space.M}px;
      margin: ${({ theme }) => theme.space.M}px;
      width: 200px;
      border: none;
      color: white;
      font-size: 14px;
      font-weight: 700;
      border-radius: 15px;
      letter-spacing: 2px;
      text-transform: uppercase;
    `;
    
    結果

    動的スタイルコンポーネントの作成

    Next up, we will be making our dynamic styled component with all the styled-system props built-in. Here is were styled-system shines as we only have to use the style functions they provide.

    import React from 'react';
    import styled from 'styled-components';
    import {
      borderRadius,
      BorderRadiusProps,
      color,
      fontFamily,
      FontFamilyProps,
      fontSize,
      FontSizeProps,
      fontStyle,
      FontStyleProps,
      fontWeight,
      FontWeightProps,
      letterSpacing,
      LetterSpacingProps,
      lineHeight,
      LineHeightProps,
      size,
      SizeProps,
      space,
      SpaceProps,
      textAlign,
      TextAlignProps,
      textStyle,
      TextStyleProps,
    } from 'styled-system';
    
    export type StyledSystemProps =
      | SpaceProps
      | FontSizeProps
      | FontStyleProps
      | SizeProps
      | TextStyleProps
      | LetterSpacingProps
      | FontFamilyProps
      | FontWeightProps
      | BorderRadiusProps
      | FontFamilyProps
      | LineHeightProps
      | TextAlignProps
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      | { color: string; as?: keyof JSX.IntrinsicElements | React.ComponentType<any> };
    
    export default styled.div`
      ${space}
      ${fontSize}
      ${fontStyle}
      ${size}
      ${color}
      ${textStyle}
      ${letterSpacing}
      ${fontFamily}
      ${fontWeight}
      ${borderRadius}
      ${lineHeight}
      ${textAlign}
    `;
    

    This means that this component now has a bunch of props ready to be used for easy styling. This dynamic component will be the foundation for setting up all our typography types.

    すべてのタイポグラフィのスタイルとコンポーネントの設定

    Now we can start creating our text styles. I am not an expert on typography, but these guidelines from BBC タイポグラフィの調和に良い導入を与える.テキストのスタイルは次のようになります.
    import { colors } from './colors';
    import { StyledSystemProps } from './DynamicStyledSystemComponent';
    
    const fontFamilies: { heading: string; body: string } = {
      heading: 'Montserrat, serif',
      body: 'Raleway, sans-serif',
    };
    
    interface TypographyStyles {
      H1: StyledSystemProps;
      H2: StyledSystemProps;
      H3: StyledSystemProps;
      H4: StyledSystemProps;
      H5: StyledSystemProps;
      LargeLead: StyledSystemProps;
      SmallLead: StyledSystemProps;
      Paragraph: StyledSystemProps;
      SmallParagraph: StyledSystemProps;
      Link: StyledSystemProps;
    }
    export const typographyStyles: TypographyStyles = {
      H1: {
        fontSize: [50, 51, 52, 57],
        fontWeight: 700,
        fontFamily: fontFamilies.heading,
        as: 'h1',
      },
      H2: {
        fontSize: [37, 39, 41, 43],
        fontWeight: 700,
        color: colors.primary,
        fontFamily: fontFamilies.heading,
        as: 'h2',
      },
      H3: {
        fontSize: [27, 28, 30, 32],
        fontWeight: 700,
        fontFamily: fontFamilies.heading,
        as: 'h3',
      },
      H4: {
        fontSize: [18, 20, 22, 24],
        fontWeight: 700,
        color: colors.primary,
        fontFamily: fontFamilies.heading,
        as: 'h4',
      },
      H5: {
        fontWeight: 700,
        fontSize: [16, 17, 19, 21],
        fontFamily: fontFamilies.heading,
        as: 'h5',
      },
      LargeLead: {
        fontWeight: 500,
        fontSize: [18, 20, 22, 24],
        fontFamily: fontFamilies.heading,
        as: 'p',
      },
      SmallLead: {
        fontWeight: 500,
        fontSize: [17, 18, 19, 21],
        fontFamily: fontFamilies.heading,
        as: 'p',
      },
      Paragraph: {
        fontSize: [14, 15, 15, 16],
        fontWeight: 300,
        fontFamily: fontFamilies.body,
        as: 'p',
      },
      SmallParagraph: {
        fontSize: [13, 14, 14, 15],
        fontWeight: 300,
        fontFamily: fontFamilies.body,
        as: 'p',
      },
      Link: {
        fontWeight: 700,
        color: colors.primary,
        fontSize: [14, 15, 15, 16],
        fontFamily: fontFamilies.body,
      },
    };
    
    これらのテキストスタイルで、タイポグラフィコンポーネントを作成できます.私たちは2つの引数があるヘルパー機能CreateComponentを作成することができます:対応するスタイリング小道具、それは表示名です.リンクコンポーネントは、CREATE DOMリンクコンポーネントを使用する必要があるので、CreateComponent関数で作成されません.
    import React from 'react';
    import { Link as RouterLink, LinkProps } from 'react-router-dom';
    import DynamicStyledSystemComponent, { StyledSystemProps } from './DynamicStyledSystemComponent';
    import { typographyStyles } from './typographyStyles';
    
    type AnchorProps = StyledSystemProps & Pick<LinkProps, 'to'> & { onClick?: (event: React.MouseEvent<HTMLAnchorElement>) => void };
    
    const Link: React.FC<AnchorProps> = ({ to, onClick, children, ...props }) => (
      <RouterLink to={to} onClick={onClick}>
        <DynamicStyledSystemComponent {...typographyStyles.Link} {...props}>
          {children}
        </DynamicStyledSystemComponent>
      </RouterLink>
    );
    
    interface TypographyComponentProps {
      H1: React.FC<StyledSystemProps>;
      H2: React.FC<StyledSystemProps>;
      H3: React.FC<StyledSystemProps>;
      H4: React.FC<StyledSystemProps>;
      H5: React.FC<StyledSystemProps>;
      LargeLead: React.FC<StyledSystemProps>;
      SmallLead: React.FC<StyledSystemProps>;
      Paragraph: React.FC<StyledSystemProps>;
      SmallParagraph: React.FC<StyledSystemProps>;
      Link: React.FC<AnchorProps>;
    }
    
    const createComponent: (textStyle: StyledSystemProps, displayName: string) => React.FC<StyledSystemProps> = (textStyle, displayName) => {
      const component: React.FC<StyledSystemProps> = props => (
        <DynamicStyledSystemComponent {...textStyle} {...props}>
          {props.children}
        </DynamicStyledSystemComponent>
      );
      component.displayName = displayName;
      return component;
    };
    
    export const Typography: TypographyComponentProps = {
      H1: createComponent(typographyStyles.H1, 'H1'),
      H2: createComponent(typographyStyles.H2, 'H2'),
      H3: createComponent(typographyStyles.H3, 'H3'),
      H4: createComponent(typographyStyles.H4, 'H4'),
      H5: createComponent(typographyStyles.H5, 'H5'),
      LargeLead: createComponent(typographyStyles.LargeLead, 'LargeLead'),
      SmallLead: createComponent(typographyStyles.SmallLead, 'SmallLead'),
      Paragraph: createComponent(typographyStyles.Paragraph, 'Paragraph'),
      SmallParagraph: createComponent(typographyStyles.SmallParagraph, 'SmallParagraph'),
      Link: Link,
    };
    
    これで、タイポグラフィーのコンポーネントを使うことができます.私は、この物語の次のショーケースです.

    絵本の参考記事

    We can showcase how our styleguide is setup by making a storybook story. This will serve as a reference if you ever want to know which Typography, color, space you want to use.

    import React from 'react';
    import { storiesOf } from '@storybook/react';
    import { Typography } from './Typography';
    import styled from 'styled-components';
    import { colors } from './colors';
    import { breakpoints } from './theme';
    import { space } from './space';
    
    const { H1, H2, H3, H4, H5, LargeLead, Link, Paragraph, SmallLead, SmallParagraph } = Typography;
    
    storiesOf('Styleguide ', module)
      .addParameters({ viewport: { defaultViewport: 'default' } })
      .add('default', () => (
        <Container>
          <H2>Typography</H2>
          <Divider />
          <H1>H1: Animi aperiam, aspernatur culpa deserunt eaque, eius explicabo inventore ipsa laudantium</H1>
          <H2>H2: Consectetur consequuntur cum deserunt dignissimos esse fugiat inventore iusto, laboriosam maiores minima!.</H2>
          <H3>H3: Culpa dignissimos expedita facilis, fugiat minus odio reiciendis ut? Accusamus delectus dicta eius.</H3>
          <H4>H4: Accusamus ad adipisci alias aliquam aperiam autem, culpa dolorem enim error est eum.</H4>
          <H5>H5: Debitis distinctio dolorum fugiat impedit itaque necessitatibus, quo sunt? Atque consectetur, corporis.</H5>
          <LargeLead>LargeLead:Deleniti est facere id placeat provident sapiente totam vitae. Asperiores consequuntur eaque eum.</LargeLead>
          <SmallLead>SmallLead: At aut corporis culpa doloribus ea enim error est impedit, ipsum iure maxime molestiae omnis optio.</SmallLead>
          <Paragraph>
            Paragraph: Facilis hic iste perspiciatis qui quibusdam sint velit vero Animi doloremque esse ex iure perferendis.
          </Paragraph>
          <SmallParagraph>SmallParagraph: Ad animi at debitis eligendi explicabo facere illum inventore, ipsum minus obcaecati.</SmallParagraph>
          <Link to="/">Link: Lorem ipsum dolor sit amet, consectetur adipisicing elit.</Link>
          <Divider />
          <H2>Colors</H2>
          <Paragraph>These colors are defined in styleguide colors.ts.</Paragraph>
          <Divider />
          <GridContainer>
            <div>
              <SmallParagraph>Kind</SmallParagraph>
            </div>
            <div>
              <SmallParagraph>HEX</SmallParagraph>
            </div>
            <div>
              <SmallParagraph>Color</SmallParagraph>
            </div>
          </GridContainer>
          {Object.entries(colors).map(obj => (
            <GridContainer key={obj[0]}>
              <SmallParagraph>{obj[0]}</SmallParagraph>
              <SmallParagraph>{obj[1]}</SmallParagraph>
              <ColorCircle color={obj[1]} />
            </GridContainer>
          ))}
          <Divider />
          <H2>Breakpoints</H2>
          <Paragraph>These are the responsive breakpoints being used</Paragraph>
          <br />
          <FlexContainer>
            {breakpoints.map((key: string) => (
              <SmallParagraph key={key} m={4}>
                {key}
              </SmallParagraph>
            ))}
          </FlexContainer>
          <Divider />
          <H2>Space</H2>
          <FlexContainer>
            {Object.entries(space).map(obj => (
              <div key={obj[0]}>
                <SmallParagraph m={2}>
                  <strong>{obj[1]}px</strong>
                </SmallParagraph>
                <SmallParagraph m={2}>{obj[0]}</SmallParagraph>
              </div>
            ))}
          </FlexContainer>
        </Container>
      ));
    
    const Divider = styled.div`
      border: 1px solid #00000022;
      width: 100%;
      margin: ${({ theme }) => theme.space.M}px;
    `;
    
    const ColorCircle = styled.div<{ color: string }>`
      height: 20px;
      width: 20px;
      border-radius: 20px;
      background-color: ${({ color }) => color};
    `;
    
    const GridContainer = styled.div`
      display: grid;
      grid-template-columns: 150px 150px 150px;
      margin: ${({ theme }) => theme.space.M}px;
    `;
    
    const FlexContainer = styled.div`
      display: flex;
    `;
    
    const Container = styled.div`
      background-color: white;
      height: 100vh;
      padding: 16px;
    `;
    

    ラッピング

    So this was my take on how to setup a styleguide for you next react app. Hope you enjoyed the post and until the next one! Cheers

    Github repo

    ソース


    https://levelup.gitconnected.com/building-a-react-typography-system-f9d1c8e16d55
    https://www.bbc.co.uk/gel/guidelines/typography
    https://sproutsocial.com/seeds/visual/typography/
    https://medium.com/eightshapes-llc/space-in-design-systems-188bcbae0d62