cssinjs / jss

JSS is an authoring tool for CSS which uses JavaScript as a host language.
https://cssinjs.org
MIT License
7.08k stars 399 forks source link

How to combine named with non-named classes? #71

Closed trusktr closed 9 years ago

trusktr commented 9 years ago

For example, I have

let style = {
    tabbacking: {
        backgroundColor: '#25383C',
    },

    tabbaritem: {
        color: '#818181',
        textAlign: 'center',

        '&.selected': {
            color: '#f5f5f5',
            backgroundColor: '#66ccff',
        },
    },
}

let sheet = jss.createStyleSheet(style).attach()

I'd like to use tabbacking and tabbaritem namespaced classes, but I'd like for &.selected to apply whenever my component has the tabbaritem named class and the literal selected class.

How would you recommend doing something like that?

trusktr commented 9 years ago

sheet.toString() yields

.jss-0-0 {
  backgroundColor: #25383C;
}
.jss-0-1 {
  color: #818181;
  textAlign: center;
  &.selected: [object Object];
}

Does that mean that jss-nested isn't coming into play here?

kof commented 9 years ago

This should already work, I have a unit test for it https://github.com/jsstyles/jss-nested/blob/master/test/index.js#L101

kof commented 9 years ago

you did something wrong and I don't see a reproducible example to say what.

trusktr commented 9 years ago

@kof Ah, yes, the problem is my entry point imports jss (via ES6 modules) and configures it. The problem with this (compared to using CommonJS) is that all the modules I've required into my entry point use JSS before the entry point has configured JSS.

f.e.:

// JSS -> https://github.com/jsstyles/jss
import jss               from 'jss'
import jssNested         from 'jss-nested'
import jssVendorPrefixer from 'jss-vendor-prefixer'
import jssPx             from 'jss-px'
import jssExtend         from 'jss-extend'
import jssCamelCase      from 'jss-camel-case'
import jssPropsSort      from 'jss-props-sort'

// DTC components that use JSS, loaded *before* configuring JSS!
import Header            from './_header'
import Stack             from './_stack'
import Tabbar            from './_tabbar'
import Menu              from './_menu'

jss.use(jssNested)
jss.use(jssVendorPrefixer)
jss.use(jssPx)
jss.use(jssExtend)
jss.use(jssCamelCase)
jss.use(jssPropsSort)

let sheet = jss.createStyleSheet({
    'body, html': {
        width:    '100%',
        height:   '100%',
        position:  'relative',
        padding:   0,
        margin:    0,
        overflow:  'hidden'
    },
    div: {
        boxSizing: 'border-box'
    }
}, {named: false}).attach()

As you can see there, the plugins are added after the component modules are evaluated. With CommonJS, it's possible to configure JSS before evaluating the component modules (not possible with ES6):

// JSS -> https://github.com/jsstyles/jss
let jss               = require('jss')
let jssNested         = require('jss-nested')
let jssVendorPrefixer = require('jss-vendor-prefixer')
let jssPx             = require('jss-px')
let jssExtend         = require('jss-extend')
let jssCamelCase      = require('jss-camel-case')
let jssPropsSort      = require('jss-props-sort')

jss.use(jssNested)
jss.use(jssVendorPrefixer)
jss.use(jssPx)
jss.use(jssExtend)
jss.use(jssCamelCase)
jss.use(jssPropsSort)

// DTC components that use JSS, loaded *after* configuring JSS!
let Header            = require('./_header')
let Stack             = require('./_stack')
let Tabbar            = require('./_tabbar')
let Menu              = require('./_menu')

let sheet = jss.createStyleSheet({
    'body, html': {
        width:    '100%',
        height:   '100%',
        position:  'relative',
        padding:   0,
        margin:    0,
        overflow:  'hidden'
    },
    div: {
        boxSizing: 'border-box'
    }
}, {named: false}).attach()

I overlooked that.

trusktr commented 9 years ago

I think CommonJS is here to stay for a while because of that flexibility it has. I love ES6 module syntax, but it's not as flexible.

kof commented 9 years ago

there is no difference between cjs and es6 imports in this regard, just change the order in your es6 example

trusktr commented 9 years ago

This wasn't allowed in the recent past. Maybe the rules changed?

kof commented 9 years ago

never heard of this being not allowed


import jss               from 'jss'
import jssNested         from 'jss-nested'
import jssVendorPrefixer from 'jss-vendor-prefixer'
import jssPx             from 'jss-px'
import jssExtend         from 'jss-extend'
import jssCamelCase      from 'jss-camel-case'
import jssPropsSort      from 'jss-props-sort'

jss.use(jssNested)
jss.use(jssVendorPrefixer)
jss.use(jssPx)
jss.use(jssExtend)
jss.use(jssCamelCase)
jss.use(jssPropsSort)

// DTC components that use JSS, loaded *before* configuring JSS!
import Header            from './_header'
import Stack             from './_stack'
import Tabbar            from './_tabbar'
import Menu              from './_menu'
kof commented 9 years ago

You are right, babel will put imports on top

kof commented 9 years ago

I never stumbled over this because I don't put those things into same file, I have a separate jss.js file which does jss setup

kof commented 9 years ago

I think this will solve your prob.

trusktr commented 9 years ago

@kof Yeah, that's what I ended up doing, import jss from './my-configured-jss'. :]

trusktr commented 9 years ago

I just confirmed in the BabelJS slack that the imports can be defined anywhere in the top level of files, but that doesn't guarantee the order the modules are loaded.

Interesting and good to know!