🥺

TypeScriptでCSSの単位を型安全に相互変換する_1

2020/11/29に公開2

https://www.npmjs.com/package/@karibash/pixel-units

サイズを渡す時に単位まで指定できない問題

下記のようなパディングの値を渡せるようなコンポーネントがあるとする
数値を渡せるようにしたが、これだと使用者側には単位が分からない
そもそもチーム内で使用する単位は統一しろっていう話だけど、、、

example.tsx
type Props = Readonly<{
  padding: number;
}>;
const Wrapper: React:FC<Props> = ({
  children,
  padding,
}) => {
  return (
    <div css={{ padding: `${padding}rem` }}>
      {children}
    </div>
  );
};

pixel-unitsを使って解決する

numberを使用したい単位の型に書き換えるだけ

example.tsx
import { Rem } from '@karibash/pixel-units';

type Props = Readonly<{
  padding: Rem;
}>;
const Wrapper: React:FC<Props> = ({
  children,
  padding,
}) => {
  return (
    <div css={{ padding: `${padding}` }}>
      {children}
    </div>
  );
};

export default Wrapper;

使う側はこんな感じ
Rem単位しか使えないようにコンポーネント側で強制できる

example.tsx
import { Rem } from '@karibash/pixel-units';
import Wrapper from 'components/wrapper';

const Page: React:FC = () => {
  const padding = new Rem(2);
  return (
    <Wrapper padding={padding}>
      {children}
    </Wrapper>
  );
};

export default Page;

単位の相互変換も出来る

remに変換する場合はルート要素のフォントサイズの指定が必要になる
そのため、ルート要素のフォントサイズを取得するヘルパー関数も用意している

example.ts
import { Pixel, tryFindRootFontSize } from '@karibash/pixel-units';

const pixel = new Pixel(32);
console.log(`${pixel}`);
// -> 32px

const rem = pixel.toRem(tryFindRootFontSize());
console.log(`${rem}`);
// -> 2rem

まとめ

暇だったから思いつきで作ったけどあんまり需要なさそう

Discussion

catnosecatnose

ちょうど同じあたりで悩むことが最近あって結局単位縛りしていたのですが、このアプローチはとても良さそうです。有益な情報ありがとうございます。

KaribashKaribash

需要があるのか分からずにコーディングしていたのでお役に立てて嬉しいです😭