Load mantine styles after Tailwind preflight - reactjs

I'm trying to use Mantine and Tailwind together, however Tailwind's "preflight" base styles are overriding Mantine's resulting in a simple button being invisible.
You can disable preflight:
corePlugins: {
preflight: true
}
But I'd rather keep it enabled and load Mantine CSS after, per this suggestion.
Is there any way to specify order for this?

Create an Emotion cache using createEmotionCache from Mantine core, and set prepend to false. Then, call it inside MantineProvider's emotionCache prop:
import {
MantineProvider,
createEmotionCache
} from '#mantine/core';
const myCache = createEmotionCache({
key: 'mantine',
prepend: false
});
<MantineProvider emotionCache={myCache}>{children}</MantineProvider>

Two steps:
Add preflight: false in tailwind.config.js to disable the default
Copy out https://unpkg.com/tailwindcss#3.2.4/src/css/preflight.css refereed by https://tailwindcss.com/docs/preflight and import it in your entry point

So, in your global stylesheet where you imported the tailwind styles remove the base styles as they will override some mantine styles. It should look like this
#tailwind components;
#tailwind utilities;

Related

Dynamically changing Less variables in React Gatsby app with Ant Design at runtime

We are building a White Label platform using React, GatsbyJs and Ant Design. We are stuck with Gatsby and Ant Design because we are migrating from an existing system and changing any of those would bring huge impact. Also, we must have a single deploy. Having a build for each White Label is not an option.
So, we need to be able to change style (mainly color) at runtime.
The problem is: Ant Design uses less variables to define it's themes and we're not able to change them at runtime, not even with less's modifyVars.
The thing is we MUST change less variables, and not global CSS or use other means
Ant Design derivates the main variables many times to get adjacent properties. So, for instance, if we define #primary-color as red, when we add a Button to the screen, Ant Design also defines it's border color, hover color, and many other details with different shades of red.
This means that, if we were to use other styling tool, we would need to generate those color derivations and replace every little property for every component. This would be chaos.
Scenario
We are using gatsby-plugin-antd and gatsby-plugin-less to load less and change vars at build time. Our gatsby-config.js looks like this:
module.exports = {
siteMetadata: {
siteUrl: 'https://www.yourdomain.tld',
title: 'yourtitle'
},
plugins: [
'gatsby-plugin-root-import',
'gatsby-plugin-typescript',
{
resolve: 'gatsby-plugin-antd',
options: {
style: true
}
},
{
resolve: 'gatsby-plugin-less',
options: {
lessOptions: {
javascriptEnabled: true,
modifyVars: {
'primary-color': '#FFFFFF',
'link-color': '#000000',
'success-color': '#FFFFFF',
'warning-color': '#000000'
}
}
}
}
]
};
We import styling in our gatsby-browser.js file:
import './src/styles/index';
Our styles/index has:
import 'tachyons';
import './global.css';
import './antd.less';
antd.less:
#import '~antd/dist/antd.less';
And global.css has some general CSS for the project.
It's working fine with the defined variables at build time.
What we attempted so far...
We have tried out this plugin:
https://github.com/mzohaibqc/antd-theme-webpack-plugin
Which supposedly does exactly what we need. But there's no example using Gatsby.
We then tried to add the plugin using the gatsby-node.js as mentioned here:
https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/
First, we tried using index.html as the indexFileName for the pluggin. It just doesn't work.
Then, following the plugin docs, we tried using indexFileName as false and importing the following scripts using Helmet at our pages/index.tsx:
<script> window.less = { async: false, env: 'production' };
</script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js"></script> ```
Also didn't work. If we define indexFileName as false, we get memory over the heap.
If we keep indexFileName as 'index.html' and just add the scripts, we are able to call window.less.modifyVars and it returns successfully (we are logging the Promise's then and error) but it doesn't affect antd's variables.
We then tried doing something similar, but instead of loading less externally, we installed it as a node_module and imported it to the file and used it directly in a similar fashion. Got the same result: modifyVars runs and returns successfully but doesn't affect antd.
Then, we tried something a bit different: we removed gatsby plugins and tried importing less from antd directly, as suggested here:
https://ant.design/docs/react/customize-theme
So we imported it like this:
#import '~antd/lib/style/themes/default.less';
#import '~antd/dist/antd.less';
#import 'your-theme-file.less';
Also, no good. It's different from the previous scenario, because style gets updated after you save your code. No need to stop Gatsby, as the first solutions. But, modifyVars still has no affect on antd components.
Then, to isolate the issue, we tried to style a basic HTML component - a button - to check if the issue was with gatsby or antd. And... still no success. less.modifyVars didn't work to change a basic button style on runtime.
So, we think it's probably something between Gatsby and Less. We checked gatsby-plugin-antd and gatsby-plugin-less to see if we could find something, but found nothing useful.
We assume that the "less instance" or "less context" used by gatsby's less-loader during build time is not the same we are calling modifyVars on. So it doesn't affect the original vars.
Totally stuck. Please, help!
EDIT - SOLUTION
Ant Design team has just released - TODAY - a new alpha version that includes dynamic theming, using CSS Variables.
https://ant.design/docs/react/customize-theme-variable
It works fine, so far. Closing the issue.
EDIT 2
There's a more detailed solution on the accepted answer.
Ant Design team has just released - TODAY - a new alpha version that includes dynamic theming, using CSS Variables.
https://ant.design/docs/react/customize-theme-variable
It works fine, so far.
EDIT - Detailed solution
I removed gatsby-plugin-antd and gatsby-plugin-less from the project. Also removed the import of antd less file.
Instead, in my styles/index.tsx (which is imported in gatsby-browser.js), I'm importing the variables.min.css file:
import 'antd/dist/antd.variable.min.css';
Then, whenever I want to change Ant Design variables, I just use:
import { ConfigProvider } from 'antd';
...
ConfigProvider.config({
theme: {
primaryColor: '#[DESIRED_COLOR_HEX]'
}
});
Provider
Since this has to be done every time the site is loaded, I'm creating a ThemeProvider that wraps every page and defines the theme. It fetches theme data from the backend and sets Ant Design theme variables.
Example code:
import { Spin } from 'antd';
import React, { useEffect, useState } from 'react';
import { ConfigProvider } from 'antd';
import { Theme } from './theme.interface';
interface Props {
children: React.ReactNode;
}
export const ThemeProvider = ({ children }: Props): JSX.Element => {
const [themeVars, setThemeVars] = useState<Theme>(null);
useEffect(() => {
async function fetchMyAPI() {
const result = await getThemeFromBackend(); // Make API call with Axios
if (result) setThemeVars(result);
}
fetchMyAPI();
}, []);
useEffect(() => {
if (themeVars) {
ConfigProvider.config({
theme: {
primaryColor: `#${themeVars.primaryColor}`
}
});
}
}, [themeVars]);
return <div>{!themeVars ? <Spin size="large" /> : <>{children}</>}</div>;
};
And it can be used like this:
...
<ThemeProvider>
<h1>My page header</h1>
<p>Page content...</p>
</ThemeProvider>
...
Note: You can save theme data on local storage for performance improvement, so you don't have to call your backend everytime your site reloads. Maybe you'll just have to refresh it from time to time.

How to use a sass $ declaration in useEffect (jsx?)

I have different styles set in a _variables.scss file. like
$secondary: #ffc500;
$tertiary: #ffdd69;
$quartiary: #fffbed;
I want to use different body colors so I want to change the body background in different pages like so:
document.body.style.backgroundColor = "red" });
this works nicely but now i want to use for example $primary instead of 'red'
I just can't make it work. does anybody have an idea?
You can use the sass :export keyword to pass variables from sass files to js files:
// colors.scss
$primary: #123456;
:export {
primary: $primary;
}
// main.js
import colors from './colors.scss'
colors.primary; // '#123456'
As far as I know this is a non-standard keyword, it is handled by webpack + sass-loader, but not all sass transpilers.

how to import css file in react when generating static html and inject imported css into html head tag?

I am trying to generate static html from react using renderToStaticMarkup method. The problem I am facing right now is that I am not able to import css into react component. I want to import css in my React components like css-modules (import styles from './style.css'). And then inject that loaded css into generated static html head. How can I accomplish that?
P.S. I can't use webpack due to some constraints. If there is any babel plugin availabe for this specific case, then please let me know.
Here is how I am generating static html from react component:
const reactElement = require('react').createElement;
const ReactDomServer = require('react-dom/server');
const renderHTML = Component => {
return ReactDomServer.renderToString(reactElement(Component))
}
You can pass a URL in as a prop and render a <link/> tag. Made an example here, not sure if that would meet your needs or if you need it to be a style tag.
This may be challenging without a lot of custom logic.
If you want to inline the CSS only for the initial render and then fetch the rest after the initial render, styled-components may be a better option because it supports exactly what you're trying to achieve without too much configuration: https://www.styled-components.com/docs/advanced#server-side-rendering
May be I am too late you can also create It like this way.
React.createElement("style", {},[ "body {background-color: powderblue;}
h1 {color: blue;}
p {color: red;}" ])
Output:
<style>
body {background-color: powderblue;}
h1 {color: blue;}
p {color: red;}
</style>
Since createElement take 3 params and last one is children we can put our vanila css inside it as a children. You can put any imported file in the form of string and it will convert to style tag

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

How do I apply custom CSS to Modal dialog - React-bootstrap

I am new to React here and I am trying to apply CSS to a Modal dialog.
I've created a css file: /css/mycss.css
/css/mycss.css
.test {
width: 90%;
color: red;
}
At the root level, I have my modal dialog JSX file:
MyModal.jsx
//more code above
<Modal
{...this.props}
show={this.state.show}
onHide={this.hideModal}
dialogClassName="test"
>
//more code below
As I understand it, I'm supposed to use the dialogClassName prop to apply CSS to the modal dialog. I'm trying to access the class selector in my CSS file and pass it into the prop as shown.
Do I have to import the CSS?
import test from '/css/mycss.css';
That didn't work. What do I do to get the CSS to show?
Edit:
I've tried
import styles from './css/mycss.css'; // dialogClassName='styles.test';
import { test } from './css/mycss.css'; // dialogClassName='test';
import .test from './css/mycss.css'; // dialogClassName='test';
import {.test} from './css/mycss.css'; // dialogClassName='.test';
import './css/mycss.css'; // dialogClassName='test';
None of that applies the CSS.
Edit 2:
I tried import styles from './css/mycss.css' again and then did dialogClassName = {styles.test};. That actually worked...but sort of. The text colors did change to red but the width of the Modal dialog is still pretty stagnant. It is not 90% of the screen or 10% of the screen no matter what I change the width attribute to. So first, why was the tutorial I was following telling me to pass a string to dialogClassName? And how do I get the width of the modal dialog to change?
You said that you are using webpack. If you don't have installed css loader.
npm install css-loader --save-dev
Now you can import your partial CSS files in React components. This example is when you have CSS files in the same direction as a js file.
import componentStyle from './componentStyle.scss';
There are more way how to import css files. This I use because you can go inside the file like this: className={componentStyle.classInside}.
Webpack example:
module.exports = {
module: {
loaders: [
{ test: /\.css$/, loader: "style-loader!css-loader" }
]
}
};
Also, you can use SASS, LESS, etc. in the same way.
Try import './css/mycss.css';
Path should be relative to the file.
In .js file
import classes from './style.css';
dialogClassName= {classes.myModalStyle} as Modal attribute
In style.css
.myModalStyle{
width: 90%,
max-width: none!important;
}
Note: max-width: none!important is the most important part. Without it, resizing the width won't work

Resources