Emotion: Support Vue

Created on 29 Jun 2017  路  7Comments  路  Source: emotion-js/emotion

Is this even a thing in Vue?

import Vue from 'vue'
import { css } from './index'

export default function (tag, cls, vars = [], content) {
  return Vue.component('styled', {
    props: ['class'],
    template: `<${tag} v-bind:class="[{{class}}, ${css(
      cls,
      vars.map(v => (v && typeof v === 'function' ? v(props) : v)),
      content
    )}]"><slot></slot></p>`
  })
}

Suggested solution:
Learn Vue

Most helpful comment

I've tested this locally and it works except for the name so you can only have one component. I'm trying to extract the name from the class name but it's being strange.

import Vue from 'vue'
import { css as magic } from 'emotion'

const styled = (tag, cls, vars = [], content) => {
  Vue.component('styled', {
    functional: true,
    render (h, context) {
      const className = magic(
        cls,
        vars.map(v => (v && typeof v === 'function' ? v(context.props) : v)),
        content
      )
      return h(tag, { class: context.props.class
          ? className + ' ' + context.props.class
          : className }, context.children)
    }
  })
}

export default styled

All 7 comments

I think Vue converts templates into jsx render functions.

Haven't tried locally, but how about something like this:

import { css } from './index'

Vue.component('styled', {
  props: ['class'],
  render(h) {
    const ourCss = css(
      cls,
      vars.map(v => (v && typeof v === 'function' ? v(props) : v)),
      content
    );

    return h(tag, { class:`${this.class} ${ourCss}` }, this.$slots.default);
  }
});

Mostly from docs example

I've tested this locally and it works except for the name so you can only have one component. I'm trying to extract the name from the class name but it's being strange.

import Vue from 'vue'
import { css as magic } from 'emotion'

const styled = (tag, cls, vars = [], content) => {
  Vue.component('styled', {
    functional: true,
    render (h, context) {
      const className = magic(
        cls,
        vars.map(v => (v && typeof v === 'function' ? v(context.props) : v)),
        content
      )
      return h(tag, { class: context.props.class
          ? className + ' ' + context.props.class
          : className }, context.children)
    }
  })
}

export default styled

@mitchellhamilton I think class can be an array so you can lose the concat. Not 100% sure if it works with h though.

You don't need to register the component globally I guess? I mean no need of Vue.component('styled', component), just return the component object.

Thanks @egoist, it's working perfectly now, about to submit a PR.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mitchellhamilton picture mitchellhamilton  路  3Comments

kentcdodds picture kentcdodds  路  3Comments

desmap picture desmap  路  3Comments

meebix picture meebix  路  3Comments

hamlim picture hamlim  路  3Comments