Use bootstrap css and other global css in Vue.js custom elements - css

No fancy webpack, simple Vue custom element with some global css and some inline css for overrides.
I would like to use some styling library, like from getbootstrap.com and have it change styles inside custom element.
https://jsfiddle.net/Deele/6xk1atrn/25/
<div class="btn bg-info">Zero</div>
<test-widget id="One"></test-widget>
<test-widget id="Two"></test-widget>
const TestWidget = Vue.defineCustomElement({
props: {
id: String
},
data: () => {
return {
message: 'Test'
}
},
emits: {},
template: `<div class="btn bg-info">{{id}} {{message}}</div>`,
styles: [`div { color: green; }`]
})
customElements.define('test-widget', TestWidget)
.bg-info {
background-color: red!important;
}
Was expecting divs inside rendered elements would be styled as buttons, but it does not work!?
From what I have found in the internet, it has something to do with Shadow DOM not inheriting any global styles.
Please, tell me if there is a solution to this approach? I would like to create small widgets for my website using Vue.js, but this hurdle creates fatal limitation.

Custom elements defined using the Vue API always use a shadow DOM, so they are isolated from the parent document and any global styles in the app.
So to make it happen, You can inject the bootstrap styles or any global style url's in the styles option by using #import statement.
Live Demo :
const TestWidget = Vue.defineCustomElement({
props: {
id: String
},
data: () => {
return {
message: 'Test'
}
},
template: `<div class="btn bg-info">{{id}} {{message}}</div>`,
styles: [`#import url("https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css"); div { color: green; }`]
});
customElements.define('test-widget', TestWidget);
<script src="https://unpkg.com/vue#next"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css"/>
<div class="btn bg-info">Zero</div>
<test-widget id="One"></test-widget>
<test-widget id="Two"></test-widget>

Related

Add styles of class of external css file to Block props to use as attributes

Is it possible to use styles of a class in an external css file ( which is added to the block.json) as props to use these as attributes in the InspectorControls Component, if so, how?
I know that I can use inline styles as attributes for the InspectorControls Component. But dont know any way to use certain parts of classes in the external css files.
My css file added to the blocks.json:
"editorScript": "file:./index.js",
"editorStyle": "file:./editor.css",
"style": "file:./style.css"
I want to use Method 2 from this wordpress docs page for my classes and then use parts of the classes as attributes.
Yes, by importing the class names from a CSS module as the options for a UI control (eg <SelectControl>) the class can be applied to the block with useBlockProps().
In the example below, I used create block to setup a simple block that renders a paragraph which the user can choose the color "theme" of. It's best to use a CSS file containing only the classes you wish to load into the UI component, eg:
theme.scss (or an external css file)
.red{
color:red;
border-color: red;
}
.blue{
color:blue;
border-color: blue;
}
Create a new SCSS file with CSS modules in block/src to import the external styles:
classes.module.scss
#import './theme.scss';
Import the same external CSS in the blocks main style so it will be compiled into style.css, eg:
style.scss (main block styles)
#import './theme.scss';
.wp-block-gutenberg-default-block{
/* all custom styles for the block */
padding: 1em;
border:2px solid;
}
Alternatively, you could enqueue the stylesheet separately via PHP or via the theme..
Add a new string attribute to store the name of the class selected from the UI/SelectControl, eg:
block.json
{
...
"attributes": {
"customClassName": {
"type": "string",
"default": ""
}
},
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
}
By naming the importing the CSS module in edit(), we can have access an Object containing all the classes from theme.scss. Before displaying in the UI, the class names are formatted as options for a <SelectControl>. The selected class name is saved to the blocks attributes and applied by useBlockProps(), eg:
edit.js
import { InspectorControls, useBlockProps } from '#wordpress/block-editor';
import { PanelBody, SelectControl } from '#wordpress/components';
import styleClasses from './classes.module.scss';
export default function Edit({ attributes, setAttributes }) {
const { customClassName } = attributes;
const myClasses = [{ label: 'none', value: '' }]; // Default option for SelectControl
// Add each classname in styleClasses to myClasses
for (const key in styleClasses) {
myClasses.push({ label: key, value: key })
}
return (
<>
<InspectorControls>
<PanelBody>
<SelectControl
label="Custom Class"
value={customClassName}
options={myClasses}
onChange={(value) => setAttributes({ customClassName: value })}
/>
</PanelBody>
</InspectorControls>
<p {...useBlockProps({ className: customClassName })}>Hello World</p>
</>
);
}
Finally, useBlockProps.save() wraps the selected classname into the blocks markup on save.
save.js
import { useBlockProps } from '#wordpress/block-editor';
export default function save({ attributes }) {
const { customClassName } = attributes;
return (
<p {...useBlockProps.save({ className: customClassName })}>Hello World</p >
);
}
End result:
Hopefully this will give you some ideas for what's possible in your own block with CSS and attributes.

react-step-progress bar styling customization

I am creating a progress bar using the react-step-progress[enter link description here][1] library provided in react. It already takes it own styling reference from react-step-progress/dist/index.css. But, I want to override the colors provided by them. I tried to override by creating my own sass file and giving reference to those classes but they dont seem to override the existing styles.
Can someone please help me override those styles?
I had taken reference from the following link. https://www.npmjs.com/package/react-step-progress?activeTab=readme
I have tried to override in the following way.
I imported my own scss file with the required styles I want in my tsx file.
Then I referred my respective classes in the progressbar tag like this.
iconStyles.module.scss
.ProgressBar {
.stepColor {
color:#ffffff;
background-color: #26890D;
}
}
And I have imported this class into my tsx file in the following way :
Progressbar.tsx
import styles from './iconStyles.module.scss';
import * as React from 'react';
import StepProgressBar from 'react-step-progress';
const step2Content = <h1>Step1</h1>;
const step3Content = <h1> Step 2</h1>;
const step4Content = <h1> Step3 </h1>;
export default function ProgressBar() {
// setup step validators, will be called before proceeding to the next step
function step2Validator() {
// return a boolean
}
function step3Validator() {
// return a boolean
}
// render the progress bar
return (
<div>
<StepProgressBar
className={styles.stepColor}
startingStep={0}
steps={[
{
label: 'Step1',
name: 'Step1',
content: step1Content
},
{
label: 'Step2',
name: 'Step2',
content: step2Content,
validator: step2Validator
},
{
label: 'Step3',
name: 'Step3',
content: step3Content,
validator: step3Validator
}
]} onSubmit={undefined} />
</div>
);
}
To control the class used for each step you need to use the stepClass prop rather than the className prop:
[...]
return (
<div>
<StepProgressBar
stepClass={styles.stepColor}
startingStep={0}
steps={ [...] }
onSubmit={undefined} />
</div>
);

Vue.js stylus and scoped css is not working

I'm using stylus and scoped css styles with vuetify. I tried using deep nested selector ::v-deep or >>> but none of them had worked for me (eventhough i rebuild the project because hot reload sometimes is not working) Whenever i click on textbox, this class is being applied to it (i believe coming from vuetify
.v-application --primary-text{
color:white !important
}
Now I tried changing and overriding this style via but none of them had worked.
<style lang="stylus" scoped>
.v-application
&.primary--text
color:black !important
.sample
color:red !important
.v-application >>> .primary--text
color:black !important
.v-application /deep/ .primary--text
color:black !important
.v-application::v-deep .primary--text{
color:black !important
}
</style>
Template part
<template>
<div>
<v-text-field
v-model="name"
label="Regular"
counter="25"
hint="This field uses counter prop"
#input="updateFilter"
#keyup.enter="onEnter"
clearable
:class="sample"
>
<v-icon small #click="submit">fas fa-search</v-icon>
</v-text-field>
</div>
</template>
<script>
import Vue from 'vue'
export default Vue.extend({
name: 'MultiSearch',
data() {
return {
name: '',
// title: 'Preliminary report',
// description: 'California is a state in the western United States',
// rules: [(v) => v.length <= 25 || 'Max 25 characters'],
// wordsRules: [(v) => v.trim().split(' ').length <= 5 || 'Max 5 words'],
}
},
methods: {
updateFilter(event) {
console.log('event is', event)
console.log('this name', this.name)
},
submit(event) {
console.log('event is', event)
console.log('clicked', this.name)
this.$emit('updateFilter', this.name)
},
onEnter(event) {
console.log('entered is ', event)
},
},
})
</script>
Did you installed stylus at first before trying any CSS ?
yarn add -D stylus stylus-loader
https://vue-loader.vuejs.org/guide/pre-processors.html#stylus
As of the selector, this should be ::v-deep indeed.
Reference for the selectors: https://stackoverflow.com/a/55368933/8816585
I solved this problem by adding
options: { styleIsolation: 'shared' }, // add this
methods: {
yourFunc1 () {
}
}
.
Config this in the components like the methods, it's the same level like methods.

Overlapping CSS in React, Webpack application

I have created an application using webpack and reactjs.
So far I have created 2 pages. I have defined CSS styling for both the pages. But when I load page 2 after loading page 1, the styles from page 1 are interfering with those of page 2.
For example
Page 1
require('style1.css');
var Page1 = React.createClass({
render: function(){
return(
<div> <h1>This is Page1</h1> <span> hello from page1</span></div>
)
}
});
module.exports = Page1;
style1.css
span {
color : red
}
Page 2
require('style2.css');
var Page2 = React.createClass({
render: function(){
return(
<div> <h1>This is Page2</h1> <span> hello from page2</span></div>
)
}
});
module.exports = Page2;
style2.css
h1 {
color : blue
}
When page2 is loaded after page1, the color of span was red, which was loaded from page1's style. Is there any way to avoid such kind of interferences or am I doing something wrong here?
You can have local stylesheets for each React component.
So the style sheet itself will have something like this:
:local(.styles) {
.your-style{...}
}
You can store it in the same folder as your component code. You import the style like so:
/* component styles */
import { styles } from './styles.scss'
In the render function of your component you will have this:
return (
<div className={styles}>
...
</div>
)
Everything within that <div> will have the stylesheet applied.
Loader configuration for your Webpack:
loaders: [{
test: /\.scss$/,
loader: 'style!css?localIdentName=[path][name]--[local]!postcss-loader!sass',
}]
You can look at this awesome boilerplate app, that implements all of this very nicely.
Webpack is not going to fix the inherent problems with style sheets. If you want component level styling the simplest solution is to go with inline styles. You might also look at Radium. https://github.com/FormidableLabs/radium

How to apply style rules that are tied to a model in AngularJS?

I am building an application which sends 1-5 views and the appropriate model&controller to the client on page load. The user is guided to each view consecutively using routing and this is working just fine.
The problem I have is that I want to apply style rules to the view, but the style rules are tied to the model. I know that I cannot simply save some css as text and inject them into a <style></style> block. I cannot simply add a reference to a .css file because all of this is coming from a database, and each model could potentially have style rules that conflict with another model.
Any advice on how to solve this issue?
You can insert a style element into the page:
angular.module('myApp', [])
.controller('MyController', function($scope) {
$scope.css = ".red { color: red;}"
})
.directive('myDirective', function() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
var style = angular.element('<style type="text/css"></style>');
style.append(scope.css);
elem.append(style);
}
}
});
Plunker Demo
Here's an example of using ng-class. If you can get your css rules out of the database and into a $scope object like this:
$scope.css = {
divcss:{
'border-style': 'solid',
'border-width': '2px',
'background-color': 'yellow'
},
headercss:{
'font-weight': 'bold',
'font-size': '50px'
}
}
Then you can apply them to your view element like this:
<div ng-style="css.divcss">Check it out</div>
<span ng-style="css.headercss">Big ol' Header</span>
Plunker demo

Resources