At FeldsparTech we are working on a no-code platform called Atman. Atman's UI is a component library that works as a standalone application or can be embedded into another application to enable quick no-code workflows.
One of our goals is to allow granular control over our components. If this only meant rendering - we would build Renderless components. However, we also want the consuming application to be able to override, modify and augment behavior.
The approach we have chosen to achieve this goal is to use a Vuex store.
- Prerequisite: Both the consuming application and the library should import and use Vuex.
- We first need to dynamically register our library as a module in the application's store. This is possible through the registerModule method
if(!this.$store.hasModule("ourlibrary")){
this.$store.registerModule("ourlibrary", store);
}
- Methods that need to be customizable are implemented as actions in a vuex module. Within the action, the behavior could vary:
- If we want the consuming application to be able to override behavior, the action first checks if a global action is available and invokes it. If not, the action proceeds to perform the default logic specified in the library.
- If we want the consuming application to augment behavior, the module action first performs the internal logic and then invokes the global action (or vice versa) to perform any augmentation as necessary.
Overriding behavior example
overriddenMethod({dispatch},params){
if(this._actions["overriddenMethod"]) {
return dispatch("overriddenMethod", params, {root:true});
} else {
//Default behavior
}
}
Augmenting behavior example
augmentedMethod({dispatch},params){
let response;
/*
Internal logic which updates `response`
...
*/
if(this._actions["augmentedMethod"]) {
globalResponse = dispatch("augmentedMethod", params, {root:true});
}
/*
Update `response` with `globalResponse`
*/
return response;
}
This pattern is quite powerful. For instance, you can now even allow the consuming application to entirely replace a particular nested component with one of its own.
Here, the vuex action functions as a Factory. Now you can customize the logic as per your needs. The Overriding approach will entirely replace default component. The Augmentation approach will allow the consuming application to add business-specific components you may not want in the library.
Dynamic Component in the Library
<template>
<component v-if="currentComponent" v-bind:is="currentComponent"></component>
</template>
<script>
export {
//...
async mounted() {
this.currentComponent = await this.$store.dispatch(`<module>/deriveComponent`)
}
}
</script>
Action in Library's store
deriveComponent(context, params) {
let currentComponent;
//augment or override as per your requirements
return currentComponent
}
Resources I found useful during this exercise
- Github template to create a vuetify component library
mitevpi / vuetify-component-lib-template
Template for creating a component library/design system using Vue.js and Vuetify.js.
Vue.js + Vuetify.js Component Library Template
A Design System / Component Library Template for enabling graphic consistency and legibility across web development projects by creating reusable components and styles with accessible & legible documentation Built on top of Vue.js and Vuetify.js.
Usage
This Template is comprised of two major categories: Styles and Components. It builds to compiled components (
.js
) and compiled styles (.css
) from the source (.vue
) files which can be used across web applications. It also creates a Storybook site for component/design system documentation.Clone this repository locally, and use it as a starting point for building a component library / design system on top of Vue.js and Vuetify.js
Added/Updated Configurations to Vue CLI Starter
- AirBnB Style Guide
- Prettier Style Guide
- ESLint (Style Enforcing)
- Storybook
- Library Build
- SCSS/SASS
- Vuetify.js
Key Commands
After cloning/downloading the repository locally, install the required dependencies using…
- A step-by-step series by siegerts on how to create a Vue JS component library
Also cross-posted on Medium
Top comments (0)