On several occasions I saw people asking the question: "What's the best way to create variants using Styled components?"
And, because this variant feature is not natively supported by Styled Components I saw different people have different ways to approach this issue.
So, today I wanted to show you a couple of solutions that actually scales.
Note that this post will be split into two parts.
In this first one we are going to focus on how to create Styled Component variants within the same file.
The problem with if else or switch statements
Let's start by creating a simple Styled Component button with 3 variants:
const ButtonStyle = styled.button`
color: ${({ theme, flashy, disabled }) => {
if (flashy) return "fuchsia";
else if (disabled) return theme.grey;
else return theme.primary;
}};
`;
As you can see, here you will have to maintain an if else (or switch) condition every time.
Obviously you could externalise this to a specific function determineColor
but, still, the problem remains.
Solution 1
I have seen some people writing the same code as above in a more readable fashion:
const ButtonStyle = styled.button`
color: ${(props) => props.theme.primary};
${({ variant }) =>
variant == "flashy" &&
css`
color: "fushia";
`}
${({ variant }) =>
variant == "disabled" &&
css`
color: ${(props) => props.theme.grey};
`};
`;
Unfortunately, here again, you are kinda using an if-else statement.
Solution 2 using inheritance
My preferred solution is actually to use the built-in inheritance property of styled-components.
const ButtonStyle = styled.button`
color: ${(props) => props.theme.primary};
`;
const ButtonStyleFlashy = styled(ButtonStyle)`
color: fuchsia;
`;
const ButtonDisabled = styled(ButtonStyle)`
color: ${(props) => props.theme.grey};
`;
Here, ButtonStyleFlashy
and ButtonDisabled
inherits the CSS from ButtonStyle
.
Zooming out
As a rule of thumb when I am creating styled component variants within the same file
▶️ If I am sure that the component will have exactly 2 variants I will use a Boolean props
const ParagraphVariant = styled.p`
font-weight: ${(props) => (props.$bold ? `bold` : `normal`)};
`;
▶️ If the component has x variants then I will use inheritance as seen above.
Top comments (1)
Nice post!
Stitches has the optimal solution to this, if one dares to leave styled-components: stitches.dev/blog/migrating-from-s...