vue-material localized theme to avoid conflict - vue.js

Running a vuejs application as component of a website, using vue-material theming css create conflict with existing css.
By default, vue-material add a class on html <html class="md-theme-default"> to apply its style but I am trying to change that by only applying on a specific DOM element which should be my vue app.
Coming from material-ui, what I am looking for is the equivalent of <ThemeProvider> component.
Also, I only import a few components doing the following:
import { MdTabs, MdRadio } from "vue-material/dist/components";
import "vue-material/dist/vue-material.min.css";
import "./theme.scss";
Vue.use(MdRadio);
Vue.use(MdTabs);
Theme.scss redefine colors to match my theme.
#import "./variables";
#import "~vue-material/dist/theme/engine"; // Import the theme engine
#include md-register-theme("default", (
primary: $purple,
accent: $purple
));
#import "~vue-material/dist/theme/all"; // Apply the theme
I am using single .vue files with the following template synthax:
<template>
<div>
<md-radio v-model="radio" :value="objA">20€ / an</md-radio>
<md-radio v-model="radio" :value="objB">2€ / mois</md-radio>
</div>
</template>

Related

How to build web component with styling library using vite and vue 3?

I am able to build vue web component and load it in other pages, but I can't find document how to correctly include a UI framework. It seems the web component is under shadowDOM and import css using style tag won't work.
(Add the CDN link in the template and style is applied)
Any hint on any framework, Vuetify or Ant Design or Tailwind CSS will be appreciated.
Similar question: Vuetify build as Web component style not showing
Using custom elements without Shadow DOM is trivial. Just add like the way you do traditionally. However, with Shadow DOM, things are tricky. Only inheritable CSS styles pass through the Shadow DOM. Everything else is blocked. No straight forward integration with existing design systems (Vuetify, Ant, etc.) is not directly possible if that library is only exposing global CSS.
If the design system or a component library is exposing styles i.e. css files for individual components, then you can that with some effort.
The best solution is to use constructable stylesheet. You can use a bundler like Webpack to load the stylesheet for individual component (if and only if it is provided) as a string and feed it to the stylesheet constructor method as illustrated here.
// Read SCSS file as a raw CSS text using Webpack/Rollup/Parcel
import styleText from './my-component.scss';
const sheet = new CSSStyleSheet();sheet.replaceSync(styleText);
// Use the sheet inside the web component constructor
shadowRoot.adoptedStyleSheets = [sheet];
However, Firefox and Safari are yet to implement it.
If you need a fallback, then there are ways that are not so clean. Approach is same. Import the CSS/SCSS as a string and using the template literal, add it to the element's inner style tag.
import styleText from 'ant/button.css';
class FancyComponent extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `
<!-- Styles are scoped -->
<style>
${styleText}
</style>
<div>
<p>Hello World</p>
</div>
`;
}
}
customElements.define('fancy-comp', FacyComponent);
This all relies on the assumption that ant/material/veutify is exposing styles as individual files instead of one global file.
Alternately, the browsers have started supporting the link tag inside the Shadow DOM. But again it is really useful if you have styles for individual components. Read more about that here.

Headless UI component will not take style

I'm currently playing around with Headless UI and I can't seem to style any of the components.
This is the code in my tabs file
<template>
<TabGroup>
<TabList class="bg-blue-900/20 rounded-xl">
<Tab>Products Information</Tab>
<Tab>Find Offices Nearby</Tab>
<Tab>Requirements</Tab>
</TabList>
<TabPanels>
<TabPanel>Content 1</TabPanel>
<TabPanel>Content 2</TabPanel>
<TabPanel>Content 3</TabPanel>
</TabPanels>
</TabGroup>
</template>
<script>
import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '#headlessui/vue'
export default {
components: {
TabGroup,
TabList,
Tab,
TabPanels,
TabPanel,
},
}
</script>
It's either of these problems
Tailwind CSS is not installed or configured properly so you cannot use Tailwind CSS classes like 'rounded-xl'.
'bg-blue-900/20' is not an inbuilt tailwind CSS class, so either customize color in tailwind or use inbuilt colours like 'bg-blue-400', 'bg-blue-500', etc
Tailwindcss v2.1 introduced JIT mode that generates styles on-demand.
You need to enable jit mode to use such classes like bg-blug-900/20.
You can see how to do that in official doc

Cannot use vue-start-rating in nuxt.js?

Cannot Used vue-star-rating in nuxt.js ReferenceError
document is not defined
<template>
<star-rating v-model="rating"></star-rating>
</template>
import StarRating from "vue-star-rating";
export default {
components: {
StarRating
}
}
thi is my codesandbox
Currently vue-star-rating does not support SSR, however, there is a feature-request open for this.
Currently, the only way to get this working with nuxt is to downgrade vue-star-rating to 1.6.2 and wrap it in no-ssr tags,
<no-ssr>
<star-rating :rating="3"></star-rating>
</no-ssr>
The solution above didn't work for me.
So, I just took the library (2 components and 1 class) and moved it to my component folder, so the components support the SSR now.

babel-standalone not transpilling esm module

I want to write vue demo for education teaching purpose, in order to focus only the vue part, I don't want to introduce npm, bundler like webpack or browserify and so on.
So I write code using babel-standalone. I also want to use vue-class-component. But now I could not use the esm build of vue and vue-class-component, in short I want to support write code like this in my main.js
import Vue from '../vender/vue.esm.browser';
import Component from '../vender/vue-class-component.esm';
#Component
class App extends Vue {
//......
}
If I wrote the code like above, I got Uncaught ReferenceError: require is not defined eror.
Now I can make it work using the following style, but using the Component of vue-class-component is ugly.
<!-- the html contain these scripts -->
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vue-class-component#7.1.0/dist/vue-class-component.js"></script>
<script src="vender/babel.min.js"></script>
<!-- fix regenerator not defined -->
<script src="vender/regenerator-runtime.js"></script>
<script src="js/main.js"
data-plugins="transform-runtime,transform-class-properties,transform-decorators-legacy,transform-regenerator"
data-presets="es2015,stage-1" type="text/babel">
</script>
// js/main.js
const Component = VueClassComponent.default;
#Component
class App extends Vue {
//......
}
more details can found on https://github.com/liudonghua123/todos/tree/master/todos-vue-class-component
You need to add to data-plugins: "transform-es2015-modules-umd"

Font Awesome 5 Bundle via NPM

I'm trying to bundle only required Font Awesome 5 icons via webpack, but the icons are not replaced in the DOM.
I've added all required packages from the documentation:
yarn add -D #fortawesome/fontawesome
yarn add -D #fortawesome/fontawesome-pro-solid
yarn add -D #fortawesome/fontawesome-pro-regular
yarn add -D #fortawesome/fontawesome-free-brands
The following custom JS is included:
"use strict";
import fontawesome from '#fortawesome/fontawesome';
import faCheck from '#fortawesome/fontawesome-pro-regular/faCheck';
fontawesome.icon(faCheck);
function iconsDoneRendering () {
console.log('Icons have rendered'); // No output in console
}
fontawesome.dom.i2svg({
callback: iconsDoneRendering,
})
The HTML template:
<head>
<link rel="stylesheet" href="/css/app.css?v2.1.4"> <!-- contains fa-svg-with-js.css -->
</head>
<body>
<ul class="fa-ul">
<li><span class="fa-li"><i class="far fa-phone"></i></span>List item 1</li>
<li><span class="fa-li"><i class="far fa-check"></i></span>List item 2</li>
</ul>
<script src="/js/app.js?v2.1.4"></script>
</body>
The svg path is inside the bundled JS file, but I can't figure out which method needs to be called.
The following JS code solves the problem (since v5.0.2):
"use strict";
import fontawesome from '#fortawesome/fontawesome';
import faCheck from '#fortawesome/fontawesome-pro-regular/faCheck';
import faPhone from '#fortawesome/fontawesome-pro-regular/faPhone';
fontawesome.library.add(faCheck,faPhone);
I realize this is already answered, but I'd like to give some visibility to the full solution since the information above does not include how to execute the SVG icon replacement.
If you're loading Font Awesome 5 via NPM & WebPack for use in front-end HTML like I am, you will need to do something like this in your JS that's included in your bundle:
"use strict";
// Import FontAwesome: https://fontawesome.com/how-to-use/use-with-node-js
import fontawesome from '#fortawesome/fontawesome';
// This enables using FontAwesome in CSS pseudo elements
// see: https://fontawesome.com/how-to-use/svg-with-js#pseudo-elements
fontawesome.config.searchPseudoElements = true;
// Icons should be imported individually to keep bundle size down
import faCheck from '#fortawesome/fontawesome-pro-regular/faCheck';
import faPhone from '#fortawesome/fontawesome-pro-solid/faPhone';
fontawesome.library.add(faCheck, faPhone);
// If really necessary, entire styles can be loaded instead of specifying individual icons
//import solid from '#fortawesome/fontawesome-pro-solid';
//fontawesome.library.add(solid);
// Execute SVG replacement
fontawesome.dom.i2svg();
That last line is key, you have to execute SVG icon replacement manually.
We just released version 5.0.2 and updated the #fortawesome NPM packages to fix a few bugs related to this. Make sure you upgrade before you try anything else.
The missing step of the above example is to add the icon to the library:
fontawesome.library.add(faCheck)
Try to use
fontawesome.library.add(faCheck);
instead of
fontawesome.icon(faCheck);
If it does not work, please update your question with your DOM template, to see how it's defined in there.