Fela does the great job, but it has no idea how to cook it with Vue. This is what I've created after combining vue's :style and :class attributes to make apps dynamically configured and easiest to write and maintain.
// All of the options are optional. const options = { // Default styles to mix. Does not mix if omitted. // Have a look at the example below to see it in action. // Either pass a function (then key would be `fdef`): defStyles: (componentInstance) => ({ colors: { cyan: 'cyan' }, bold: { fontWeight: 'bold' } }), // ... Or an object with your own key: defStyles: { key: 'fdef', value: (componentInstance) => ({ colors: { cyan: 'cyan' } }) }, // Modifiers to classes when assigned from templates. See examples below. // Each modifier is a condition that is being called with provided class name and context object. modifiers: {}, // Name of styling method. Defaults to `f`. method: 'f', // Additional fela plugins. plugins: [], // Additional fela enhancers. enhancers: [], // Preset configurations. preset: { // Config for fela-plugin-unit. Same defaults ('px', {}). unit: ['em', { margin: '%' }] }, // SSR status. ssr: false } const renderer = new Renderer(options) // If Options API. To use globally: Vue.mixin(renderer.mixin) // or createApp(App).mixin(stylesRenderer.mixin) // ... Or per module export default { mixins: [ renderer.mixin ], // ... }
// main.js import Vue from 'vue' import { Renderer } from 'fela-vue' const renderer = new Renderer({ ...options, modifiers: { // Too simple but short c: mobile: () => window.clientWidth < 600 } }) // Not required. // Search for documentation link by "DOM helpers" here above. renderer.setClasses(css` .html, .body { margin 0 padding 0 font-size 18px } `) // if Options API. // Vue 2: Vue.mixin( renderer.mixin ) // Vue 3: // createApp(App) // .mixin((new Renderer(options)).mixin) // .mount('#app')
<template> <div :class="f('wrapper')"> <span :class="f('one')"> It's green! </span> <span :class="f('two')"> It's cyan! </span> <span :class="f('mobile&one !mobile.two localModifier.bold')"> It's green when mobile modifier is true and cyan when false. `.` equals to `&` on your taste. For Options API the local modifiers named styleMods in mixins (see below in JS) For Composition API search for "with Vue Composition API" doc link above. </span> <span :class="f('three', {color: 'white'})"> you don't see me! </span> <span :class="f({color: 'yellow'})"> I do it by myself! </span> <span :class="f('one two, bold')"> Combined classes by commas and spaces </span> <span :class="f('bold my-kebab')"> And kebab-case! </span> <span :class="f('bold myKebab')"> The same! </span> <span :class="f('button one')"> If class is not in local style(), it will be taken from defaults (defStyles), if present. Here's button could be taken from there, then merged with `one` where is `one` is in priority: right to left principle. </span> <div v-for="i in [0,1,2]"> <span :class="f((i) => ({color: ['green', 'blue', 'yellow'][i]}))" > This way is OK too. </span> </div> </div> </template> <script> // Uncomment to use literal css: css`...` // import { css } from 'fela-vue' import { defineComponent } from 'vue' export default defineComponent({ computed: { style() { // Not required. Use with arbitrary key by `options.defStyles.key`. const { colors } = this.fdef // Also, it's recommended to return one css`...` with all classes included. // Search for a "lit-css" documentation link above. // Also search for a "Vue Composition API" to use along it. return { one: { color: 'green' }, two: { color: colors.cyan }, three: ({color}) => { fontWeight: 'bold', color }, bold: () => ({ fontWeight: 'bold' }), // 'my-kebab' is also valid if the same in the template. myKebab: { color: 'purple' }, anotherClass: css` background: grey `, ...css` .other-class { margin-top: 44; // still ok for fela. will be 44px. // you can comment a whole line, margin-left: 22 // this's OK too. /* block comments are also supported. */ :hover { // no colons and semicolons are ok. background grey } } .anotherOne { padding: 15 } ` } }, styleMods() { return { localModifier: (name, context) => true } } } }) </script>
It's better to make this computed in the end of a component definition or make a const variable at the bottom and return it from the computed prop.
Also, It's very handy to make snippets for adding style() {} to computed.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4