The Problem
Imagine a Button with an Icon inside. You want the icon size to match the button size. Without context, you’d do this:The Solution
With context, the icon knows its parent’s size automatically:Creating a Context
UsecreateStyledContext() to define which variants should be shared.
Connecting Components
Pass the context to each component that should participate.How It Works
When you pass variant props to the parent:- The parent renders with those variants
- It wraps its children in a context provider
- Children with the same context read the values
- Children apply matching variants automatically
Default Variants Propagation
When the parent component hasdefaultVariants, children automatically inherit them—even without explicit props.
Overriding Context
Children can override the context values when needed.Boolean Variants
For true/false variants, use the special["boolean"] marker.
true. You don’t need false: {}. When using the component, pass actual booleans:
⚠️ Use
isDisabled instead of disabled to avoid shadowing the native disabled prop on elements like button or Pressable.Variant Priority
When multiple sources provide variant values, this is the priority order (highest wins):- 🥇 Props passed directly to the component
- 🥈 Context values from parent
- 🥉 defaultVariants in config
Local Variants
Not all variants need to propagate to children. Some behaviors are specific to a single component—like haptic feedback on a Button root, but not on its Text or Icon slots.The Problem
Imagine you want your Button to have haptic feedback options, but this only makes sense for the Pressable root:The Solution
Define variants outside ofcreateStyledContext() to keep them local:
How It Works
- Context variants (
variant) - Defined increateStyledContext(), propagate to all children with the same context - Local variants (
haptics) - Defined only invariants, stay on that component
When to Use Local Variants
✅ Use local variants for:- Platform-specific behaviors (haptics, animations)
- Root-only interactions (press effects, gestures)
- Variants that don’t make semantic sense on children
- Visual consistency (size, color, variant)
- Semantic states (disabled, loading)
- Anything children should know about
Function Composition
Local variants work great with function props. When you defineonPress in a variant, it composes with any onPress passed to the component:
Shared Config
When multiple components share the same context and variants, you end up duplicating the config:styledConfig() to create a single config validated against both components:
styledConfig() is an identity function — it returns the config unchanged with zero runtime overhead. It exists purely so TypeScript can validate the config against both components and give you full autocomplete.
styledConfig() uses the same type inference as styled(). No generics needed — just pass the components array and the config.styledConfig() API Reference
Signature, parameters, and type safety details
Nested Contexts
If you nest components with the same context, the nearest parent wins.Without Context
Not every component needs context. For standalone components, just omit it:Next: Slots
Build compound components with dot notation