Variants
The "variants" pattern allows you to conditionally apply one of several predefined styles based on a value. This is especially useful for theming or dynamic component behavior.
It is common to have different styles for different "variants" of a component. Some other styling solutions provide an explicit API for defining variants. In StyleX, you can define variants with a simple pattern instead.
Example: Button Variants
Here’s how you can create a button component with different visual styles based on variant
props:
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
base: {
appearance: 'none',
borderWidth: 0,
},
});
const colorVariants = stylex.create({
primary: {
backgroundColor: {
default: 'blue',
':hover': 'darkblue',
},
color: 'white',
},
secondary: {
backgroundColor: {
default: 'gray',
':hover': 'darkgray',
},
color: 'white',
},
});
const sizeVariants = stylex.create({
small: {
fontSize: '1rem',
paddingBlock: 4,
paddingInline: 8
},
medium: {
fontSize: '1.2rem',
paddingBlock: 8,
paddingInline: 16
},
});
type Props = {
color: keyof typeof colorVariants,
size: keyof typeof sizeVariants,
...
};
function Button({
color = 'primary',
size = 'small',
...props
}: Props) {
return (
<button
{...props}
{...stylex.props(
styles.base,
colorVariants[color],
sizeVariants[size],
props.style
)}
/
>);
}
// Usage
<Button color="primary" size="medium">Primary</Button>
<Button color="secondary">Secondary</Button>
Compound Variants
Sometimes variants are dependent on a combination of variants props.
In most cases, it's simpler to leverage StyleX’s deterministic style merging to simplify this behaviour.
Example: A disabled
prop
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
base: {...},
disabled: {
backgroundColor: 'grey',
color: 'rgb(204, 204, 204)',
cursor: 'not-allowed',
},
});
const colorVariants = stylex.create({
primary: {
backgroundColor: {
default: 'blue',
':hover': 'darkblue',
},
color: 'white',
},
secondary: {
backgroundColor: {
default: 'gray',
':hover': 'darkgray',
},
color: 'white',
},
});
const sizeVariants = stylex.create({...});
type Props = {
color?: keyof typeof colorVariants,
size?: keyof typeof sizeVariants,
disabled?: boolean,
...
};
function Button({
color = 'primary',
size = 'small',
disabled = false,
...props,
}: Props) {
return (
<button
{...props}
{...stylex.props(
styles.base,
colorVariants[color],
sizeVariants[size],
disabled && styles.disabled,
disabled && {
backgroundColor: 'grey',
color: 'rgb(204, 204, 204)',
cursor: 'not-allowed',
props.style
)}
/>
);
}
// Usage
<Button color="primary" size="medium">Primary</Button>
<Button color="secondary">Secondary</Button>
There may be other scenarios where you need to be more explicit about the styles that should applied under various condition. You can do this by declaring multiple style definitions for a particular variant.
Example: Two definitions for color
variant styles
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
base: {...},
});
const colorVariantsEnabled = stylex.create({
primary: {
backgroundColor: {
default: 'blue',
':hover': 'darkblue',
},
color: 'white',
},
secondary: {
backgroundColor: {
default: 'gray',
':hover': 'darkgray',
},
color: 'white',
},
});
const colorVariantsDisabled = stylex.create({
primary: {
backgroundColor: 'blue',
color: 'white',
},
secondary: {
backgroundColor: 'gray',
color: 'white',
},
});
const sizeVariants = stylex.create({...});
type Props = {
color?: keyof typeof colorVariants,
size?: keyof typeof sizeVariants,
disabled?: boolean,
...
};
function Button({
color = 'primary',
size = 'small',
disabled = false,
...props,
}: Props) {
const colorVariants = disabled
? colorVariantsDisabled
: colorVariantsEnabled;
return (
<button
{...props}
{...stylex.props(
styles.base,
colorVariants[color],
sizeVariants[size],
props.style
)}
/>
);
}
// Usage
<Button color="primary" size="medium">Primary</Button>
<Button color="secondary">Secondary</Button>