Material UI nested class override - reactjs

Im using muiSelect and there is a css selector that im trying to overwrite:
.MuiSelect-select.MuiSelect-select
How can I override this? Ive tried a couple things already like
MuiSelect: {
select: {
"& $MuiSelect-select":
}
}
Which doesnt seem to work

Try:
MuiSelect: {
select: {
'&&': { ... },
}
}
This is the line of source code where the default is set (paddingRight: 24px), and the mui theme key to override it is '&&'. I was able to find this by first finding the source code of the native select component, and then searching for the css value that showed up on the dom element I was trying to override.

Related

Darkmode not working on tailwind headless UI

Darkmode works everywhere in my react app, except on a headless ui combobox. I put a styled h1 in the same component and applied dark:bg-red-200(and any other style) no problem. The combobox accept all other tailwind utilities including attibutes like hover: but not the dark: property.
For others (such as me) stumbling upon this:
E.g. the Dialog-component (and I assume others too) render right in the body tag (source)
If you are using "the class strategy" to handle dark mode (i.e. adding a "dark" class to the wrapper) this will be a problem, because the class is not anymore parent to the Dialog
Solution I ended up using:
I ended up using useEffect to add the dark class to the body:
useEffect(() => {
if(darkMode){
document.body.classList.add('dark')
}else{
document.body.classList.remove('dark')
}
}, [darkMode])

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.

froala editor 3 with react js - how to hide toolbar on initialize?

I am trying to implement froala editor in my react js application, and the i need to keep toolbar hidden by default and should only show up when the textarea/editor has focus. in the previous versions the initialize would work like below but not in version 3 anymore. any help is appreciated.
'froalaEditor.initialized': function (e, editor) {
editor.toolbar.hide();
}
You have to use the config prop and then set an initialized event like this:
(
<FroalaEditor
tag='textarea'
config={{
events: {
'initialized': function() {
// this is the editor instance.
this.toolbar.hide();
}
}
}}
/>
)

Image insertion at cursor in editor using slatejs

I am trying to implement a Rich Text editor using reactjs and slate.js. So far, i was able to get most features working, however unable to add images to the document at the cursor is not working (Image insertion at beginning of the document is working, however).
when iam trying to insert it any other point iam getting the error.
at the renderpart i.e., executing the onchange method of the editor.
const target = getEventRange(e, this.state.EditorComp.state.value)
change = this.state.EditorComp.state.value.change().call(this.insertImage, filelocation,target)
this.state.EditorComp.onChange(change);
slate-react.es.js:1229 Uncaught Error: Unable to find a DOM node for "51". This is often because of forgetting to add `props.attributes` to a custom component.
at findDOMNode$1 (slate-react.es.js:1229)
at findDOMPoint (slate-react.es.js:1247)
at findDOMRange (slate-react.es.js:1290)
My code is based on the link https://github.com/ianstormtaylor/slate/blob/master/examples/images/index.js
Please help.
Do you have a schema defined for your editor? I had this same error until I added a schema for images that set isVoid to true. You need at least the following in your schema:
const schema = {
blocks: {
image: {
isVoid: true
}
}
};
I would imagine you would want to insert the image inline if you want it at the cursor:
change.insertInline({
type: 'img',
isVoid: true,
data: { location: location }
})
change.moveToStartOfNextText().focus()
Then in your renderNode method:
const { attributes, node, isSelected } = props
if (node.type === 'img') {
node.data.get('location')
return <img ... />
}

How to avoid Material UI Select focus when option is chosen?

I am trying to make an interface with a pair of Select and Input from Material UI components library. I want the current behaviour for my UI/UX in the next order:
1. User chose option from Select element
2. Inputwill be focused when user chose something from Select
You can see how it's works (see the second Select, because the first one is a native Select, and it's not suitable for my purpose):
https://codesandbox.io/s/l4nq3pjjrm
The first one in the example above works great, but I need non-native variant.
How I can do that?
Thanks.
P.S. Also, I found that there are another issues with that wrong Select behaviour, take a look for my github post for mo details. (https://github.com/mui-org/material-ui/issues/11964)
So if your problem is the focus after the value selection, try this:
1) Import MuiThemeProvider and createMuiTheme on your component:
import { MuiThemeProvider, createMuiTheme } from '#material-ui/core/styles';
2) Then Add this lines of code after your imports (override css):
const theme1 = createMuiTheme({
overrides: {
MuiSelect: {
select: {
"&:focus": {
background: "$labelcolor"
}
}
}
}
});
3) And for the final step, wrap your component that you want to edit with this code:
<MuiThemeProvider theme={theme1}>
// Your Component here
</MuiThemeProvider>
I applied it on your code here
For some reason the top answer didn't work for me. For anyone else facing this, you can also do it this way:
className: {
"& .MuiSelect-select:focus": {
backgroundColor: white,
},
},

Resources