How to override external module class with css module pattern in react - css

I want to override a external module cssclass locally for a component
In my code
import `style` from './style.module.css' // this is local css module
import `ExternalComponent` from 'ExternalComponent' // suppose this is external module i'm using
function Component(){
return(
<ExternalComponent/>
)
}
Now the ExternalComponent render a div element with a class parent. So if i am importing the
ExternalComponent how can i override the parent class of ExternalComponent in my locally imported style module so that the style in the ExternalComponent change only for this component
only and else where i'm using it does not change.
I'm using react by the way.

style.module.css
.whatever-name-scope {
:global {
.parent {
// override here
}
}
}
Then your jsx goes:
function Component(){
return (<div className={style.whateverNameScope}>
<ExternalComponent/>
</div>)
}

Related

Can I use css modules in react class based components?

I have to implement css modules for some older React code. But when I try to import CSS modules, I canĀ“t use this class in another files.
Do I have to refactor the code to React Components? Or is there another easier solution?
Code example:
import styles from "styles.module.css"
var Greeting = createReactClass({
render: function() {
return <h1>Hello</h1>;
}
});
Yes, module CSS is also supported in class-based components.
In the module CSS you have to use CSS as an object,
For Example, You have a CSS class for an alert component
.alert{
color:red
}
then you can use it in components like this:-
import styles from "styles.module.css"
var Alert = createReactClass({
render: function() {
return <h1 className={styles.alert}>Hello</h1>;
}
});

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.

is there a way to add class from module css with variable? in react

see example below:
import React, { Component } from 'react';
import styles from './Button.module.css';
class Button extends Component {
let classNameVariable= "error-button"
render() {
return <button className={styles.classNameVariable}>Button</button>;
}
}
as you saw above example, I need to use variable instead of className, to add className.
so is there a way to do it?
Take a look at bracket notation: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Operators/Property_Accessors
Instead of styles.clasNameVariable make it styles[classNameVariable]

How to set path to a component image using style jsx tag in nextjs

I am using jsx to define styles for the NextJs components and i need to define a background image for some elements.
The only paths that seems to accept is the relative path, to the current page, or absolute path.
But how to pass a relative path to the component itself?
Here a simple component function for testing:
import React from 'react'
const TestComponent = (props) => {
return (
<div>
<h1 className="test">See my background</h1>
<style jsx>{`
.test {
background-image: url("someImageFile.jpg");
}
`}</style>
</div>
)
}
export default TestComponent
This will return the 404 error for url "localhost:3000/current page/someImageFile.jpg"
For a NextJS application, you should have a public folder at the root of the directory of your app where you store all the static files: such as images.
Here is a link to the official documentation where they explain it very clearly:
https://nextjs.org/docs/basic-features/static-file-serving
The trick is to use $ to be able to call require function:
<style jsx>{`
.test{
background-image: url(${require("./someImageFile.jpg")});
}
`}</style>
Reference documentation here.

How to import CSS file content into a Javascript variable

Consider a very simply custom element using shadow DOM:
customElements.define('shadow-element', class ShadowElement extends HTMLElement {
constructor() {
super();
this.styleTag = document.createElement('style');
this.styleTag.textContent= `
.root::before {
content: "root here!";
color: green;
}
`
this.shadow = this.attachShadow({mode: 'closed'});
this.root = null;
}
connectedCallback() {
this.root = document.createElement('div');
this.root.className = 'root';
this.shadow.append(this.root, this.styleTag);
}
})
<shadow-element></shadow-element>
To get the CSS into the shadow DOM, I create a style tag, which I append into the shadow root. This is all working fine so far.
Now for more complex CSS I would like to author it in a file shadow-element.css which is in the same folder as shadow-element.js. Besides seperation of concerns I also want IDE syntax highlighting and -completion for CSS authoring, so I really want the CSS in a separate, dedicated file.
I want to import the contents of that CSS file into a Javascript variable, like
import styles from './shadow-element.css'; // obviously doesn't work
On the project where this is being used we have a working webpack stack that allows importing CSS (and even SCSS), but unfortunately that imported CSS then becomes part of bundle.css - which obviously is not at all useful, because the element uses shadow DOM.
Does anyone have a solution to this? I'm also open to alternative solutions, as long it won't require me to author my CSS in a .js file.
Edit: I am aware of the option of using #import './shadow-elements.css'; inside the style tag, but I would much prefer a solution that bundles the imported CSS into my Javascript bundle (as part of the component code).
As you are using webpack, you can use raw-loader to import a text file (CSS in your case) into a string:
npm install raw-loader --save-dev
And you can use it inline in each file:
import css from 'raw-loader!./shadow-element.css';
customElements.define('shadow-element', class ShadowElement extends HTMLElement {
constructor() {
super();
this.styleTag = document.createElement('style');
this.styleTag.innerText = css;
this.shadow = this.attachShadow({mode: 'closed'});
this.root = null;
}
connectedCallback() {
this.root = document.createElement('div');
this.root.className = 'root';
this.shadow.append(this.root, this.styleTag);
}
})

Resources