composing recipes, sprinkles and styles #939
-
I'm relatively new to vanilla extract and attempting to wrap my head around how I can create multiple lower level components (eg; Block, Text, etc) that can be used throughout a design system. I've used styled-systems previously and wanting to achieve a similar result where you can have multiple helper properties on components (padding, margins, etc) and propagate them up into higher level components (Alert, Button, ect) which can have the values passed down into the base component via props. The way I'm currently doing this is via sprinkles and I've got a base sprinkle that contains many useful css properties that may require to be overridden (margins, paddings, etc) via props across components. export const responsive = defineProperties({
conditions: {
xs: {
'@media': 'screen and (max-width: 480px)',
},
...
},
defaultCondition: 'xs',
properties: {
// space properties
paddingTop: vars.spaces,
paddingBottom: vars.spaces,
paddingLeft: vars.spaces,
paddingRight: vars.spaces,
...
})
export const sprinkles = createSprinkles(responsive) I now have the lowest level component which is a Block, other components in the design system are all built upon this block so we expose all those common sprinkle properties we can use. export type BlockProps = React.PropsWithChildren<ThemeSprinkles> & {
as?: React.ElementType
className?: string
}
const Block: React.FC<BlockProps> = ({ children, as, className, ...rest }) => {
const Component = as ?? 'div'
return <Component className={composeStyles([sprinkles({ ...rest }), className ?? ''])}>{children}</Component>
} I now have a Text component that is built on top of our Block, this uses textSprinkle that contains text helper properties as well as recipe to change the color variant. I could then use this Text component create create a Heading component based upon this since it already has a lot of the styles I'd need, the only differing factor is the heading levels and differing element type. export type TextProps = BlockProps & TextSprinkles & TextVariants
const Text: React.FC<TextProps> = ({
children,
fontStyle,
textDecoration,
textTransform,
color,
className,
...rest
}) => (
<Block
as='span'
className={composeStyles([
textSprinkle({ fontStyle, textDecoration, textTransform }),
styles.text({ color }),
className ?? '',
])}
{...rest}
>
{children}
</Block>
) My question is what I'm doing some sort of anti-pattern and are there other ways to achieve the same result? Or should the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
I never used
That means you now already have a lot of class names in your HTML (that is rendered in the browser), when using multiple sprinkles props and styles, right? If yes, then you can just replace |
Beta Was this translation helpful? Give feedback.
I never used
composeStyles
but it looks like its behavior depends on where it is used:*.css.ts
file it will merge all styles, giving you one class nameThat means you now already have a lot of class names in your HTML (that is rendered in the browser), when using multiple sprinkles props and styles, right?
If yes, then you can just replace
composeStyles
withstyle
whenever you are in a*.css.ts
file, and use something like clsx for all other files. Your approach is actually how SEEK (the company behind vanilla-extract, I think) uses vanilla-extract for their own design system .