Stack Components using Twin.macro
I like to use Tailwind via twin.macro for styling. These are a VStack
and HStack
components that can be used to layout UI in React.
<HStack space={4}>
<div tw="bg-blue-500 w-20 h-20" />
<div tw="bg-blue-500 w-20 h-20" />
<div tw="bg-blue-500 w-20 h-20" />
</HStack>
Implementation
twin.macro runs at build time so we need to define all possible styles upfront. This gives us ability to space between 0 and 16 in horizontal and vertical directions.
import tw, { TwStyle } from "twin.macro";
export interface StackProps {
justify?: JustifyValues;
align?: AlignValues;
space?: StackSpace;
className?: string;
}
type JustifyValues = "center" | "between" | "start" | "end";
type AlignValues = "center" | "start" | "end" | "baseline";
const justifyValues: Record<JustifyValues, TwStyle> = {
center: tw`justify-center`,
between: tw`justify-between`,
start: tw`justify-start`,
end: tw`justify-end`,
};
const alignValues: Record<AlignValues, TwStyle> = {
center: tw`items-center`,
baseline: tw`items-baseline`,
start: tw`items-start`,
end: tw`items-end`,
};
type StackSpace = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 14 | 16;
const vSpaces: Record<StackSpace, TwStyle> = {
0: tw`space-y-0`,
1: tw`space-y-1`,
2: tw`space-y-2`,
3: tw`space-y-3`,
4: tw`space-y-4`,
5: tw`space-y-5`,
6: tw`space-y-6`,
7: tw`space-y-7`,
8: tw`space-y-8`,
9: tw`space-y-8`,
10: tw`space-y-8`,
12: tw`space-y-12`,
14: tw`space-y-14`,
16: tw`space-y-16`,
};
const hSpaces: Record<StackSpace, TwStyle> = {
0: tw`space-x-0`,
1: tw`space-x-1`,
2: tw`space-x-2`,
3: tw`space-x-3`,
4: tw`space-x-4`,
5: tw`space-x-5`,
6: tw`space-x-6`,
7: tw`space-x-7`,
8: tw`space-x-8`,
9: tw`space-x-8`,
10: tw`space-x-8`,
12: tw`space-x-12`,
14: tw`space-x-14`,
16: tw`space-x-16`,
};
const BaseStack: React.FC<StackProps & { dir: "vertical" | "horizontal" }> = ({
dir,
justify,
align,
space,
...props
}) => (
<div
{...props}
css={[
dir === "vertical" ? tw`flex flex-col` : tw`flex`,
dir === "vertical" ? vSpaces[space ?? 0] : hSpaces[space ?? 0],
justify != null && justifyValues[justify],
align != null && alignValues[align],
]}
/>
);
export const HStack: React.FC<StackProps> = props => (
<BaseStack {...props} dir="horizontal" />
);
export const VStack: React.FC<StackProps> = props => (
<BaseStack {...props} dir="vertical" />
);
tags: web
Links to this page
Last Updated February 27, 2021