Transforming regular React components to Stitches components

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.

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 />
      <label htmlFor={id}>{children}</label>

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.

Subscribe to jantto
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
This entry has been permanently stored onchain and signed by its creator.