Skip to content

[Feature request]: Add new syntax for jsx classes #155

@MaxmaxmaximusGitHub

Description

@MaxmaxmaximusGitHub

I remind you that JSX itself is a SUGAR on top of javascript ;)

💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡
💡 We need more sugar! New syntax for jsx classes! (and isolated styles)
💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡

  • Start Date: 2020-04-13

Summary

new JSX class syntax:

  1. attr start with dot is class name (intentionally similar to css, yes)
  2. if this attr have expression value, then if exp is true, then class exists, otherwise not exist
  3. of course, these classes have an ISOLATED SCOPE, for the ISOLATION of styles, I came up with this syntax.

Basic example

this:

<div .block .chat .active={ state.active }></div>

compile to:

<div className={ `block chat${ state.active ? " active" : "" }` } ></div>

by the way, no one forbids you to add dynamic class names, and still use your favorite css modules

this:

<div .[css.button] .[css.active]={ user.active } ></div>

compile to:

<div className={ `${css.button}${ user.active ? " " + css.active : "" }` }></div>

Motivation

Attributes names with started a dot symbol is prohibited, so dot is idle idle. dot can be used for syntactic sugar for routine 90% of the operations of assigning classes to elements.

people will be able to write a main class describing what kind of entity it is. and add dynamic modifier classes, which reflect the component state.

it’s just syntactic sugar. but it will save 90% of the time for developers. the programmer simply type on a keyboard the dot symbol, and the IDE will automatically autocomplete them for the available classes.

in brevity and elegance, this syntax is even superior to html ;)

our beloved jsx is high time to develop, because competitors (angular and vue) do not stand still ;)

Detailed design

you just look how cool:

<ul .users>
  {this.props.users.map( user =>
      <li .user .banned={ user.isBanned } .admin={ user.isAdmin }>
        User { user.name }
      </li>
  )}
</ul>

and imagine how it will be cool with syntax highlighting in the IDE and if you click by mouse wheel you will immediately be transferred to the desired selector in css file.

what it looks like now:

<ul className="users">
  {this.props.users.map( user =>
      <li className={ `user${ user.isBanned ? " banned" : "" }${ user.isAdmin ? " admin" : "" }` }>
        User { user.name }
      </li>
  )}
</ul>

feel the difference?

this:

<div .box .active={active} onClick={toggleActive}></div>

compile to this:

<div className={ `box${ active ? " active" : "" }` } onClick={toggleActive}></div>

just compare

export default function TabTitle({active, onClick, children}) {

  return <div className={ classes('tab-title', {
    __active: active
  }) } onClick={ onClick }>

    { children }

    <style jsx>{ style }</style>
  </div>
}

and my version:

export default function TabTitle({active, onClick, children}) {

  return <div .tab-title .__active={active} onClick={ onClick }>

    { children }

    <style jsx>{ style }</style>
  </div>
}

is a syntax hell :

image

We can use new syntax and old syntax at the same time:

this:

function classes(classesArr){ classesArr.join(' ') }

<div .box .active={active} className={ cssModule.class + classes(['one', 'two']) }>

compile to:

function classes(classesArr){ classesArr.join(' ') }

return <div className={[cssModule.class + classes(['one', 'two']), `box${active ? ' active' : '' }`].join(' ') }>

Drawbacks

Why should we not do this? Please consider:

There are no drawbacks, since the dot symbol was previously prohibited, backward compatibility is present.

The disadvantage is that jsx with the new syntax will cause a syntax error in compilers that do not support the new function. therefore, we must write babel-plugin to translate the new code into the "old" jsx.

Alternatives

You can write the babel plugin to support the new syntax, but this will not motivate the creators of the IDE to add new syntax. The popularity of React and Facebook and the headline "React 17.0 - New Syntax for Classes." will motivate support this feature.

Adoption strategy

React competitors use much more convenient syntax than jsx. Since it uses attributes starting with special characters. jsx does not use such attributes, and simply prohibits them. People are tormented by class definitions in jsx and rejoice in Angular and Vue. People will be happy with the new “meaningful” syntax, which will be much more organic than native html. Since in css classes start with a dot, in jsx they will also start with a dot. And also the most common operation with classes is adding or removing a class, depending on the state. We add and make it native. There is not a single developer in the world who says "bliiin, well, support for convenient classes has appeared (" and there are 99% of people who say "FINALLY" =)

How we teach this

This innovation is sugar, and does not break or change existing behavior. Therefore, we can simply ADD a new section to the "dot classes" documentation. Those who like the new syntax will use it, those who like the old will use the old. Anyone who likes both syntaxes can combine them. className is just a string, so at the jsx compilation stage we can quietly unify both methods of class declaration.

Unresolved questions

Since we are doing such a thing, then maybe we should immediately think about isolated styles for the component? Since we are making syntax changes, it may be that we think over the isolation of styles in advance? After all, if we implement this without thinking it over, then we will not be able to change it on the future. I suggest thinking about how to natively (from the point of view of jsx) and syntactically solve the problem of encapsulating classes, and how to make it flexible enough so that other encapsulation libraries can USE this syntax.

by the way, we can also add dynamic attribute names

this:

let prop = "ololo"
<div [prop]="value"></div>

compile to:

let prop = "ololo"
React.createElement('div', { [prop]: "value"} )

plus this syntax allows you to finally do this:

function List(props) {
  return <ul .list {...props}></ul>
}


function Component() {
  return <List .red></List>
}

its render to:

<ul className="lisit red></ul>

ability at the precompilation stage to competently concatenate dot classes and className is phenomenal =)

Adequate guys, do you want me to write a transpiler plugin for this syntax, and add support for it in your IDEs? Who agrees? I think to create a separate repository =)

UPD:

cheers guys, I came up with a workaround !!!! thank god these guys did not forbid the dollar symbol !!! =)

<div $chat $active={ false } $opened={ null }></div>

I will write a babel plugin that implements the behavior that I described here. the dollar sign will temporarily act as a dot symbol =) this way we can test new syntax

yes, it breaks backward compatibility, since now you can’t use properties starting with the dollar sign, but it's not my fault, but the guys from React =)

but living even that way will be much easier. of course it's a fierce crutch, but at least something

p.s. yes and goodbye typescript

I experimented a lot, and technically, the length of such a syntax is literally equal to the length of the syntax I proposed:

image

but visually the dollar symbool is annoying and far less logical than the dot symbool.

to implement override and disable classes semantics, I will write the runtime mergeProps function, but this will be the next step

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions