Skip to main content

Signature

function createStyledContext<T extends StyledContextInput>(
  variants: T
): StyledContext<T>

Parameters

variants
object
required
An object defining the variant names and their possible values.Each key is a variant name. Each value is an array of possible values.
{
  size: ["sm", "md", "lg"],
  variant: ["primary", "secondary"],
  disabled: ["boolean"],
}

Special Values

["boolean"]
array
Use ["boolean"] for true/false variants. This produces a proper boolean type instead of "true" | "false".
createStyledContext({
  disabled: ["boolean"],  // Type: boolean
  loading: ["boolean"],   // Type: boolean
});

Returns

StyledContext
object
An object with:
Context
React.Context
The underlying React context. Rarely needed directly.
Provider
React.Provider
The context provider component. Used internally by styled components.
useVariants
function
Hook to read current variant values. Returns null outside a provider.
const context = createStyledContext({ size: ["sm", "lg"] });

function Child() {
  const variants = context.useVariants();
  // variants: { size: "sm" | "lg" } | null
}
variantKeys
T
The original variants object. Used for type inference.

Examples

Basic

import { createStyledContext } from "better-styled";

const CardContext = createStyledContext({
  size: ["sm", "md", "lg"],
  elevated: ["boolean"],
});

With styled()

const CardContext = createStyledContext({
  variant: ["default", "outlined"],
});

const CardRoot = styled("div", {
  context: CardContext,
  variants: {
    variant: {
      default: { className: "bg-white shadow" },
      outlined: { className: "border-2 border-gray-200" },
    },
  },
});

const CardTitle = styled("h2", {
  context: CardContext,
  base: { className: "font-bold" },
  variants: {
    variant: {
      default: { className: "text-gray-900" },
      outlined: { className: "text-gray-700" },
    },
  },
});

Multiple Variants

const ButtonContext = createStyledContext({
  size: ["xs", "sm", "md", "lg", "xl"],
  variant: ["solid", "outline", "ghost", "link"],
  colorScheme: ["blue", "red", "green", "gray"],
  disabled: ["boolean"],
  loading: ["boolean"],
});

Using useVariants

const TabsContext = createStyledContext({
  size: ["sm", "lg"],
});

function TabIndicator() {
  const variants = TabsContext.useVariants();

  if (!variants) return null;

  return (
    <div className={variants.size === "lg" ? "h-1" : "h-0.5"} />
  );
}

Type Inference

Types are automatically inferred from the arrays:
const ctx = createStyledContext({
  size: ["sm", "md", "lg"],        // "sm" | "md" | "lg"
  disabled: ["boolean"],           // boolean
  variant: ["a", "b", "c", "d"],   // "a" | "b" | "c" | "d"
});

// Inferred type:
// {
//   size: "sm" | "md" | "lg"
//   disabled: boolean
//   variant: "a" | "b" | "c" | "d"
// }
No as const needed.

Notes

Context values are provided when a parent component with context receives variant props or has defaultVariants defined. Children automatically inherit these values.
Only variants defined here will propagate to children. You can define additional local variants in styled() that stay on a single component. See Local Variants.
Always define arrays inline in createStyledContext(). Assigning them to variables first can break type inference.
// ✅ Correct
createStyledContext({ size: ["sm", "lg"] });

// ❌ Wrong - loses literal types
const sizes = ["sm", "lg"];
createStyledContext({ size: sizes });

See Also