Skip to content

Variants

Variants
All platforms
2.0.0

Variants were the most requested feature in version 1.0 and are now available to use! You can mix them with other Unistyles features like media queries and breakpoints.

Basic usage

Variants are objects that can be nested in any style object:

const stylesheet = createStyleSheet(theme => ({
container: {
backgroundColor: theme.colors.background,
variants: {
// here you can define your variants
}
},
text: {
color: theme.colors.text,
variants: {
// here you can define other variants!
}
}
}))

Variants contain groups of atomic variants.

To define a group, first you need to name it and then define variants within it:

const stylesheet = createStyleSheet(theme => ({
container: {
flex: 1,
variants: {
color: {},
size: {},
otherGroupName: {}
}
}
}

These groups will later be used to select your variants, so remember to name them appropriately.

With the given structure, you can now define your variants that can contain any number of styles. You can also use breakpoints, media queries or styles like transform:

const stylesheet = createStyleSheet(theme => ({
container: {
flex: 1,
variants: {
color: {
primary: {
backgroundColor: theme.colors.primary
},
secondary: {
backgroundColor: theme.colors.secondary
}
},
size: {
small: {
width: 100,
height: 100
},
medium: {
width: 200,
height: 200
},
large: {
width: 300,
height: 300
}
},
otherGroupName: {
// other variants
}
}
}
}

Selecting variants

With your named groups, you can now select any variant from your stylesheet using the useStyles hook:

import { useStyles } from 'react-native-unistyles'
const Component = () => {
const { styles } = useStyles(stylesheet, {
color: 'primary',
size: 'small'
})
return (
<View style={styles.container} />
)
}
const stylesheet = ...

TypeScript will provide perfect autocompletion for your variants, ensuring accuracy!

Selecting variants with boolean values

All platforms
2.1.0

You can also use boolean values to select variants:

import { useStyles } from 'react-native-unistyles'
const Component = ({ isPrimary, isDisabled }) => {
const { styles } = useStyles(stylesheet, {
color: !isDisabled,
borderColor: isPrimary
// you can also use strings
// color: "true" | "false"
})
return (
<View style={styles.container} />
)
}
const stylesheet = createStyleSheet(theme => ({
container: {
// otter styles
variants: {
color: {
true: {
backgroundColor: theme.colors.primary
},
false: {
backgroundColor: theme.colors.disabled
},
// you can still specify a default variant
default: {
backgroundColor: theme.colors.barbie
}
// or other variants
special: {
backgroundColor: theme.colors.special
}
},
borderColor: {
true: {
borderColor: theme.colors.primary
}
// you can also skip "false" here
}
}
}
})

If you specify a boolean variants like “true”, there is no requirement to specify a “false” variant (and vice versa). You can mix boolean variants with other variants as well.

Default variant

You can define a default variant that will be used when you don’t pass any variant to the useStyles hook:

const stylesheet = createStyleSheet(theme => ({
container: {
flex: 1,
variants: {
color: {
primary: {
backgroundColor: theme.colors.primary
},
secondary: {
backgroundColor: theme.colors.secondary
},
default: {
backgroundColor: theme.colors.barbie
}
}
}
}
}

Options to select the variant

If you pass undefined or empty object Unsityles will try to find the default variant in your stylesheet:

const { styles } = useStyles(stylesheet, undefined) // will use default variant (if any)
const { styles } = useStyles(stylesheet, {}) // will use default variant (if any)

Passing an object with named keys and undefined will work the same way dafaulting to the default option:

const { styles } = useStyles(stylesheet, {
color: undefined // will use default variant (if any)
})

Lastly, you can pass the correct variant name for a variant group:

const { styles } = useStyles(stylesheet, {
color: 'secondary' // will use secondary variant
})

Pass variants as component props

Variants were designed to be used as component props:

import React from 'react'
import { useStyles } from 'react-native-unistyles'
enum Color {
primary = 'primary',
secondary = 'secondary'
}
enum Size {
small = 'small',
medium = 'medium',
large = 'large'
}
type ComponentProps = {
color: Color
size: Size
}
const Component: React.FunctionComponent = ({ color, size }) => {
const { styles } = useStyles(stylesheet, {
color,
size
})
return (
<View style={styles.container} />
)
}

Defining the same variant across multiple styles

It’s possible to define the same variant group across multiple styles:

const stylesheet = createStyleSheet(theme => ({
container: {
flex: 1,
variants: {
size: {
small: {
width: 100,
height: 100
},
medium: {
width: 200,
height: 200
},
large: {
width: 300,
height: 300
}
}
}
},
text: {
fontWeight: 'bold',
variants: {
size: {
small: {
fontSize: 12
},
medium: {
fontSize: 16
},
large: {
fontSize: 20
}
}
}
}
}
const stylesheet = createStyleSheet(theme => ({
container: {
flex: 1,
variants: {
size: {
small: {
width: 100,
height: 100
},
medium: {
width: 200,
height: 200
},
large: {
width: 300,
height: 300
}
}
}
},
text: {
fontWeight: 'bold',
variants: {
size: {
small: {
fontSize: 12
},
// missing medium and large variants!
}
}
}
}

In this case, the generated TypeScript type will be:

size: ('small' | 'medium' | 'large') | ('small')

If you don’t need all variants and want the correct type, please add empty variants:

const stylesheet = createStyleSheet(theme => ({
container: {
flex: 1,
variants: {
size: {
small: {
width: 100,
height: 100
},
medium: {
width: 200,
height: 200
},
large: {
width: 300,
height: 300
}
}
}
},
text: {
fontWeight: 'bold',
variants: {
size: {
small: {
fontSize: 12
},
medium: {},
large: {}
}
}
}
}

The generated TypeScript type will then be:

size: ('small' | 'medium' | 'large')