web-dev-qa-db-ja.com

感情CSS-in-JS-コンポーネントの小道具に基づいて条件付きCSSを追加する方法?

Emotion でスタイル付けされ、最終的にスタイリングを制御する小道具を受け取るコンポーネントが欲しいのですが。たとえば、パディングと幅を変更するさまざまな小道具があるGridColコンポーネントを考えます(幅はビューポートの異なる幅で変更できます)。

次のようなAPIを使用したいと思います。

<GridCol Gutter size="2>

// or alternatively, like this:

<GridCol Gutter size={{
  m: 2,
  l: 4
}}>

ここでは3つのことが起こります。

  • Gutterは、列に水平方向のパディングを追加するブールプロップです。
  • sizeプロパティは文字列またはオブジェクトです。文字列の場合は数行のCSSを追加するだけで十分ですが、オブジェクトの場合は、他の場所に設定されているブレークポイントオブジェクトに基づいてメディアクエリを挿入する必要があります。

Emotionのドキュメント この性質のスタイリングを処理する方法が明確ではありません。少なくとも私はそれを見たことがないので、共通の解決策が見つかることを期待していました。

Gutterプロップの場合、それは簡単です:

const GridCol = props => styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props.Gutter ? `0 10px` : '0'};
`

sizeプロップの場合は、さらに複雑になります。結果のCSSは次のようになります。

const GridCol = props => styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props.Gutter ? `0 10px` : '0'};

  /* styles here if  `size` is a string */
  width: 10%;

  /* styles here if  `size` is an object */
  @media screen and (min-width: 500px) {
      width: 20%;
  }


  @media screen and (min-width: 800px) {
      width: 30%;
  }


  @media screen and (min-width: 1100px) {
      width: 40%;
  }
`

width値は、breakpointsオブジェクトの値に対応するプロップのキーによって決定されます。この部分は簡単ではありませんが、必要なcssを動的に生成する方法がわかりません。

追加できる情報は他にもあると思います。いくつか試みましたが、現時点ではどれも機能していません。私は、各条件のcssを生成し、最後にCSSに結合するステートレス機能コンポーネントを作成する必要があると感じています。

8
Zander

これは素晴らしい質問です。まず、このパターンを避けます。

const GridCol = props => styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props.Gutter ? `0 10px` : '0'};
`

この例では、新しいスタイルのコンポーネントがすべてのレンダリングで作成されますが、パフォーマンスはひどいものです。

任意の式、または補間を関数にすることができます。この関数は2つの引数を受け取ります:propsおよびcontext

const GridCol = styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props => props.Gutter ? `0 10px` : '0'};
`

あなたの例のsize propについては、次のパターンを使用します。

import { css } from 'emotion'

const sizePartial = (props) => typeof props.size === 'string' ?
  css`width: 10%;` :
  css`
   @media screen and (min-width: 500px) {
      width: 20%;
   }


   @media screen and (min-width: 800px) {
      width: 30%;
   }


   @media screen and (min-width: 1100px) {
      width: 40%;
   }
 `

次に、式で発生する他の関数と同じように、パーシャルを使用できます。

const GridCol = styled('div')`
  display: block;
  box-sizing: border-box;
  flex: 1 0 0;
  min-width: 0;
  padding: ${props => props.Gutter ? `0 10px` : '0'};
  ${sizePartial};
`

これは、プロジェクト全体で再利用可能な動的スタイルを作成するために使用できる非常に強力なパターンです。

このパターンを利用する他のライブラリに興味がある場合は、 https://github.com/emotion-js/facepainthttps://github.com/jxnblk/styled-をチェックしてください。システム

19
tkh44