Shorter way to use SCSS #exported classNames in React (Next.js + css-modules) - reactjs

I have a set of semantic color classes in SCSS, which should be applied to components based on their props. I'm using React + Next.js + css-modules.
What I Want:
The current code I wrote below works correctly, but I want a simpler approach... declaring a bunch of classNames for every component to #extend something else is overkill! I want to write the extension directly in jsx part. Is there a better (more dynamic) way to do this? maybe inline extends?
Not a valid code, but I'm looking for something like this:
export default function Component({ status }) {
return (
<div style={#extend %{status}}>
...
</div>
)
}
Code
This is the semantics file. I import it inside other scss files to extend the classes:
/* _semantics.scss */
%warning {
background: orange;
color: red;
}
%error {
background: red;
color: black;
}
...
Example Component
/* component.module.scss */
#use "semantics" as *;
.warning {
#extend %warning;
}
.error {
#extend %error;
}
.success {
#extend %success;
}
// component.jsx
import css from "./component.module.scss"
export default function Component({ status }) {
return (
<div className={css[status]}>
...
</div>
)
}
// index.jsx
<Component status="warning">...</Component>
Notes
I am looking for an alternative way, so:
Using a package is fine
Using #include (mixins) instead of #extend is fine
Using .semantic-class instead of %semantic-class is fine

you can use global css to achieve this purpose

Related

Angular using wrapper component for primeng p-inputnumber not able to style

I am new to PrimeNg with Angular. I have a simple primeng p-inputnumber component as below:
<p-inputNumber
[showButtons]="true"
[placeholder]="placeholderText"
incrementButtonIcon="fal fa-plus"
decrementButtonIcon="fal fa-minus"
[minFractionDigits]="_config?.integer ? 0 : 1"
[min]="_config?.minValue"
[max]="_config?.maxValue"
[(ngModel)]="value"
(onBlur)="onBlur()">
</p-inputNumber>
And have created a wrapper to this component i.e is the wrapper to the above component and using it in a homepage component. Now i want to apply style to this wrapper component which in turn should apply style to primeng component. Right now it is not setting.
Homepagecomponent.html
---<app-number-input class="disabled">
------<p-inputNumber>
i set the below style in homepagecomponent.scss
:host ::ng-deep .disabled {
background: red;
}
But the above is not being set. Can anyone help me how to achieve my expected?
Thanks
You would need something like this in your CSS
:host ::ng-deep {
// you may want to specify your app element or something here to be more specific than just .disabled class
.disabled {
// tweak this list to whichever pieces of the p-inputnumber you want to have red background
.p-inputnumber,
.p-inputnumber-stacked,
.p-inputnumber-horizontal,
.p-inputnumber-vertical,
.p-inputnumber-input,
.p-inputnumber-button,
.p-inputnumber-button-up,
.p-inputnumber-button-down,
.p-inputnumber-button-icon {
background-color: red;
}
}
}

Using nested pseudo css selectors with react-emotion

Running on a strange problem.
Following are two blocks of code. One of them works well and another just don't.
This work
const StyledButton = styled('button')`
// Some styles here
:first-child {
// Some other styles
}
:first-child:after {
content: 'F';
}
`
// After get applied succesfully to the first child
This doesn't
const StyledButton = styled('button')`
// Some styles here
:first-child {
// some other styles
:after {
content: 'F';
}
}
`
// After get applied to all nth child.
I'm using react-emotion.
Is this behavior intended or am I missing something? I want to achieve that :after should get applied to first-child only by using a similar approach to the second one.
I think there's an error in the code on the nested :after
The change that would, if I'm correct, solve your issue it to change the nested :after to &:after like so:
const StyledButton = styled('button')`
// Some styles here
&:first-child {//<====== note the & here
// some other styles
&:after { //<====== note the & here
content: 'F';
}
}
}
The & is a placeholder for the parent selector, thus the code above will compile to:
button:first-child {
// some other styles
}
button:first-child:after {
content: 'F';
}
EDIT: Sandbox with working example
Hope this helps!
`

Overwriting global CSS style in modules is not working

I'm having a problem with overwriting CSS styles using composing in modules.
My current setup:
I have a thirdparty grid library file which I insert into my application in the entry JS file:
import './css/thirdparty/file.css';
I'm also using CSS modules for my components like this:
import styles from './component.module.css';
const Component = () => {
// component code omitted
// in render
<div className={styles.col14}></div>
In webpack config, I have two rules setup to load the file.css using plain css-loader and the *.module.css files using css-loader with modules.
All of these files are loaded correctly and the styles are all present. Here's the problem:
file.css contains:
.col-1-4 /* and all other col-1-* variations*/ {
float: left;
min-height: 1px;
padding-right: 20px;
}
.col-1-4 {
width: 25%;
}
component.module.css contains:
.col14 {
composes: col-1-4 from global;
padding-right: 0;
}
Current output of the component:
<div class="col14__3bA8W col-1-4">
So the style is supposedly overwritten, but what I see in the browser is that the padding-right is still 20px. It seems to only happen when I try to compose from a global style, because if I compose two classes from the same component CSS file, it works as expected.
Does anyone know why this is not working?
You can try with
.col14 {
composes: col-1-4 from global;
padding-right: 0!important;
}

how to use common less variable with styled component?

Say I have a styled component, in index.jsx
import './index.less';
class Input extends React.Component {
...
}
and my index.less files looks:
.input{
color: #whiteColor;
}
This index.less has to work with the mixin.less that imported in the root project.
So my question is, even though I imported the mixin.less, it prompts variable #whiteColor not found. Any idea to solve this?
I have felt the same pain, why isn't my styled component resolving less variables?
The syntax is simple JavaScript, just do:
.input{
color: ${props => props.whiteColor};
// or
color: ${props => props.theme.whiteColor};
}
But, at my company, we had thousands of less components, and we really thought that the less syntax was cleaner and definitely faster to write. We developed Styless.
It is a babel plugin that parses less and generates javascript code. Add it to your .babelrc file.
{
"plugins": ["babel-plugin-styless"]
}
Then, we can do!!
const Input = styled.input`
#highlight: blue; // can be overwritten by theme or props
background: darken(#highlight, 5%); // make green darken by 5%
`;
Check here to see how to use the theme provider and load variable from your index.less!
You can try import the mixin.less in index.less
I have been trying the same than you.
But then I thought.. it is that what I really want? Because styled-components propose a different approach to having a modular structure for your styles.
https://www.styled-components.com/docs/advanced Check theming, is amazing powerful.
Because in styled components you define the variables with javascript.
And if you want color manipulation like less, sass, you can check https://github.com/erikras/styled-components-theme
Its like forgetting about less, and sass and moving it to a new style modules.
Still, if you want to keep your defined style classes, you can do that:
class MyComponent extends React.Component {
render() {
// Attach the passed-in className to the DOM node
return <div className={`some-global-class ${this.props.className}`} />;
}
}
Check the existing CSS usage from docs:
https://www.styled-components.com/docs/advanced#existing-css

Global Utility Classes with PostCSS / CSS Modules

Using CSS Modules, how can I apply a global utility class to multiple elements without duplicating the style declaration?
For example, here is a React component without CSS Modules. The relevant line is the div with two classes: widget and clearfix...
/* components/widget.jsx */
class Widget extends Component {
render() {
return (
<div className="widget clearfix">
<div className="widget-alpha">Alpha</div>
<div className="widget-beta">Beta</div>
</div>
);
}
}
.clearfix is a global utility class that I want to apply to many elements throughout my app:
/* util/clearfix.scss */
.clearfix {
&:before, &:after { content: " "; display: table; }
&:after { clear: both; }
}
I've seen various ways of importing .clearfix into a CSS Module, but in each case the style declarations are redefined for each occurrence where the class is applied. Here's one example:
/* widget.scss */
.widget {
// other styles
composes: clearfix from '../util/clearfix.scss';
}
Through trial and error, I found that you can declare :global in the selector where the utility class is employed (not where it's defined):
.widget {
// other styles
:global {
composes: clearfix;
}
}
To avoid messy and repetitive import and from statements, I used an index.scss file to import the utility files and then import that in any partial where a utility class is needed.

Resources