Skip to main content

Type-Safe by Default

Full TypeScript inference without manual typing or as const

Context Propagation

Variants automatically flow from parent to child components

Compound Components

Build complex components with the slots pattern

Universal

Same API for React Web and React Native

The Problem

When building UI components, you often need child elements to match their parent’s style. A button’s text should match the button’s size. A card’s header should match the card’s variant. The typical solution? Prop drilling.
// Without better-styled: manual prop drilling
<Button size="lg" variant="primary">
  <ButtonIcon size="lg" variant="primary" name="check" />
  <ButtonText size="lg" variant="primary">Submit</ButtonText>
</Button>
This gets tedious. And error-prone.

The Solution

With better-styled, you define the relationship once. Children inherit automatically.
// With better-styled: automatic inheritance
<Button size="lg" variant="primary">
  <Button.Icon name="check" />
  <Button.Label>Submit</Button.Label>
</Button>
Both Button.Icon and Button.Label know they should render as size="lg" and variant="primary". No repetition needed.

Quick Example

import { createStyledContext, styled, withSlots } from "better-styled";
import { Pressable, Text } from "react-native";

// 1. Define your variants
const ButtonContext = createStyledContext({
  size: ["sm", "md", "lg"],
  variant: ["primary", "secondary"],
});

// 2. Create the parent component
const ButtonRoot = styled(Pressable, {
  context: ButtonContext,
  base: { className: "rounded-lg items-center justify-center" },
  variants: {
    size: {
      sm: { className: "px-3 py-1.5" },
      md: { className: "px-4 py-2" },
      lg: { className: "px-6 py-3" },
    },
    variant: {
      primary: { className: "bg-blue-600" },
      secondary: { className: "bg-gray-600" },
    },
  },
});

// 3. Create child that inherits from context
const ButtonLabel = styled(Text, {
  context: ButtonContext,
  base: { className: "font-medium text-white" },
  variants: {
    size: {
      sm: { className: "text-sm" },
      md: { className: "text-base" },
      lg: { className: "text-lg" },
    },
  },
});

// 4. Export as compound component
export const Button = withSlots(ButtonRoot, {
  Label: ButtonLabel,
});
Now use it:
<Button size="lg" variant="primary">
  <Button.Label>Click me</Button.Label>
</Button>
The label automatically gets size="lg" from the parent. Clean and maintainable.

Why better-styled?

Featuretailwind-variantsbetter-styled
Variants
Compound Variants
Context Propagation
Compound Components
Type InferenceNeeds as const✅ Automatic
React Native

Next Steps