Stoop
GitHub
/

Creating Components

Create styled components with Stoop

Basic Component

Create a styled component using the styled function:

import { styled } from "./theme";

const Button = styled("button", {
  padding: "$medium $large",
  borderRadius: "$default",
  backgroundColor: "$primary",
  color: "$background",
  border: "none",
  cursor: "pointer",
  "&:hover": {
    opacity: 0.9,
  },
});

With Variants

Add variants for different styles:

const Button = styled("button", {
  padding: "$medium $large",
  borderRadius: "$default",
  cursor: "pointer",
  variants: {
    variant: {
      primary: {
        backgroundColor: "$primary",
        color: "$background",
      },
      secondary: {
        backgroundColor: "$background",
        border: "1px solid $border",
      },
    },
    size: {
      small: {
        padding: "$small $medium",
        fontSize: "$small",
      },
    },
  },
});

<Button variant="primary" size="small">Click me</Button>

Boolean Variants

Create boolean variants:

const ToggleButton = styled("button", {
  padding: "$medium $large",
  borderRadius: "$default",
  variants: {
    active: {
      false: {
        backgroundColor: "$background",
      },
      true: {
        backgroundColor: "$primary",
        color: "$background",
      },
    },
  },
});

<ToggleButton active={true}>Active</ToggleButton>

Multiple Variants

Components support multiple variant props:

const Card = styled("div", {
  padding: "$large",
  borderRadius: "$default",
  variants: {
    variant: {
      outlined: { border: "1px solid $border" },
      filled: { backgroundColor: "$background" },
    },
    size: {
      small: { padding: "$small" },
      large: { padding: "$xlarge" },
    },
  },
});

<Card variant="outlined" size="small">Content</Card>

Polymorphic Components

Use the as prop to render different elements:

const Box = styled("div", {
  padding: "$medium",
});

<Box as="section">Content</Box>
<Box as="article">Article</Box>

Dynamic Styles with css Prop

Use the css prop to apply dynamic styles to styled components:

const Button = styled("button", {
  padding: "$medium $large",
  borderRadius: "$default",
});

function MyComponent() {
  const isActive = true;

  return (
    <Button
      css={{
        marginTop: "$large",
        backgroundColor: isActive ? "$primary" : "$background",
        "&:hover": {
          opacity: 0.8,
        },
      }}
    >
      Dynamic Button
    </Button>
  );
}

The css prop merges with the component's base styles and supports:

Merging order: Base styles → Variants → CSS properties as props → css prop (later styles override earlier ones)

CSS Properties as Props

CSS properties can be passed directly as props and convert to CSS styles:

const Box = styled("div", {
  padding: "$medium",
});

<Box marginTop="$large" padding="$small">
  Content
</Box>

CSS properties passed as props are merged after variants but before the css prop, allowing for prop-based overrides.

Component Targeting

Styled components expose a .selector property for targeting in nested styles:

const Button = styled("button", {
  padding: "$medium",
  backgroundColor: "$primary",
});

const Card = styled("div", {
  padding: "$large",
  [Button.selector]: {
    marginTop: "$medium",
  },
});

The selector is based on the component's base styles hash, making it stable across renders even if variants or CSS props change.