egoist / styletron-vue

Vue bindings for Styletron.
https://egoist.moe/styletron-vue
MIT License
48 stars 7 forks source link

Theming solution #2

Open egoist opened 7 years ago

egoist commented 7 years ago

Currently it supports:

styled('div', (props, ctx) => {
  // ctx: the context of created functional component
  // so you can access:
  // ctx.injections.theme
  // ctx.parent.$root.$options
  // ctx.parent.$store
})

Not sure which one is the best though 😅

ianwalter commented 7 years ago

I think the provide/inject method would probably be the most straightforward unfortunately I'm getting an error when trying to implement it. Do you have any ideas on how I can fix it?

Here is the MyFooter component:

<styled-footer>...</styled-footer>
import StyledFooter from '../styles/StyledFooter'

export default {
  name: 'BlueFooter',
  provide: { theme: 'blue' },
  components: { StyledFooter },
}

Here is the StyledFooter component:

import { styled } from 'styletron-vue'

import { colors } from '../data'

export default styled('footer', (props, { injections }) => ({
  color: injections.theme === 'blue' ? colors.blue : colors.gray
}))

The error is:


vue.esm.js:566 TypeError: Cannot read property 'injectDeclaration' of undefined
    at injectWithPlugins (inject-style-prefixed.js:94)
    at Object.injectStyle [as injectStylePrefixed] (inject-style-prefixed.js:46)
    at render (styletron-vue.es.js:27)
    at createFunctionalComponent (vue.esm.js:3459)
    at createComponent (vue.esm.js:3618)
    at _createElement (vue.esm.js:3797)
    at createElement (vue.esm.js:3736)
    at vm._c (vue.esm.js:4076)
    at Proxy.module.exports.staticRenderFns (MyFooter.vue?75e9:13)
    at Proxy.renderStatic (vue.esm.js:4002)
handleError @ vue.esm.js:566
Vue._render @ vue.esm.js:4130
updateComponent @ vue.esm.js:2538
get @ vue.esm.js:2881
Watcher @ vue.esm.js:2870
mountComponent @ vue.esm.js:2542
Vue$3.$mount @ vue.esm.js:7863
Vue$3.$mount @ vue.esm.js:10066
init @ vue.esm.js:3501
createComponent @ vue.esm.js:5147
createElm @ vue.esm.js:5090
createChildren @ vue.esm.js:5218
createElm @ vue.esm.js:5123
patch @ vue.esm.js:5606
Vue._update @ vue.esm.js:2414
updateComponent @ vue.esm.js:2538
get @ vue.esm.js:2881
Watcher @ vue.esm.js:2870
mountComponent @ vue.esm.js:2542
Vue$3.$mount @ vue.esm.js:7863
Vue$3.$mount @ vue.esm.js:10066
Vue._init @ vue.esm.js:4236
Vue$3 @ vue.esm.js:4321
renderRoot @ render.js:77
renderMain @ render.js:117
renderPreview @ render.js:135
renderUI @ index.js:89
dispatch @ createStore.js:173
_renderMain @ config_api.js:47
render @ config_api.js:66
configure @ config_api.js:91
(anonymous) @ config.js:7
options.path @ config.js:7
__webpack_require__ @ bootstrap c581583…?850f:659
fn @ bootstrap c581583…?850f:85
(anonymous) @ process-update.js:132
__webpack_require__ @ bootstrap c581583…?850f:659
(anonymous) @ bootstrap c581583…?850f:708
(anonymous) @ preview.bundle.js:712
vue.esm.js:479 [Vue warn]: Error in render function: "TypeError: Cannot read property 'injectDeclaration' of undefined"

found in

---> <MyFooter> at /Users/ian/styled/src/stories/MyFooter.vue
       <Root>
warn @ vue.esm.js:479
handleError @ vue.esm.js:562
Vue._render @ vue.esm.js:4130
updateComponent @ vue.esm.js:2538
get @ vue.esm.js:2881
Watcher @ vue.esm.js:2870
mountComponent @ vue.esm.js:2542
Vue$3.$mount @ vue.esm.js:7863
Vue$3.$mount @ vue.esm.js:10066
init @ vue.esm.js:3501
createComponent @ vue.esm.js:5147
createElm @ vue.esm.js:5090
createChildren @ vue.esm.js:5218
createElm @ vue.esm.js:5123
patch @ vue.esm.js:5606
Vue._update @ vue.esm.js:2414
updateComponent @ vue.esm.js:2538
get @ vue.esm.js:2881
Watcher @ vue.esm.js:2870
mountComponent @ vue.esm.js:2542
Vue$3.$mount @ vue.esm.js:7863
Vue$3.$mount @ vue.esm.js:10066
Vue._init @ vue.esm.js:4236
Vue$3 @ vue.esm.js:4321
renderRoot @ render.js:77
renderMain @ render.js:117
renderPreview @ render.js:135
renderUI @ index.js:89
dispatch @ createStore.js:173
_renderMain @ config_api.js:48
render @ config_api.js:66
configure @ config_api.js:91
(anonymous) @ config.js:7
options.path @ config.js:7
__webpack_require__ @ bootstrap c581583…?850f:659
fn @ bootstrap c581583…?850f:85
(anonymous) @ process-update.js:132
__webpack_require__ @ bootstrap c581583…?850f:659
(anonymous) @ bootstrap c581583…?850f:708
(anonymous) @ preview.bundle.js:712
vue.esm.js:566 TypeError: Cannot read property 'injectDeclaration' of undefined
    at injectWithPlugins (inject-style-prefixed.js:94)
    at Object.injectStyle [as injectStylePrefixed] (inject-style-prefixed.js:46)
    at render (styletron-vue.es.js:27)
    at createFunctionalComponent (vue.esm.js:3459)
    at createComponent (vue.esm.js:3618)
    at _createElement (vue.esm.js:3797)
    at createElement (vue.esm.js:3736)
    at vm._c (vue.esm.js:4076)
    at Proxy.module.exports.staticRenderFns (MyFooter.vue?75e9:13)
    at Proxy.renderStatic (vue.esm.js:4002)
egoist commented 7 years ago

@ianwalter hmm you need to bind styletron instance: https://github.com/egoist/styletron-vue#usage

maybe we should allow to pass that in provide too.

ianwalter commented 7 years ago

Ah you're right, I added it to the App's root Vue instance but I'm seeing the error in Storybook.js which most likely creates it's own root instance. I'll have to figure out a way to pass it to that, thanks!

egoist commented 7 years ago

@ianwalter basically you can set styletron instance anywhere now via component options (need Vue.use) or provide. https://github.com/egoist/styletron-vue#usage

egoist commented 7 years ago

In the meanwhile I made https://github.com/egoist/emotion-vue which you don't need to bind the instance but you need the emotion/babel babel plugin.

ianwalter commented 7 years ago

@egoist Thank you, I've gotten both working. Emotion doesn't seem to provide the same optimization as styletron on the other hand styletron doesnt support nesting and is hard to debug strangely enough since it doesn't show the css in the <style> tag inside of chrome dev tools. I guess I will try out fela.