Closed kof closed 8 years ago
Interesting. Give me few days and will I'll see how it goes.
I think the negative feedback I have got so far to jss was from people who are not ready to write CSS in JSON. They want CSS syntax. This is also the reason for popularity of css-modules. At the same time the amount of advantages of runtime-rendered CSS is so huge, I don't even want to go ever back to the server rendered CSS, exception are some optimizations for e.g. bootstrapping application.
I have tried to put it on the list here https://github.com/jsstyles/jss/blob/master/docs/benefits.md and also did this presentation recently https://slides.com/kof/javascript-style-sheets/
With JSS we will have many already written plugins. So I really want CSSX + JSS solution :D.
I also will follow this one, because I'm working on https://github.com/postjson/postjson idea, which also could be useful and interesting in some way. :)
@tunnckoCore postjson is very interesting, sounds like I could use postjson in jss as a lower level lib.
@kof thanks! Yea, maybe. I'm still thinking what would be the best approach and API for the plugins - there are two ways for the moment haha. I'm open for ideas (feel free to open issues there) and would be happy to hear what you need.
@kof @ai @tunnckoCore Yesterday I did an update of CSSX allowing the generation of plain JavaScript literal. I.e. it's not CSSX lib specific. Here is an example:
var styles = function () {
return <style>
.container {
width: 100%;
}
@media (max-width: 600px) {
.container {
width: 50%;
}
}
</style>;
}
It is transpiled to:
var styles = function () {
return (function () {
var _4 = {};
_4['width'] = '50%';
var _3 = {};
_3['width'] = '100%';
var _2 = [];
_2.push(['.container', _3]);
var _5 = {},
_6 = [];
_5['@media (max-width: 600px)'] = _6;
_6.push(['.container', _4]);
_2.push(_5);
return _2;
}.apply(this));
};
Which is the following JSON:
[
[
".container",
{
"width": "100%"
}
],
{
"@media (max-width: 600px)": [
[
".container",
{
"width": "50%"
}
]
]
}
So it is definitely possible writing a .toJSON
method. @kof can you please point me to a place where I could see the jss dsl specification (or at least an example containing all the different types of nodes).
I saw so much similar code in the cssx client to what jss and it's plugins do, it really makes sense to use jss for client side rendering and combine our efforts in making it better.
I like JSS's Object-literal syntax better. Also, why not just compile to the literal form rather than to the pieces and putting them together? Suppose for example we have this:
var stylesheet = <style>
.container {
width: 100%;
}
@media (max-width: 600px) {
.container {
width: 50%;
}
}
</style>
stylesheet.attach() // <-- better leaving it up to the user to decide when to attach/detach
then it'd compile to this:
let stylesheet = jss.createStyleSheet({
'.container': {
width: '100%'
},
'@media (max-width: 600px)': {
'.container': {
width: '50%'
}
}
})
stylesheet.attach() // <-- better leaving it up to the user to decide when to attach/detach
Maybe you guys can agree on a common object-literal format, then end users can choose which runtime they prefer, as either would be compatible with the compiled output. In that case, then we'd want to compile to this:
let styles = {
'.container': {
width: '100%'
},
'@media (max-width: 600px)': {
'.container': {
width: '50%'
}
}
}
and we'd let the user choose which runtime to use:
let stylesheet = cssx('my-styles', styles)
// or
let stylesheet = jss.createStyleSheet(styles)
Example where we take advantage of JSS' collision-free class names:
var style = <style>
container {
width: 100%;
}
</style>
jss.createStyleSheet(style)
would compile to
var stylesheet = {
container: {
width: '100%'
}
}
jss.createStyleSheet(style)
which generates at runtime:
<style>
.container-jss-0 {
width: 100%;
}
</style>
@trusktr That's exactly what I'm working on right now. I'm changing the transpiler of CSSX to output non-CSSX specific code.
@kof @ai @tunnckoCore @trusktr
Finally I managed to release a jss compatible version - 5.0.0
. I bumped the major version twice because I had to make changes everywhere :)
var styles = <style>
button {
font-size: 12;
&:hover {
background: blue;
}
}
ctaButton {
extend: button;
&:hover {
background: red;
}
}
@media (min-width: 1024px) {
button {
minWidth: 200;
}
}
</style>;
is transpiled to:
var styles = (function () {
var _1 = {},
_2 = {},
_3 = {},
_4 = {},
_5 = {},
_6 = {},
_7 = {};
_2['background'] = 'blue';
_3['&:hover'] = _2;
_3['font-size'] = '12';
_4['background'] = 'red';
_5['&:hover'] = _4;
_5['extend'] = 'button';
_6['minWidth'] = '200';
_7['button'] = _6;
_1['button'] = _3;
_1['ctaButton'] = _5;
_1['@media (min-width: 1024px)'] = _7;
return _1;
}.apply(this));
which if we execute outputs:
{
"button": {
"&:hover": {
"background": "blue"
},
"font-size": "12"
},
"ctaButton": {
"&:hover": {
"background": "red"
},
"extend": "button"
},
"@media (min-width: 1024px)": {
"button": {
"minWidth": "200"
}
}
}
There is a working example that uses jss here (the source code is here).
I'll be happy if someone tests a more complex cases so we see if it works with production-ish ready code.
Nice, will try it out soon. Do you think it makes for cssx to focus on cssx as a language and continue providing all transpiling tools, but remove the cssx client and fully rely on jss?
Also I think it would be nice to add cssx as an option on the jss repl http://jsstyles.github.io/repl/ Thinking of a select box which allows to switch between them.
Regarding json output from cssx: it would be nice to get number values from those which have no unit. This allows jss-default-unit plugin to set default unit automatically.
Regarding json output from cssx: it would be nice to get number values from those which have no unit. This allows jss-default-unit plugin to set default unit automatically.
I just filed an issue about that https://github.com/krasimir/cssx/issues/6
Do you think it makes for cssx to focus on cssx as a language and continue providing all transpiling tools, but remove the cssx client and fully rely on jss?
I already started thinking in this direction. I removed 3 features of the CSSX client-side library and it is really simple now. I'm not planning to extend it soon. Just updated the docs so cssx lib is more like an alternative of jss.
If you need something for cssx jss doesn't allow to do, just create an issue on jss repository.
Hey! This going very interesting! Soon is my turn to review the jss
core more deeply (@kof help will be appreciated), meaning what it does actually, what are the processes/steps. And you can help with PostJSON - it can be third direction.
Btw I'm going deeper and deeper, today pushed https://github.com/limonjs/limon (pluggable lexer) and going to push "pluggable" parser. When finish them both, I'll start playing with few things - json lexer, parser and stringifier; semver lexer, parser and stringifier; and porting PostCSS's tokenizer (because it is awesome).
@krasimir, междудругото парсъра мисля да го кръстя лиман хахаха - лимон и лиман. За жалост лагуна е заето, lemon също, та затова лимон и лиман - само това, че разликата е само в една буква ме притеснява и дразни. Чудя се. Anyway.
@tunnckoCore interesting things yes, ping me on gitter if you have any questions, I still didn't have time to think how we could extract the part of jss which is about the ast and it's manipulations by plugins into something generic like postjson. But I think it's definitely possible, it's just a load of work.
Yea, done. :)
@krasimir Idea: maybe let the user choose the runtime:
// User chooses CSSX:
let style = <style runtime="cssx">
.foo {
height: 100%;
}
</style>
// or, maybe instead of <style>, template tag syntax:
let style = cssx`
.foo {
height: 100%;
}
// User chooses CSSX:
let style = <style runtime="jss" named="false">
.foo {
height: 100%;
}
</style>
let style2 = <style runtime="jss">
foo {
height: 100%;
}
</style>
// or, maybe instead of <style>, template tag syntax:
let style = jss`
foo {
height: 100%;
}
`
But I'm not sure how to enable named:false
in the template tag form of the jss example, so maybe the <style>
tag is more useful.
Also, what happens if a user places a <style>
tag in a React component, which is bound to happen if CSSX gained wide adoption:
render() {
return <div>
<h1>My React App</h1>
<style runtime="jss">
.foo {
height: 100%;
}
</style>
</div>
}
Maybe a compile-timeerror would be thrown in that case, with an explanation pointing to some docs on how to use CSSX?
Or maybe you can somehow scope that style to the element where the <style>
tag is located? Maybe it'd require matching rules. F.e.:
render() {
return <div>
<h1 className="foo">My React App</h1>
<style runtime="jss">
.foo {
color: red;
}
</style>
</div>
}
That's just an outer-level idea. I'm not sure what JS that'd actually translate to. Maybe it'd remove the stylesheet entirely from the JSX, before JSX handles it, so it'd look like the following before JSX transforms the code:
var _cssx_classes1 = (function () {
...
}.apply(this));
render() {
return <div>
<h1 classname="{_cssx_classes1.foo}">my react app</h1>
</div>
}
@trusktr thank you for commenting here. Here is my feedback:
Regarding the
runtime
attribute
CSSX is translated to JavaScript similarly to JSX. The difference is that CSSX result is not doing anything. It's not using any library. It's just a creation of object literal. What happen with this next depends on the developer. For example:
let style = <style>
.foo {
height: 100%;
}
</style>
Is transformed to:
let style = (function () {
var _1 = {},
_2 = {};
_2['height'] = '100%';
_1['.foo'] = _2;
return _1;
}.apply(this));
which is the same saying:
let style = {
".foo": {
"height": "100%"
}
}
How the style
variable is used is completely up to the developer. So, if we add a runtime attribute we'll make a big assumption which I want to escape from.
Also, what happens if a user places a
<style>
tag in a React component.
We'll indeed get an error. If we have to provide a message that points the developer to CSSX docs then we have to contribute to JSX transpilation which will assume that by adding <style>
you mean CSSX which is not quite right. You may have a React class component which name is style
.
Or maybe you can somehow scope that style to the element where the
<style>
tag is located?
There is react-cssx project where we have a CSSX
component and we do have scoping of CSSX styles. However, I'm thinking that the project here should be really about transpiling. Even though we have a consumer of the transpiled code will be nice to use jss or css-modules instead because they did a good progress and have some sort of adoption already.
Maybe it'd remove the stylesheet entirely from the JSX, before JSX handles ...
This requires changes in how JSX is transpiled which is part of babylon project. If I have to submit a PR with this I'm 99% sure that it will be rejected because (a) it's a custom thing and (b) will decrease the performance of the transpiler.
@krasimir
It's just a creation of object literal. What happen with this next depends on the developer.
Maybe "format" is better than "runtime". So that way a developer can choose between CSSX or JSS object formats, depending on what the developer prefers, then do as needed with the object.
About the JSX stuff, for sure. Just throwing some ideas out there. I myself am fine just having the object transpiled from the CSS syntax, f.e.
jss.createStyleSheet(<style format="jss">
...
</style>)
So that way a developer can choose between CSSX or JSS
I adopted the JSS format. So now CSSX and JSS use same thing. (I mean in the released version 5).
adopted the JSS format
Oh okay, gotcha. That works in my case since I'm using JSS. :]
Can't wait to try this soon!
Just got to try this for the first time finally (cssx-loader + jss). So awesome!
I am wondering if you could imagine to compile cssx syntax to json dsl of jss and then use jss lib for rendering at runtime.