Prevent Sass framework variable collisions - import

Is there a way that I could import multiple framework Sass files in a way that each framework will use its own variables without the variables of one framework overriding/colliding with the variables of the other while I would still be able to access the variables of one or both of those frameworks in subsequent styles as needed?
For example:
framework-a-variables.scss:
$border-color: green !default;
framework-a-box.scss:
.box-a { border: 1px solid $border-color; }
framework-b-variables.scss:
$border-color: red !default;
framework-b-box.scss:
.box-b { border: 1px solid $border-color; }
app-styles.scss:
#import 'framework-a-variables';
#import 'framework-a-box';
#import 'framework-b-variables';
#import 'framework-b-box';
This will result in an element with a box-b class having a green border due to how Sass variable declarations and the !default keyword work. Likewise, if I wanted to use $border-color as defined by framework-b-variables.scss in, say, button-styles.scss, I wouldn't be able to.
I have tried using placeholder selectors to scope the Sass imports so that the variables initialized by each framework are scoped to be used only by the other imported files of that framework. This seems to scope the variables as desired, but none of the styles are compiled unless I extend the placeholder selector, but Sass requires that extend directives be used only within rules and I wouldn't want to increase the specificity of all my selectors just to achieve this.
%framework-a-scope {
#import 'framework-a-variables';
#import 'framework-a-box';
}
%framework-b-scope {
#import 'framework-b-variables';
#import 'framework-b-box';
}
#extend %framework-a-scope; // This is not allowed in Sass
#extend %framework-a-scope; // This is not allowed in Sass
html {
#extend %framework-a-scope; // Wouldn't want do this
#extend %framework-b-scope; // Wouldn't want do this
}
I have also tried using mixins to scope the Sass imports. I believe that mixins, unlike extends, can output rules without being nested within rules, but Sass does not allow import directives within control directives or mixins.
#mixin framework-a-scope() {
#import 'framework-a-variables'; // This is not allowed in Sass
#import 'framework-a-box'; // This is not allowed in Sass
}
#include framework-a-scope();
So, is there any way to achieve what I am looking to achieve? I don't mind having to explicitly import variables in specific scopes when needed, for example:
.my-custom-box-1 {
#import 'framework-a-variables';
border: 1px solid $border-color;
}
.my-custom-box-2 {
#import 'framework-b-variables';
border: 1px solid $border-color;
}

Related

Styling Outline in react-pdf

Is there a way to style the outline of the react-pdf module, according to the documentation, the Outline component has the props className, but I don't know how to use it, thanks in advance
if you pass a classname to it you can target it after with css.
eg:
import "../styles.css";
export function ExampleeComponent() {
return (<Outline className="custom-outline" />);
}
styles.css
.custom-outline { color red; }

no-duplicate-selectors error for different selectors inside the same file

I am using stylelint within a CSS-IN-JS project (here using astroturf, but I face the same pattern using any CSS-IN-JS library such as styled-components as well).
I define different styled elements within the same file, and therefore sometimes end up having duplicated selectors and/or import rules.
/* style.js */
import styled from 'astroturf';
export const StyledComponentA = styled('div')`
transform: scale(0);
&.visible {
transform: scale(1);
}
`;
export const StyledComponentB = styled('div')`
opacity: 0;
/* -> stylelint error: Unexpected duplicate selector "&.visible" */
&.visible {
opacity: 1;
}
`;
Which I compose this way:
import React from 'react';
import { StyledComponentA, StyledComponentB } from './style';
export const Component = ({ isVisible }) => (
<StyledComponentA visible={isVisible}>
<StyledComponentB visible={isVisible}>Whatever</StyledComponentB>
</StyledComponentA>
);
Is there a way to set these stylelint rules on blocks instead of an entire file?
Is there a way to set these stylelint rules on blocks instead of an entire file?
There is not.
Rules like no-duplicate-selectors are scoped to a source and stylelint treats the following as sources:
entire files
code passed to the code option of the node API
stdin passed to the CLI
When writing CSS-in-JS, it might be advisable to turn off the rules scoped to sources. You can turn them off:
entirely in your configuration object e.g. "no-duplicate-selectors": null
on a case-by-case basis using command comments

Material-UI: "The key provided to the classes property is not implemented"

I am using the withStyles() HOC to override some MUI component styles, theme and breakpoints.
There is obviously something I do not understand here as I keep getting errors such as this one:
Warning: Material-UI: the key tab provided to the classes property
is not implemented in Items.
You can only override one of the following:
card,details,content,cover,avatar,lock
Example code: https://codesandbox.io/s/6xwz50kxn3
I have a <List /> component and its child <Items />.
My intention is to apply the styles in the demo.js file only to the <List /> component, and the styles in the demoChild.js to the <Items /> Component.
I would really appreciate an explanation of what I'm doing wrong, and maybe a solution?
Note: I have found other posts with the same error, but they seem to have something different to my example.
The warnings are caused by this line in your demo.js file:
<Items {...this.props} items={items} />
You're spreading all of List's props down into your Items. One of these props is classes, containing all of the CSS classes you define in demo.js. Since those are intended for List, they include CSS classes that are implemented by List but not Items. Since Items is receiving this prop, it's reading it as you trying to override classes that aren't available and warning you about it.
You can fix this problem by spreading only the unused props:
// Use other to capture only the props you're not using in List
const { classes, headerIsHidden, ...other } = this.props;
// Then spread only those unused props
<Items {...other} items={items} /
Then, you won't be spreading classes object into Items, so you won't get any warnings about classes that aren't implemented.
In my case, I want to reuse multiple styles in different files, so I wrote a helper function:
import { withStyles } from '#material-ui/core/styles'
// Fixed: material-ui "The key provided to the classes property is not implemented"
const withMultipleStyles = (...params) => {
return withStyles((theme) => {
var styles = {}
for (var len = params.length, key = 0; key < len; key++) {
styles = Object.assign(styles, params[key](theme));
}
return styles
})
}
export default withMultipleStyles
Usage:
import React from 'react'
import compose from 'recompose/compose'
import { connect } from 'react-redux'
import { style1, style2, withMultipleStyles } from '../../styles'
class your_class_name_here extends React.Component {
// your implementation
}
export default compose(
withMultipleStyles(style1, style2),
withWidth(),
connect(mapStateToProps, mapDispatchToProps)
)(your_class_name_here)

How to add style class and icon to TabContainerItem in openui5

How to add style class and icon to the TabContainerItem in openui5?
In TabContainerItem documentation there is no addStyleClass and icon properties which is possible in tabstrip by using tab title.
but I need to use TabContainerItem because it is having tabs menu which is useful in mobile device.
Can any one please help me
oTabContainer = new sap.m.TabContainer("tabContainer", {
items:
[
new sap.m.TabContainerItem({name: "tab1",
content: [
new sap.ui.core.mvc.JSView({id:"tab1",viewName:"oui5mvc.tab1"})
]}),
new sap.m.TabContainerItem({name: "tab2",
content: [
new sap.ui.core.mvc.JSView({id:"tab2",viewName:"oui5mvc.home"})
]}),
]
}).placeAt("content").addStyleClass("tabContainer");
Here is an example that i have tried.
Since sap.m.TabContainerItem inherits from Element directly and not from Control it does not offer addStyleClass.
However, you can still apply custom CSS to the TabContainerItem by adding a style class to the sap.m.TabContainer which targets its TabContainerItem children, like:
/* class tabContainer as your custom class added to the TabContainer */
/* custom TabContainerItem (selected) */
.tabContainer
.sapMTabStrip
.sapMTSTabsContainer
.sapMTSTabs
.sapMTabStripItem.sapMTabStripItemSelected {
color : green;
background : yellow;
}
/* custom TabContainerItem (unselected) */
.tabContainer
.sapMTabStrip
.sapMTSTabsContainer
.sapMTSTabs
.sapMTabStripItem {
color : white;
background : grey;
}
Here`s your adapted example. You can adjust this to your needs with basic CSS rules, then.
As far as I know, it is currently not supported to add an icon/image to the TabContainerItem. You can create a feature request for that on the issue tracker of the OpenUI5 project with the enhancement label or contribute it by yourself.

Build less #import url dynamically

While working on a google webfont import mixin, I noticed that it is not possible to build #import URLs dynamically.
.gFontImport (#name, #weights, #subsets) {
#url: "http://fonts.googleapis.com/css?family=#{name}:#{weights}&subset=#{subsets}";
#import url(#url);
}
Which can be narrowed down to
#url: "http://localhost/test.css";
#import url(#url);
Neither any of these additional tests work:
#import url("#{url}"); // this one renders at least
#import url(~"#{url}");
When the compiler renders the CSS file the #import URL is always left unchanged, e.g. "#{url}"
It seems to work in 1.4 beta.
1.4
Doing something like this (I tried it out at less2css.org) in LESS:
.gFontImport (#name, #weights, #subsets) {
#import url('http://fonts.googleapis.com/css?family=#{name}:#{weights}&subset=#{subsets}');
}
.gFontImport("Roboto+Slab",400,latin);
will have the expected output in CSS:
#import url('http://fonts.googleapis.com/css?family=Roboto+Slab:400&subset=latin');
<=1.3.3
If it does not work for you, you can use a workaround that injects the #import call into a selector name:
.gFontImport (#name, #weights, #subsets) {
#gimport: ~"#import url('http://fonts.googleapis.com/css?family=#{name}:#{weights}&subset=#{subsets}');";
#{gimport} some-selector {/* */};
}
so calling something like this in LESS:
.gFontImport("Roboto+Slab",400,latin);
will output this in CSS:
#import url('http://fonts.googleapis.com/css?family=Roboto+Slab:400&subset=latin');
some-selector {
/**/
}
This works, but it is a tiny bit messy. In a javascript implementation of LESS you can use
`'\n'`
and
`'\t'`
in the string interpolation to make it look a bit tidier.
I've made a gist with working mixins for both versions
https://gist.github.com/line-o/5568723
A working example, that defines font sets :
(with Less v1.7.3)
// Google font import mixin
.gFontImport (#name; #weights: 400; #subsets: latin) {
#nameEsc: ~`"#{name}".replace(/'([^']+)'/,'$1').replace(' ', '+')`;
#import url('http://fonts.googleapis.com/css?family=#{nameEsc}:#{weights}&subset=#{subsets}');
}
// Font sets
// The variable #post-fontset is dynamic (user input)
// ------------------
// foo1
.font(#fontset) when (#fontset = foo1){
.gFontImport('Roboto');
.gFontImport('Lato');
}
.font-text() when (#post-fontset = foo1){
font-family:Lato;
}
.font-headings() when (#post-fontset = foo1){
font-family:Lato;
}
.font-sitetitle() when (#post-fontset = foo1){
font-family:Roboto;
}
// foo2
.font(#fontset) when (#fontset = foo2){
.gFontImport('Oswald');
.gFontImport('Lato');
.gFontImport('Roboto Slab');
}
.font-text() when (#post-fontset = foo2){
font-family:'Roboto Slab';
}
.font-headings() when (#post-fontset = foo2){
font-family:Lato;
}
.font-sitetitle() when (#post-fontset = foo2){
font-family:Oswald;
}
// Using the mixins in the CSS
// ------------------
// This executes the font import mixin
.font(#post-fontset);
// Site title
h1{.font-sitetitle();}
// Heading
h2, h3, h4, h5, h6{.font-headings();}
// Text
body{.font-text();}