Is it possible to express this CSS snippet as a JSS sheet? And without resorting to globals? If possible, it doesn't seem obvious.
.switch { /* ... */ }
.switch__input { /* */ }
.switch__input:checked + .switch__toggle { /* */ }
.switch__input:checked + .switch__toggle:before { /* */ }
.switch__input:not(:checked) + .switch__toggle:before { /* */ }
Example DOM:
<label class="switch">
<input class="switch__input" type="checkbox">
<div class="switch__toggle"></div>
</label>
My intent would be making the switch__toggle styling dependent only on view-related concerns (i.e. whether the sibling input is :checked), thus avoiding introducing new classes to reflect component state.
The way I'm doing these kind of things is, to maintain some kind of UI STATE. So "checking/unchecking" a checkbox might set some part of the UI STATE to true/false and some other components or parts of the app might "listen" for changes of the UI STATE and update themselves accordingly.
@serapath It's what I'm doing. The checked state comes from the view (JS). My concern in my concrete example is that <div class="switch__toggle"></div> feeds on its sibling to style itself, and this relies on a sibling selector, which I don't know how to express in JSS.
Sure, one can add classes (say, with --checked ending) either to label.switch or div.switch__toggle to express checked state on .switch__toggle, but given an existing, complex stylesheet which is developed separately, it would be much simpler to just rely on sibling selectors.
yes, you can use pseudo selectors within named rules via jss-nested plugin
Its a nice example, it would be nice to have it in jss-examples repository
Thank you for the pointer. I went ahead and tried it, only having success in my use case with named: false:
window.styles = {
'.switch__input': {
'&:checked + .switch__toggle': {background: 'red'}
},
'.switch__toggle': {}
}
Stylesheet creation:
jss.use(jssNested).createStyleSheet(window.styles, {named: false}).attach()
yields:
.switch__input {}
.switch__input:checked + .switch__toggle {background: red;}
.switch__toggle {}
However:
jss.use(jssNested).createStyleSheet(window.styles, {named: true}).attach()
yields:
.jss-0-0 {}
.jss-0-0:checked + .switch__toggle {background: red;}
.jss-0-2 {}
I expected .switch__toggle to be renamed to .jss-0-2 in the second declaration.
Would this behavior be out of scope?
I see you misunderstand the concept of named styles, please rtfm)
to be more concrete: you don't write selectors in named styles .... you write names to access your rules and classes, selectors are generated
the point is to select a sibling you need to use a global selector, which is already a bad thing. If you use . switch__toggle its even worth because now you have jss and bem. The only option I see here is '&:checked + div' if the toggler is div otherwise the other element, but this will work correctly only if you don't have other element with the same tag name as sibling.
At the end the best option is wrapper component which handles state.
But what I described above can work too.
you don't write selectors in named styles
Yup. I just reused the selectors as they're valid object key names.
All clear wrt the rest. I discovered that what I'm after is possibly a name resolution step before the renaming takes place, to cover every occurrence of names in forms such and name1 + name2. If such thing existed it would make porting of existing stylesheets to named styles much easier, at risk of misusing object keys.
Yes, you want to write is '&:checked + toggler' where toggler is the name of other rule. This feature is not there yet and I am not sure how to implement it. Also I am not sure if there is much value in it.