Recipes
Create multi-variant styles with a type-safe runtime API, heavily inspired by Stitches.
As with the rest of vanilla-extract, all styles are generated at build time.
💡 Recipes is an optional package built on top of vanilla-extract using its function serialization API. It doesn’t have privileged access to vanilla-extract internals so you’re also free to build alternative implementations.
Setup
npm install @vanilla-extract/recipes
recipe
Creates a multi-variant style function that can be used at runtime or statically in .css.ts
files.
Accepts an optional set of base
styles, variants
, compoundVariants
and defaultVariants
.
import { recipe } from '@vanilla-extract/recipes';
export const button = recipe({
base: {
borderRadius: 6
},
variants: {
color: {
neutral: { background: 'whitesmoke' },
brand: { background: 'blueviolet' },
accent: { background: 'slateblue' }
},
size: {
small: { padding: 12 },
medium: { padding: 16 },
large: { padding: 24 }
},
rounded: {
true: { borderRadius: 999 }
}
},
// Applied when multiple variants are set at once
compoundVariants: [
{
variants: {
color: 'neutral',
size: 'large'
},
style: {
background: 'ghostwhite'
}
}
],
defaultVariants: {
color: 'accent',
size: 'medium'
}
});
.button_button__708odg0 {
border-radius: 6px;
}
.button_button_color_neutral__708odg1 {
background: whitesmoke;
}
.button_button_color_brand__708odg2 {
background: blueviolet;
}
.button_button_color_accent__708odg3 {
background: slateblue;
}
.button_button_size_small__708odg4 {
padding: 12px;
}
.button_button_size_medium__708odg5 {
padding: 16px;
}
.button_button_size_large__708odg6 {
padding: 24px;
}
.button_button_rounded_true__708odg7 {
border-radius: 999px;
}
.button_button_compound_0__708odg8 {
background: ghostwhite;
}
With this recipe configured, you can now use it in your templates.
app.tsimport { button } from './button.css.ts'; document.write(` <button class="${button({ color: 'accent', size: 'large', rounded: true })}"> Hello world </button> `);
Your recipe configuration can also make use of existing variables, classes and styles.
For example, you can pass in the result of your sprinkles
function directly.
button.css.tsimport { recipe } from '@vanilla-extract/recipes'; import { reset } from './reset.css.ts'; import { sprinkles } from './sprinkles.css.ts'; export const button = recipe({ base: [reset, sprinkles({ borderRadius: 'round' })], variants: { color: { neutral: sprinkles({ background: 'neutral' }), brand: sprinkles({ background: 'brand' }), accent: sprinkles({ background: 'accent' }) }, size: { small: sprinkles({ padding: 'small' }), medium: sprinkles({ padding: 'medium' }), large: sprinkles({ padding: 'large' }) } }, defaultVariants: { color: 'accent', size: 'medium' } });
The recipes function also exposes an array property variants
that includes all the variants from your recipe.
button.variants(); // -> ['color', 'size']
Recipe class name selection
Recipes function exposes internal class names in classNames
property.
The property has two predefined props: base
and variants
. The base
prop includes base class name. It is always defined even if you do not have any base styles. The variants
prop includes class names for each defined variant.
app.css.tsconsole.log(button.classNames.base); // -> app_button__129pj250 console.log(button.classNames.variants.color.neutral); // -> app_button_color_neutral__129pj251 console.log(button.classNames.variants.size.small); // -> app_button_size_small__129pj254
RecipeVariants
A utility to make use of the recipe’s type interface. This can be useful when typing functions or component props that need to accept recipe values as part of their interface.
button.css.tsimport { recipe, RecipeVariants } from '@vanilla-extract/recipes'; export const button = recipe({ variants: { color: { neutral: { background: 'whitesmoke' }, brand: { background: 'blueviolet' }, accent: { background: 'slateblue' } }, size: { small: { padding: 12 }, medium: { padding: 16 }, large: { padding: 24 } } } }); // Get the type export type ButtonVariants = RecipeVariants<typeof button>; // the above will result in a type equivalent to: export type ButtonVariants = { color?: 'neutral' | 'brand' | 'accent'; size?: 'small' | 'medium' | 'large'; };