レイアウト用のコンポーネントがあると便利
2024-05-13
7 months ago
開発環境
- next 14.2.3
- tailwind 3.4.1
前提
あると便利なコンポーネントの紹介です。
MUIやChakraUIなど、UIコンポーネントライブラリを利用していないプロジェクトを前提にしています。
本題
フロントエンドの実装ではButtonやCardのような汎用的なコンポーネントを使い回すことが多いと思いますが、レイアウトだけを提供するコンポーネントも同じように実装しているとコードもスッキリし、統一した実装がしやすくなるので便利です。
今回はFlexBoxのStackという汎用的なコンポーネントを紹介します。
サンプル
import type { ReactNode } from 'react';
const directions = {
row: 'flex-row',
col: 'flex-col',
};
const justifyContents = {
start: 'justify-start',
center: 'justify-center',
end: 'justify-end',
between: 'justify-between',
around: 'justify-around',
evenly: 'justify-evenly',
};
const alignItemsSet = {
start: 'items-start',
center: 'items-center',
end: 'items-end',
stretch: 'items-stretch',
};
const wraps = {
wrap: 'flex-wrap',
none: 'flex-nowrap',
};
const spacings = {
0: 'gap-0',
1: 'gap-1',
2: 'gap-2',
3: 'gap-3',
4: 'gap-4',
5: 'gap-5',
6: 'gap-6',
7: 'gap-[1.75em]',
8: 'gap-8',
10: 'gap-10',
12: 'gap-12',
};
type StackProps = {
children: ReactNode;
justifyContent?: keyof typeof justifyContents;
alignItems?: keyof typeof alignItemsSet;
direction?: keyof typeof directions;
spacing?: keyof typeof spacings;
wrap?: keyof typeof wraps;
};
export const Stack = ({
children,
justifyContent = 'start',
alignItems = 'center',
direction = 'row',
spacing = 2,
wrap = 'none',
}: StackProps) => {
return (
<div
className={`flex ${directions[direction]} ${justifyContents[justifyContent]} ${alignItemsSet[alignItems]} ${spacings[spacing]} ${wraps[wrap]}`}
>
{children}
</div>
);
};
利用例
<Stack direction="col" spacing={10}>
<Button />
<Link />
</Stack>
利用しなかった場合の例
<div className="flex flex-col justify-center items-center gap-10 flex-nowrap">
<Button />
<Link />
</div>
propsで指定していないところはデフォルト値のクラスがあたっています。
こうして見ると、かなりコードがスッキリしたことが分かります。
また、アプリケーション全体でこのようなFlexのスタイルが2〜3個ぐらいなら、利用しなかった場合の例のように個別でスタイルを当てても気になりませんが、そんなことはほぼないです。
実装するポイント
- 利用する側から自由にスタイルを当てれるようにする(propsにclassName追加)のもありですが、当てれないほうが、コンポーネントの責務がはっきりする(今回の場合は並びのレイアウトに責務を負っている)ので、メンテナンスしやすいです。
- デフォルト値は極力設定してあげた方がより利用しやすく、スタイルを統一しやすいです。
さいごに
MUIのStackコンポーネントを参考に、そのtailwind版のような形で実装しました。
今回紹介したコンポーネントも絶対に必要かと言われると、そうではないと思います。
実装方針に合わせて利用する、しないを決めていただければと思います。