Types for Variables
The unstable_moduleResolution
option needs to be enabled in the StyleX Babel configuration to enable theming APIs.
Declaring types for variables is an advanced use-case. It is not necessary for the majority of use-cases.
By default, variables values are strings. This is the correct choice for the
majority of use-cases. However, modern browsers support defining types for CSS
variables. A variable can be declared with an @property
rule that specifies
the <syntax>
type of the variable.
Doing so can enable some interesting use-cases that would otherwise not be possible with CSS. Some examples include:
- Animating gradients by animating an angle or color variables
- Capturing the value of
1em
on an element and using it on a descendant - Converting a floating point number to an integer
API
To assign types to variables in StyleX, you can use the various functions, such
as stylex.types.color
or stylex.types.length
.
Reference the API documentation for a full list of available functions.
Usage
To assign types to variables, the value of the variable can be wrapped in with the appropriate type function.
For example, consider the following set of variables:
import * as stylex from '@stylexjs/stylex';
export const tokens = stylex.defineVars({
primaryText: 'black',
secondaryText: '#333',
borderRadius: '4px',
angle: '0deg',
int: '2',
});
Currently, all the values can be arbitrary strings. To assign types to the variables, they can be wrapped with the appropriate type function:
import * as stylex from '@stylexjs/stylex';
export const tokens = stylex.defineVars({
primaryText: stylex.types.color('black'),
secondaryText: stylex.types.color('#333'),
borderRadius: stylex.types.length('4px'),
angle: stylex.types.angle('0deg'),
int: stylex.types.integer(2),
});
Conditional Values
The usage remains unchanged even when at-rules are used within the values. The following is completely valid:
import * as stylex from '@stylexjs/stylex';
export const colors = stylex.defineVars({
primaryText: stylex.types.color({default: 'black', [DARK]: 'white'}),
});
Type-safety in your source code
The primary utility of stylex.types.*
functions is to enable functionality
by declaring types for variables in the generated CSS. However, the StyleX API
also enhances the type-safety within your own codebase.
When a variable is declared with a certain type within stylex.defineVars
, the
static types will enforce that the same type function is used when the variable
is themed within a stylex.createTheme
call.
import * as stylex from '@stylexjs/stylex';
import {tokens} from './tokens.stylex.js';
export const highContrast = stylex.defineVars({
primaryText: stylex.types.color('black'),
secondaryText: stylex.types.color('#222'),
borderRadius: stylex.types.length('8px'),
angle: stylex.types.angle('0deg'),
int: stylex.types.integer(4),
});
Since the types for the variables are already declared within the stylex.defineVars
call, the usage type functions within stylex.createTheme
is functionally a no-op, but
is required by the static types for type-safety.
Example use-cases
Simulating round()
Modern browsers are starting to support
the round()
function in CSS.
However, the feature can be simulated with a variable with an integer
type:
const styles = stylex.create({
gradient: {
// Math.floor
[tokens.int]: `calc(16 / 9)`
// Math.round
[tokens.int]: `calc((16 / 9) + 0.5)`
},
})
Since tokens.int
is declared with an integer
type, any fractional
value is discarded and the value is cast into an integer type whenever
a value is assigned.
Animating gradients
It is usually not possible to animate gradients. However, by using a typed
angle
variable, the gradient can be animated by animating the angle used
within it.
Instead of animating a normal CSS property, the angle
variable can be
animated with stylex.keyframes
:
import * as stylex from '@stylexjs/stylex';
import {tokens} from './tokens.stylex';
const rotate = stylex.keyframes({
from: { [tokens.angle]: '0deg' },
to: { [tokens.angle]: '360deg' },
});
const styles = stylex.create({
gradient: {
backgroundImage: `conic-gradient(from ${tokens.angle}, ...colors)`,
animationName: rotate,
animationDuration: '10s',
animationTimingFunction: 'linear',
animationIterationCount: 'infinite',
},
})
This can be used to create rotating conic gradients: