Consider the following style declaration:
const styles = {
someDiv: {
'&:hover, &:focus, &:active': {
'& $someNestedDiv': {
color: 'red',
}
}
}
}
I thought that the styles rendered would look like this:
.someDiv:hover .someNestedDiv, .someDiv:focus .someNestedDiv, .someDiv:active .someNestedDiv {
color: red
}
but actually it looks like this:
.someDiv:hover, .someDiv:focus, .someDiv:active .someNestedDiv {
color: red
}
What do you think about switching the behavior to what I expected it to be? Or is it bad form to be specifyiny rules with commas (and if so is that documented somewhere?)
What you did won't work at all ... the object inside of a nested rule is not a new rule, it is props.
const styles = {
someDiv: {
'&:hover, &:focus, &:active': {
color: 'red',
}
}
}
Ah whoops @kof! I edited my original question as I forgot the key & $ prefixing the someNestedDev which makes it a rule not props, right?
this is still not correct, I assume $someNestedDiv rule need to be defined ....
you mean something like this
{
someDiv: {
'&:hover, &:focus, &:active': {
'& $someNestedDiv': {
color: 'red',
}
}
},
someNestedDiv: {
float: 'left'
}
}
.someNestedDiv-3787690649 {
float: left;
}
.someDiv-4073602825:hover, .someDiv-4073602825:focus, .someDiv-4073602825:active .someNestedDiv-3787690649 {
color: red;
}
should result in this instead
.someNestedDiv-3787690649 {
float: left;
}
.someDiv-4073602825:hover .someNestedDiv-3787690649, .someDiv-4073602825:focus .someNestedDiv-3787690649, .someDiv-4073602825:active .someNestedDiv-3787690649 {
color: red;
}
yes! correctamundo! What do you think about having this different functionality? And you're fully functional example brings up another learning speed bump I encountered on the way. That someOtherDiv has to have a top level rule object for it to be referenced as $someOtherDiv with jss-nested. There have bene times where a className only needs to be referenced within another rule and I have empty rule declarations just to get jss to acknowledge it. So tangentially to my original question: What do you think about allowing rules to reference classNames that have no top level rule declaration?
Can you tell me what problem you are solving?
problem looking to solve for the first question: improve the ease of reading/writing JSS by adding some sugar. This basically make writing JSS more intuitive for people familiar with SASS as well as having less repetition in rule declaration. Right now to get the functionality I'd like I'd have to do the following:
const hoverFocusActiveProps = { color: 'red' }
{
someDiv: {
'&:hover $someNestedDiv' {
...hoverFocusActiveProps,
},
'&:focus $someNestedDiv' {
...hoverFocusActiveProps,
},
'&:active $someNestedDiv' {
...hoverFocusActiveProps,
},
},
as opposed to what I thought would work:
'&:hover, &:focus, &:active': {
'& $someNestedDiv': {
color: 'red',
}
}
problem I'm seeking to solve with my second tangential issue: Not realizing that you'd need a top level empty rule to reference a className within a nested selector. Again this is basically removing a speed bump to new JSS learners (like me). I don't see a reason from a JSS API perspective that consumers need to define an empty rule with a className so they could reference a className in a nested selector.
Can you give ma a full example of what you are trying to achieve? Not quite following.
Besides of that, you are talking about a 3rd level nesting, normally this doesn't lead to a better readability, so I want to see if I can write down what you trying to achieve in a better way without deep nesting.
What I'm trying to do is create a highlighted state for a row element. To do so I'm trying to set several divs within the row to a certain color, maybe text-decoration: underline when the row is hovered over or active or focused. To relate this real case to the toy scenario the row has a someDiv className and one of the divs inside has the someOtherDiv className. Seems like a reasonable thing to support, right?
Well, if you give me a toy scenario, I give you a toy answer. Give me a full picture, I want to see whether it needs fixing or not and how.
{
inner: {
color: 'grey'
},
row: {
'&:hover $inner': {
color: 'red'
},
'&:focus $inner': {
color: 'blue'
}
}
}
Based on reactions I see there is an entire team behind this issue, which is nice, means you are using or going to use jss in a bigger project and yet I change stuff only if there is a real prove behind, that it needs to be changed. There is a reason why jss is flat and jss-nested isn't a SASS clone. So lets discuss and make clear statements instead of putting thumbs up and down lol.
Also your code snippet here can be expressed in this way:
{
row: {
'&:hover $inner, &:focus $inner, &:active $inner': {
color: 'red'
}
}
}
I realize there is a bit more repetition here, but it is not all that dramatic, deep nesting leads to way worse readability.
Me and @nathanmarks discussed that issue and clear is that we have to
The current behaviour is confusing because it allows the nesting but produces output which does not match the user's expectations of what the provided syntax should result in.
Since the deep nesting with multiple selectors doesn't act as one would expect, the current functionality should be clearly documented and in a dev environment have it throw an error so the user knows that their syntax is considered incorrect.
Whether or not it should properly support N levels of nesting is an interesting question. There are other syntax options for achieving the same goals in this issue, and outside of the pseudo classes use case nesting like that isn't something people should do anyways. Keeping the feature simpler also has its pluses when generating styles at runtime vs having a build step.
On the flip side, I'm sure there is a certain expectation that people have who are coming from scss, less, postcss, etc. where there is more freedom in that respect.
What I think would be great is if the plugin API was able to properly support a different implementation of these features.
It also looks like enabling nesting to work in this manner is a fairly trivial task and can be done on the plugin side already.
We could add an option to enable this in the plugin, or @alurim if you take a look at jss-nested you'll see (line 45+) that it would be super easy to create your own plugin that implements nesting the way you want it. It isn't supporting the N levels properly in the current iteration as it does not try to split multi selectors when creating the nested rules.
Released jss-nested with those 2 points addressed. Closing this for now, if something comes up again feel free to create a new issue with new input.
Most helpful comment
Well, if you give me a toy scenario, I give you a toy answer. Give me a full picture, I want to see whether it needs fixing or not and how.