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:
- Theme tokens (
$primary,$medium, etc.) - Pseudo-classes (
&:hover,&:focus, etc.) - Media queries (if configured)
- All CSS properties
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.
Related Pages
- Theme Setup - Learn about theme configuration
- API Reference: styled - Complete styled API documentation
- Utility Functions - Create custom CSS utilities