"Unresolved variable" when using className={styles.nameOfClass} - css

I am attempting to change a button's style in ReactJS with the "className" element. However, I get back an error stating "Unresolved variable nameOfClass" in WebStorm, and the stylistic changes are not made when I run webpack and open the page on localhost. I have attempted different methods of importing the CSS file and naming conventions to no avail.
The file with the React Component class is here:
import * as React from "react";
var styles = require('./Roster.css');
export class Roster extends React.Component<{},{}> {
render() {
return (
<div>
<button className={styles.nameOfClass} type="button" >Players</button>
</div>
);
}
}
And the Roster.css file is here:
.nameOfClass {
background-color: #ff0000;
}
webpack.config.js
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "./dist/bundle.js",
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
externals: ['axios'],
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
loaders: [
// All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
{ test: /\.tsx?$/,
loader: "ts-loader"
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'),
}
],
preLoaders: [
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ test: /\.js$/, loader: "source-map-loader" }
]
},
plugins: [
new ExtractTextPlugin('styles.css', { allChunks: true })
],
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
"react": "React",
"react-dom": "ReactDOM"
},
};

You don't have to require the styles file.
import * as React from "react";
export class Roster extends React.Component<{},{}> {
render() {
return (
<div>
<button className="nameOfClass" type="button" >Players</button>
</div>
);
}
}
and your css file:
.nameOfClass {
background-color: #ff0000;
}

Should look something like:
import * as React from "react";
export class Roster extends React.Component<{},{}> {
render() {
return <div>
<button className="nameOfClass" type="button">Players</button>
</div>
}
}
You can't require css files, only typescript/javascript files.
There's the css-modules thing, and there are some js solutions for react/css, such as Radium and reactCss.

Related

TailwindCSS 3.0 Upgrade overriding button styles

Problem:
Button class being overridden by default tailwind base classes. Not sure why my classes on the element aren't being applied.
Question:
How can I get my styles to apply properly?
Screenshot:
As you can see background color on .documentCategory__row is being overridden by button, [type=button] on index.scss which is being defined within #tailwind/base.
/* index.scss */
:root {
--color-primary: #00a3e0;
--color-secondary: #470a68;
--color-success: #87d500;
--color-accent: #e87722;
/* Dark themes below */
--color-dark-primary: rgba(31, 41, 55, 1);
--dark-text: rgba(187, 193, 198, 1);
}
#import "tailwindcss/base";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
I'm not sure if this has to do with me switching to dart-scss so here is my webpack configuration in case I am missing something
import path from 'path'
import { Configuration as WebpackConfiguration, HotModuleReplacementPlugin } from 'webpack'
import { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
import HtmlWebpackPlugin from 'html-webpack-plugin'
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'
import ESLintPlugin from 'eslint-webpack-plugin'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
const CopyPlugin = require('copy-webpack-plugin');
interface Configuration extends WebpackConfiguration {
devServer?: WebpackDevServerConfiguration;
}
const config: Configuration = {
mode: 'development',
devServer: {
static: path.join(__dirname, 'build'),
historyApiFallback: true,
port: 4000,
open: true,
hot: true,
},
output: {
publicPath: '/',
},
entry: './src/index.tsx',
module: {
rules: [
{
test: /\.(ts|js)x?$/i,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'#babel/preset-env',
'#babel/preset-react',
'#babel/preset-typescript',
],
},
},
},
{
test: /\.(sa|sc|c)ss$/i,
use: [
'style-loader',
'css-loader',
'sass-loader',
{
loader: 'postcss-loader', // postcss loader needed for tailwindcss
options: {
postcssOptions: {
ident: 'postcss',
plugins: [tailwindcss, autoprefixer],
},
},
},
],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
loader: 'file-loader',
options: {
outputPath: '../fonts',
},
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
}),
new HotModuleReplacementPlugin(),
new CopyPlugin({
patterns: [
// relative path is from src
{ from: 'public/images', to: 'images' },
],
}),
// Add type checking on dev run
new ForkTsCheckerWebpackPlugin({
async: false,
}),
// Add lint checking on dev run
new ESLintPlugin({
extensions: ['js', 'jsx', 'ts', 'tsx'],
}),
],
devtool: 'inline-source-map',
};
export default config
If there are other files I am missing that are needed let me know!
without seeing what your index.tsx looks like I can only make a guess, but here's what caused this issue in our app:
in our index.tsx we were importing index.css after importing our component tree with import App from 'src/App. thus the css was loaded into the site in the wrong order. imports from components first (css modules, normal css imports), tailwind last.
go to your entry file (probably index.tsx) and try moving your import 'index.scss' line above importing the root component.
like this for example
/* index.tsx */
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'; // this file holds all tailwind styles
import { App } from 'src/App';
// ...
read more here:
https://github.com/tailwindlabs/tailwindcss/discussions/7304#discussioncomment-2256226
Even i faced the same issue but I am using Vue3 + element-ui-plus, after spending more than 6 hours my solution is to set :native-type='null':
<el-button type='primary' round #click='handleClick' :native-type='null'>Click Me</el-button>
but this is kinda "hack", this either need to be fixed by Tailwind or by element-ui team. Anyhow, for now enjoy ;)
And the discussion is on here
I got the same issue using tailwindcss v3 and NextUI, and button's background were "transparent". By adding type = {null}, to button's I solve the issue

Why scss module with typescript has .default property

When working with scss modules in typescript environment, my modules are stored in a property called default
Button.style.scss
.button {
background-color: black;
}
index.tsx
import * as React from 'react';
import * as styles from './Button.module.scss';
console.log(styles);
export const Button = () => (
<button className={styles.default.button}>Hello</button>
);
Console.log output
Module {__esModule: true, default: {button: "_2t432kRILm79F3WhLGdN6N"}, Symbol(Symbol.toStringTag): "Module"}
Why is that ? I cannot properly generate types with typed-scss-modules because of that.
EDIT:
Storybook config is
const path = require('path');
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.#(js|jsx|ts|tsx)'],
addons: ['#storybook/addon-links', '#storybook/addon-essentials'],
webpackFinal: async (config) => {
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader?modules=true', 'sass-loader'],
include: path.resolve(__dirname, '../'),
});
return config;
},
};
You need to adjust your css-loader rule to have the "esModule": false option, like follows:
{
loader: 'css-loader',
options: {
esModule: false,
}
},
{
loader: 'sass-loader',
}
This ensures import statements will return just the string, only

issue loading css module classes in storybook v6.4

I'm having trouble getting storybook to play nice with css modules within my Gatsby project. I'm able to render the button component but it does not add any of my styling. On inspection of the element, I'm only getting undefined undefined from the following code.
button.jsx
import React from "react"
import * as css from "./style.module.css"
const Button = ({ variant = "button", type, value = null }) => {
const baseOfVariant = () => {
if (variant === "input") {
return (
<input
type={type}
value={value}
className={`${css.button} ${css.clear_button}`}
/>
)
}
return (
<button type={type} className={`${css.button} ${css.submit_button}`}>
{value}
</button>
)
}
return baseOfVariant()
}
export default Button
button.stories.jsx
import React from "react"
import Button from "./button"
export default {
title: "Button",
component: Button,
}
export const Template = args => <Button {...args} />
export const ButtonRegular = Template.bind({})
ButtonRegular.args = {
variant: "button",
value: "Click Me",
type: "submit",
}
main.js
module.exports = {
stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.#(js|jsx|ts|tsx)"],
addons: ["#storybook/addon-links", "#storybook/addon-essentials"],
core: {
builder: "webpack5",
},
}
Storybook stuff in my devDeps
"devDependencies": {
"#babel/core": "^7.14.6",
"#babel/polyfill": "^7.12.1",
"#storybook/addon-actions": "^6.4.0-alpha.2",
"#storybook/addon-essentials": "^6.4.0-alpha.2",
"#storybook/addon-links": "^6.4.0-alpha.2",
"#storybook/addon-viewport": "^6.4.0-alpha.2",
"#storybook/builder-webpack5": "^6.4.0-alpha.2",
"#storybook/manager-webpack5": "^6.4.0-alpha.2",
"#storybook/react": "^6.4.0-alpha.2",
"babel-loader": "^8.2.2",
"prettier": "2.2.1",
"resize-observer-polyfill": "^1.5.1"
}
Gatsby needs to import css modules with the following synthax:
import * as css from "./style.module.css"
Where Storybook recognizes only this synthax:
import css from "./style.module.css"
This is due to the fact that Gatsby and Storybook don't use the same import convention. Fortunately, you can configure Storybook css module import mechanism via .storybook/main.js file.
const path = require("path")
module.exports = {
// You will want to change this to wherever your Stories will live
stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.#(js|jsx|ts|tsx)"],
addons: ["#storybook/addon-links", "#storybook/addon-essentials"],
core: {
builder: "webpack5",
},
webpackFinal: async config => {
// Prevent webpack from using Storybook CSS rules to process CSS modules
config.module.rules.find(
rule => rule.test.toString() === "/\\.css$/"
).exclude = /\.module\.css$/
// Tell webpack what to do with CSS modules
config.module.rules.push({
test: /\.module\.css$/,
include: path.resolve(__dirname, "../src"),
use: [
{
loader: "style-loader",
options: {
modules: {
namedExport: true,
},
},
},
{
loader: "css-loader",
options: {
importLoaders: 1,
modules: {
namedExport: true,
},
},
},
],
})
// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]
// use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
config.module.rules[0].use[0].options.plugins.push(
require.resolve("babel-plugin-remove-graphql-queries")
)
return config
},
}
With the above configuration, Storybook now accept this import synthax and button.jsx is correctly styled.
import * as css from "./style.module.css"
If any one is looking for sass/scss related fix
import * as style from "./style.module.scss"
Where Storybook recognizes only this synthax:
your .storybook/main.js file.
const path = require("path");
module.exports = {
stories: ["../src/**/*.stories.{js,mdx}"],
addons: [
"#storybook/addon-docs",
"#storybook/addon-actions",
"#storybook/addon-controls",
"#storybook/addon-a11y",
"#storybook/addon-viewport",
],
// https://gist.github.com/shilman/8856ea1786dcd247139b47b270912324
core: {
builder: "webpack5",
},
webpackFinal: async config => {
// https://www.gatsbyjs.com/docs/how-to/testing/visual-testing-with-storybook/
config.module.rules.push({
test: /\.(js)$/,
use: [
{
loader: require.resolve("babel-loader"),
options: {
presets: [
// use #babel/preset-react for JSX and env (instead of staged presets)
require.resolve("#babel/preset-react"),
require.resolve("#babel/preset-env"),
],
plugins: [
// use #babel/plugin-proposal-class-properties for class arrow functions
require.resolve("#babel/plugin-proposal-class-properties"),
// use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
require.resolve("babel-plugin-remove-graphql-queries"),
// use babel-plugin-react-docgen to ensure PropTables still appear
require.resolve("babel-plugin-react-docgen"),
],
},
},
],
exclude: [/node_modules\/(?!(gatsby)\/)/],
});
config.module.rules.push({
test: /\.s[ac]ss$/i,
oneOf: [
// module.scss files (e.g component styles.module.scss)
// https://webpack.js.org/loaders/style-loader/#modules
{
test: /\.module\.s?css$/,
use: [
// Add exports of a module as style to DOM
{
loader: "style-loader",
options: {
esModule: true,
modules: {
namedExport: true,
},
},
},
// Loads CSS file with resolved imports and returns CSS code
{
loader: "css-loader",
options: {
esModule: true,
modules: {
namedExport: true,
},
},
},
// Loads and compiles a SASS/SCSS file
{
loader: "sass-loader",
// only if you are using additional global variable
options: {
additionalData: "#import 'src/styles/global.scss';",
sassOptions: {
includePaths: ["src/styles"],
},
},
},
],
},
// scss files that are not modules (e.g. custom.scss)
{
use: [
// Add exports of a module as style to DOM
"style-loader",
// Loads CSS file with resolved imports and returns CSS code
"css-loader",
// Loads and compiles a SASS/SCSS file
{
loader: "sass-loader",
// only if you are using additional global variable
options: {
additionalData: "#import 'src/styles/global.scss';",
sassOptions: {
includePaths: ["src/styles"],
},
},
},
],
},
],
});
return config;
},
};
With the above configuration, Storybook now accept this import synthax and button.jsx is correctly styled.
import * as styles from "./style.module.scss"

Svelte: Is there a way to make global css variables in scope of svelte components?

I have set my global.css file which I import in index.js
--root {
--main-color: red;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
index.js
import "./global.css";
import App from "./App.svelte";
const app = new App({
target: document.body
});
My webpack setup
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.(html|svelte)$/,
exclude: /node_modules/,
use: {
loader: "svelte-loader",
options: {
emitCss: true,
hotReload: true
}
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: { loader: "style-loader", options: { sourceMap: true } },
use: [
{ loader: "css-loader", options: { sourceMap: true } },
{
loader: "postcss-loader",
options: {
sourceMap: true,
ident: "postcss",
plugins: loader => [
require("postcss-import")({}),
require("postcss-preset-env")(),
require("cssnano")()
]
}
}
]
})
}
]
},
plugins: [new HtmlWebpackPlugin(), new ExtractTextPlugin("styles.css")]
};
Works perfect for setting up global css for the entire app. But I am trying to use the --main-color in my svelte components. Is there a way to inject them down to all the components' css ?
Since I import global.css first, it should work as it emits a file with --root{} first then rest of the component styles.
You can place global styles under /routes/index.svelte file, like the example below:
<style>
:global(:root){
--header-color: purple
}
</style>
And simply use it anywhere like normally how you use CSS variables like so:
h1 {
color: var(--header-color);
}
I was busy with this, trying different webpack settings etc., seeing that the output css should work, I just could not find why it did not work. I wrote the post before trying for one last time, which wasted another hour. I finally found the error.
Instead of using :root{} I have mistyped it --root{}. I have posted it anyways, in case someone is stuck with the same mistake.

Css is not used by jsx in ReactJS

I use ReactJS with Webpack and TypeScript.
I'm trying to include CSS with React. But my CSS is not use by my React application.
I created a global.d.ts file to declare my css module. I imported my css into my.tsx file but when I add a class to an element, nothing works.
I have already tried to install a css module but I didn't succeed. So, I just made the solution to create a global.d.ts file
global.d.ts :
declare module '*.css';
Hello.tsx
import * as css from './Hello.css';
export interface HelloProps {
compiler: string;
framework: string;
}
export class Hello extends React.Component<HelloProps, {}> {
render() {
return (
<form>
<p className={css.test}> Test </p>
</form>
);
}
}
Hello.css
.test {
color: red;
}
webpack.config.js
module: {
rules: [
.....
{ test: /\.css$/, exclude: /node_modules/, use: ['style-loader', 'css-loader'] }
]
},
The word "test" is written in black.
When it should be in red
This would be due to you not having modules set to true in your css-loader options.
// webpack.config.js
rules: [
{
test: /.css$/,
exclude: /node_modules/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
],
Also, i would just do the following as there's no need for the * import.
import css from './Hello.css'
and then in your jsx:
<Component className={css.test} />
im quite new to react but i think if you remove:
"import * as css from './Hello.css';" And Replace it with "import './Hello.css';"

Resources