Specificity issue with "composes" keyword using CSS Modules and React - css

I'm having CSS specificity/import order issues when trying to use CSS modules "composes" keyword.
File structure:
|_ MyComponent.jsx
|_ MyComponent.scss
|_ utilities.scss
MyComponent.jsx
import React from 'react';
import styles from './MyComponent.scss';
const MyComponent = ({ error }) => {
const classes = classnames(
styles.root,
{
[styles.error]: error
}
);
};
export default MyComponent;
MyComponent.scss
.root {
color: #333;
}
.error {
composes: red from './utilities.scss';
}
utilities.scss
.red {
color: red;
}
As you can see in the screenshot below, the .red class is not applying because of an import order issue. Is there a way around this without resorting to something like !important?
Note: I'm using CSS modules with webpack + scss loader.

Related

Override default getstream component styles into NextJS Component

How can I override the getStream.io components css with custom css ? I have create the component as below and I need to override the css for the various classes of it's components.
As per this README documentation I have import the css file into my Next.JS component and then write my custom css of their component into the /public/style.css file but it is not applying any how.
import React from 'react';
import { StreamChat } from 'stream-chat';
import { Chat, Channel, ChannelHeader, MessageInput, MessageInputSmall, VirtualizedMessageList, Window } from 'stream-chat-react';
import 'stream-chat-react/dist/css/index.css';
const chatClient = StreamChat.getInstance(process.env.GET_STREAM_KEY);
const userToken = process.env.GET_STREAM_TOKEN;
chatClient.disconnectUser()
chatClient.connectUser({id: userId}, userToken);
const channel = chatClient.channel(process.env.TYPE, process.env.ROOM);
const ChatComponent = () => (
<Chat client={chatClient} theme='livestream dark'>
<Channel channel={channel}>
<Window>
<ChannelHeader live />
<VirtualizedMessageList />
</Window>
</Channel>
</Chat>
);
export default ChatComponent;
I have written the below css into style.css file to override the css of the components but below css are not applying.
.str-chat-channel {
max-height: 150px;
}
.str-chat__virtual-message__wrapper {
padding: 10px 40px 10px 15px;
}
.str-chat__virtual-message__wrapper {
align-items: center;
}
.str-chat__virtual-message__wrapper .str-chat__avatar--rounded {
border-radius: 25px;
}
You should move your stream-chat-react global CSS import to your custom _app file then import your own styles.css after it.
// pages/_app.js
import "stream-chat-react/dist/css/index.css";
import "<your-path-to>/style.css"; // Replace with the path to your `style.css`
// ...

Import font into React application

I'm trying to use the Roboto font in my app and having tough time..
I did npm install --save typeface-roboto and added import 'typeface-roboto' to my React component. But still can't get my font to change.
I am trying to do like this :
const React = require('react')
import 'typeface-roboto'
class Example extends React.Component {
render() {
let styles = {
root: {
fontFamily: 'Roboto'
}
}
return (
<div style={styles.root}>
<p>
This text is still not Roboto ?!???!!1
</p>
</div>
)
}
}
module.exports = Example
Am I missing something? Looking for a simple way to do this without any external css file..
Try adding import 'typeface-roboto'; in root file i.e. index.js file.
In my case I added font-family to body element and it is worked.
import this code of line in your main css or scss whatever use use
#import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap');
this will work.
If you want to customize this then go to the google font and select font style font weight whatever you want.
Here i have selected font weight 400,300 and 700
If have not selected the font weight then you can not use other font weight
I had the same issue, couldn't get Roboto fonts for my components anyhow.
I used the webfontloader package.
yarn add webfontloader
or
npm install webfontloader --save
h
Once you do this, add the following code to your index.js or to the JS file which is an entry point to your application
import WebFont from 'webfontloader';
WebFont.load({
google: {
families: ['Titillium Web:300,400,700', 'sans-serif']
}
});
// rest of the index.js code
And now apply the font-family.
You simply just require('typeface-roboto') it.
const React = require('react')
require('typeface-roboto')
class Example extends React.Component {
render() {
let styles = {
root: {
fontFamily: 'Roboto'
}
}
return (
<div style={styles.root}>
<p>
This is now Roboto
</p>
</div>
)
}
}
// or here instead if you fancy
.root {
font-family: 'Roboto';
}
It involves several changes, assuming you want to use CSSinJS:
change style to className
You'll need some kind of library to apply styles.
With react-jss
import React from 'react';
import 'typeface-roboto';
import injectSheet from 'react-jss';
const styles = {
root: {
fontFamily: 'Roboto',
},
};
class Example extends React.Component {
render() {
return (
<div className={styles.root}>
This text is Roboto
</div>
)
}
}
const StyledExample = injectSheet(styles)(Example)
export default StyledExample;
Or with MaterialUI styles:
import React from 'react';
import 'typeface-roboto';
import { withStyles } from '#material-ui/core/styles';
const styles = theme => ({
root: {
fontFamily: 'Roboto',
},
});
function Example(props) {
const { classes } = props;
return (
<div className={classes.root}>
This text is Roboto
</div>
);
}
export default withStyles(styles)(Example);
Or, you could just do it the right way, via Dan's Answer
Or the Styled-Components way:
import styled from 'styled-components'
const ExampleStyled = styled.div`
#font-face {
font-family: 'Roboto';
src: local('Roboto'), url(fonts/Roboto.woff) format('woff');
}
`
const Example = () => (
<ExampleStyled>
This text is Roboto!
</ExampleStyled>
);
export default Example;

StencilJS Component Styles

What is the proper way to use the styles option/property of the ComponentDecorator? Using the styles property with the default my-name component from the repository stencil-component-starter doesn't seem to affect the styles of the respective component nor generate something like a <style> tag in the <head>. How is styles intended to work? Or has it not been implemented yet? If the goal is to avoid having a separate CSS asset that needs to be loaded, but provide styles for the component, would styles be the right choice or is there another property such as host would need to be used?
Below is a sample component generated from the stencil-component-starter]1 with stylesUrl #Component property replaced with a styles property and setting font-size property. No errors are generated during dev or build tasks.
import { Component, Prop } from '#stencil/core';
#Component({
tag: 'my-name',
styles: `my-name { font-size: 24px; }`
})
export class MyName {
#Prop() first: string;
render() {
return (
<div>
Hello, my name is {this.first}
</div>
);
}
}
ComponentDecorator is defined as:
export interface ComponentOptions {
tag: string;
styleUrl?: string;
styleUrls?: string[] | ModeStyles;
styles?: string;
shadow?: boolean;
host?: HostMeta;
assetsDir?: string;
assetsDirs?: string[];
}
Thank you for any help you can provide!
I just tried with latest version 0.0.6-22, and it seems to work completely now.
While compiling, it will tell you if your styles contents is valid or not (mainly looking for valid selectors).
Here is a working example (with a simple string):
import { Component, Prop } from "#stencil/core";
#Component({
tag: "inline-css-example",
styles: 'inline-css-example { font-size: 24px; }'
})
export class InlineCSSExampleComponent {
#Prop() first: string;
render() {
return <div>Hello, my name is {this.first}</div>;
}
}
This one works too, with ES6 Template Strings (just showing multiline):
import { Component, Prop } from "#stencil/core";
#Component({
tag: "inline-templatestring-css-example",
styles: `
inline-templatestring-css-example {
font-size: 24px;
}
`
})
export class InlineCSSExampleComponent {
#Prop() first: string;
render() {
return <div>Hello, my name is {this.first}</div>;
}
}
(EDITed to show evolution since 0.0.6-13)

How to use custom component variable in custom component stylesheet?

Let's say I have a custom component - WoodComponent (/src/components/wood/wood.ts):
import { Component } from '#angular/core';
#Component({
selector: 'wood',
templateUrl: 'wood.html'
})
export class WoodComponent {
color: string = 'brown';
constructor() {}
}
How would I use the color variable in the component's stylesheet (/src/components/wood/wood.scss)? E.g.:
wood {
.wood-selected {
background-color: color($colors, [color variable from component]);
}
}
Thanks!
You need to declare brown inside variables.scss file and then use as shown below.
variables.scss
colors: ( primary: #488aff, brown: brown);
.scss
wood {
.wood-selected {
background-color: color($colors, brown);
}
}

React: Inline CSS modules in JSX with Webpack

I have a minimal React component which consists of two files: button.jsx and button.less. The styles are imported and the class names are appended with a hash to make all styles local to the component.
This is great, but i'd like to have all component code in one file. Is it possible to inline the styles in jsx file without losing css modularity?
Current Code
button.jsx
import React from 'react';
import styles from './button.less'
export default class Button extends React.Component {
render() {
return <button className={styles.primary}>{this.props.text}</button>;
}
}
button.less
#import '~semantic-ui/src/definitions/elements/button.less';
.common {
composes: ui button;
}
.primary {
composes: common primary;
}
webpack.config.js (relevant bits)
module: {
loaders: [
{
test: /\.jsx$/,
loader: 'babel'
},
{
test: /\.less$/,
loader: "style!css?modules&importLoaders=1!less"
}
]
},
What i'd like to write instead
button.jsx
<style lang="less" modules>
#import '~semantic-ui/src/definitions/elements/button.less';
.common {
composes: ui button;
}
.primary {
composes: common primary;
}
</style>
import React from 'react';
export default class Button extends React.Component {
render() {
return <button className={styles.primary}>{this.props.text}</button>;
}
}
Inspired by vue.js and vue-loader.
I believe this is a duplicate of this unanswered question:
Using css-loader inline with Webpack + React
I wrote a Webpack loader for this very purpose:
https://github.com/chrisdavies/stylextract-loader
It allows you to write a single style tag per JSX file and it supports webpack CSS modules, too, if you want.
At build time, it extracts the rules from your style tag and moves them out to an external CSS file.
I should note that because it simply extracts your rules out to an external CSS file, it plays nice with SASS, autoprefixer, etc
You can use callback-loader for this. This is actualy a workaround, but it do the trick. Just implement a callback which will extract your css-code and replace it with appropriate import. For example:
webpack.config.js
var fs = require('fs');
var cssIndex = 0;
// Do not forget to create and clean temporary folder "cssTemp" before
var webpackConfig = {
...
resolve: {
alias: {
cssTemp: path.resolve('./cssTemp')
}
},
module: {
loaders: [
{ test: /\.jsx$/, loader: "callback!babel" }
]
},
callbackLoader: {
cssCallback: function(code) {
var filename = cssIndex + '.less';
cssIndex++;
// Save the css code from the callback argument
fs.writeFileSync('./cssTemp/' + filename, code);
// Return the import statement which will replace the callback statement
return 'import styles from "cssTemp/' + filename + '";';
}
}
...
};
button.jsx
import React from 'react';
cssCallback(`
#import '~semantic-ui/src/definitions/elements/button.less';
.common {
composes: ui button;
}
.primary {
composes: common primary;
}
`);
export default class Button extends React.Component {
render() {
return <button className={styles.primary}>{this.props.text}</button>;
}
}

Resources