Extend and build custom and optimizable components.

Create a new component by extending an existing one:

import { GetProps, Stack, styled } from '@tamagui/core'
export const Circle = styled(Stack, {
name: 'Circle', // useful for debugging, and Component themes
borderRadius: 100_000_000,
// helper to get props for any TamaguiComponent
export type CircleProps = GetProps<typeof Circle>


<Circle x={10} y={10} backgroundColor="red" />

Note, tamagui and @tamagui/core both export many of the same helpers, like styled. If you are using tamagui, you don't need to ever add @tamagui/core to your package.json or import it and can instead import directly from tamagui itself and don't need the following.

If using just core but passing in React Native components, be sure to run setupReactNative once first, typically near your entry file:

import { setupReactNative, styled } from '@tamagui/core'
import { Image } from 'react-native'
// this allows tamagui to optimize for react-native components
// it's not required. `tamagui` automatically sets this up, but core doesn't
setupReactNative({ Image })
const MyImage = styled(Image, {
backgroundColor: 'red'

This requirement allows core to be light and not depend on react-native for web-only use cases.

The tamagui package applies this polyfill automatically as it uses React Native.

You can pass any prop that is supported by the component you are extending, even variants of the parent component. Tamagui will figure out the style props up-front, turn them into classNames, and then pass the non-style props down to the component as defaultProps.


Let's add some variants:

import { Stack, styled } from '@tamagui/core'
export const Circle = styled(Stack, {
borderRadius: 100_000_000,
variants: {
pin: {
top: {
position: 'absolute',
top: 0,
centered: {
true: {
alignItems: 'center',
justifyContent: 'center',
size: {
'...size': (size, { tokens }) => {
return {
width: tokens.size[size] ?? size,
height: tokens.size[size] ?? size,
} as const,

Please use as const for the variants definition until Typescript gains the ability to infer generics as const .

We can use these like so:

<Circle pin="top" centered size="$lg" />

To learn more about to use them and all the special types, see the docs on variants.


The styled() function supports Tamagui views, React Native views, and any other React component that accepts a style prop. If you wrap an external component that Tamagui doesn't recognize, Tamagui will assume it only supports the style prop and not optimize it.

If it does accept className, you can opt-in to className, CSS media queries, and compile-time optimization by adding acceptsClassName:

import { styled } from '@tamagui/core'
import { SomeCustomComponent } from 'some-library'
export const TamaguiCustomComponent = styled(SomeCustomComponent, {
acceptsClassName: true,