Stitches is a composable styling library for JS that is a great alternative for CSS modules, since components styled with Stitches can be extended with “inline” styles using the css
prop, or be used to define other, further Stitches styled components.
<Button css={{ background: "green" }}>Entertainment</Button>
Due to the composable nature of Stitches I was pretty bummed to find out that not a lot of documentation exists concerning composing Stitches components out of existing React components that utilize data, hooks and the like. Most of the blogs that can be found focus on the fact that “Yay! you can put Stitches components inside Stitches components!” – Well, of course you can, that’s not news. (Maybe all this is just Google acting on me and providing bad search results, what gives) But yeah, just creating styled components that can’t have any state in them is in my opinion not that cool.
// An example, ARE YOU NOT ENTERTAINED
import { styled } from "@stitches/react"
const Button = styled("button", {
border: "none",
borderRadius: "3px",
textDecoration: "uppercase",
})
const BetterButton = styled(Button,{ // YAY!
border: "2px solid #000",
})
Since I like to torture myself with Typescript, achieving what I wanted was probably a lot more difficult than just using regular Javascript. The generics in libraries can get pretty esoteric, but after a little head banging things weren’t as bad as initially thought.
Here’s a simpl-ish example of an input element styled with Stitches, utilizing the React UI library Radix UI:
import * as RadixCheckBox from "@radix-ui/react-checkbox"
import { styled } from "@stitches/react"
type CommonInputProps = {
className?: string
id?: string
name?: string
value?: string
ariaLabel?: string
autoComplete?: string
onChange?: FormEventHandler<HTMLDivElement>
}
type CheckBoxProps = CommonInputProps & {
children?: React.ReactNode
}
export const CheckBoxBase = ({id, name, value, children, className, ariaLabel}: CheckBoxProps) => {
const Wrapper = styled("div", {display: "flex", flexDirection: "row", gap: "0.5rem"})
return (
<Wrapper className={className}>
<RadixCheckBox.Root className="checkbox" id={id} name={name} value={value || "on"} aria-label={ariaLabel}>
<RadixCheckBox.Indicator className="checkboxIndicator">
<CheckIcon />
</RadixCheckBox.Indicator>
</RadixCheckBox.Root>
<label htmlFor={id}>{children}</label>
</Wrapper>
)
}
export const CheckBox = styled(CheckBoxBase, {})
To be quite honest, this kind of example is much more helpful for devs. This shows that Stitches passes a generated className
down to the styled component, which can be referenced in the props of the base component that has the logic.
Hoping this finds people and is helpful to them. Cheers.