Allow children to be styled in styleVariants
and recipe
#737
Replies: 3 comments 4 replies
-
Hello, I'm here because I was experiencing a similar issue as #464. I agree with @AndrewLeedham, the mentioned solution is not ideal. It affects readability and it doesn't seem very intuitive...
For example, let's say I have a recipe for my parent like the following: export const parent = recipe({
variants: {
alignment: {
horizontal: {
display: 'flex',
flexFlow: 'row wrap',
},
vertical: {
display: 'block'
},
},
},
}); Now let's say that depending on the parent alignment, I'd like to style its children with different properties. These children can also have some variants. So I create another recipe to style the children (or I could use export const child = recipe({
variants: {
border: {
false: {
selectors: {
[`${parent({ alignment: 'vertical' })} &:not(:last-child)`]: {
marginBottom: '1rem',
},
},
},
true: {
selectors: {
[`${parent({ alignment: 'horizontal' })} &:not(:first-child)`]: {
marginLeft: -1,
},
},
},
},
},
}); The generated class name for However, if later I add a Before adding the base, the So to avoid breaking things later, I have to apply the solution mentioned in #464 (by adding export const child = recipe({
variants: {
border: {
false: {
selectors: {
[`${parent({ alignment: 'vertical' }).split(' ')[1]} &:not(:last-child)`]: {
marginBottom: '1rem',
},
},
},
true: {
selectors: {
[`${parent({ alignment: 'horizontal' }).split(' ')[1]} &:not(:first-child)`]: {
marginLeft: -1,
},
},
},
},
},
}); When the recipe is used inside a selector, I expect it to return only the matching class and not the base class. If it is not possible, maybe a note in the documentation ( https://vanilla-extract.style/documentation/styling/#complex-selectors or in recipe package ) with the recommended approach could be helpful. |
Beta Was this translation helpful? Give feedback.
-
Yes, I think for layout components specifically this is really useful. For example I have the following use case where targeting children is the whole point of the component:
You can see how in this instance the children needing to be aware of their parent and apply the style themselves is not really tenable (which is the current solution that vanilla-extract proposes). If I implemented it the vanilla-extract way I'd have to pollute the styles of every possible child, or be forced to create some component to wrap every child in order to use them in the parent layout. These aren't good solutions when css already gives us a better one. In my current implementation I iterate over all the child nodes (in Box component's render method) in order to apply margin to them in accordance with my
So I'll likely refactor a bit to add static css classes outside of vanilla-extract, which is not ideal for keeping my styles colocated, but will be the most performant solution right now in lieu of vanilla-extract supporting child selectors. |
Beta Was this translation helpful? Give feedback.
-
I just ran into this myself. I'm not sure whether it's a good solution yet, but I created a import { GlobalStyleRule, globalStyle } from '@vanilla-extract/css'
function recipeGlobalStyle(
recipeSelector: string,
selector: string,
rule: GlobalStyleRule,
): void {
globalStyle(`${recipeSelector.split(' ')[1]} ${selector}`, rule)
} import { recipe } from '@vanilla-extract/recipes'
const stack = recipe({
variants: {
size: {
large: {},
},
},
})
recipeGlobalStyle(stack({ size: 'large' }), '> * + *', {
marginBlockStart: '3em',
}) Although I can see why this might be discouraged, it's a powerful CSS capability, and I think it's a shame it's disallowed altogether. |
Beta Was this translation helpful? Give feedback.
-
I understand and agree with why
style()
cannot style children, as it creates separation between blocks of styles affecting different nodes.However, I believe there is a case to allow it for variants. Variants are often directly linked to props of a component, and therefore affect children of said component. For example say you have a button component with a size and colour variant, you would likely want these variants to affect the background and border at the top but also the text colour and icon colour etc. of children.
You can use the recipe along with
globalStyle
to style children. This does not seem like a first-class usage though as you have to split the resulting string as seen here: #464. Also, adding a base class offsets the variant you want and there is not guarantee of the class output order.Therefore, it seems to me that allowing children to be styled via
selectors
would make sense instyleVariants
and subsequentlyrecipe
?Beta Was this translation helpful? Give feedback.
All reactions