Why is my custom theme only partially applying (antd)? - reactjs

I am using Ant Design in a React project of mine, and I am attempting to make use of their custom theming available in version 5 (5.1.2 installed) according to documentation here. However, the custom theme appears to only apply to certain components while skipping others altogether. In the below example, the darker background color is applied to the Content and Footer components while the Header and Sider components are left with the default color, and the Header and Footer components have updated foreground colors, but the Sider and Content components do not. What am I missing to make this theme apply in full to each of these components?
Example:
src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { ConfigProvider } from 'antd';
import theme from './theme';
import reducers from './reducers';
import App from './components/App';
const store = createStore(reducers)
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<ConfigProvider theme={theme}>
<React.StrictMode>
<App />
</React.StrictMode>
</ConfigProvider>
</Provider>
);
src/theme.js
import { theme } from 'antd';
const custom_theme = {
algorithm: theme.darkAlgorithm,
token: {
colorPrimary: '#e02820',
borderRadius: 5,
wireframe: false
},
}
export default custom_theme;
src/components/App.js
import React from 'react';
import { Layout } from 'antd';
const { Header, Footer, Sider, Content } = Layout;
class App extends React.Component {
render() {
return (
<Layout>
<Header>header</Header>
<Layout>
<Sider>sider</Sider>
<Content>content</Content>
</Layout>
<Footer>footer</Footer>
</Layout>
);
}
}
export default App;
Result:

I have been playing around with AntD custom theme as well and have found that not every attribute can be updated. The main changes allowed are colorPrimary and according to the documentation based on this color their algorithm chooses the rest of the color pallet that matches.
From documentation - "Brand color is one of the most direct visual elements to reflect the characteristics and communication of the product. After you have selected the brand color, we will automatically generate a complete color palette and assign it effective design semantics."
That being said you can try to be even more specific. By that I mean you can specify the style for each separate component.
<ConfigProvider
theme={{
components: {
Header: {
colorPrimary: '#00b96b',
},
Footer: {
colorPrimary: '#fff',
},
},
}}
>
Just change and add your desired styles to each component. If it still does not change, then that is the color AntD will let you have based for each component based on your choice of primary color.
Another option would be to use styled-components library to further provide the styles to AntD components that are not possible using Ants Config API.
If this provides the valid solution would you please click the green arrow on my response to inform others of the solution.

Related

Mui theme not applying if within a wrapper component

With React (typescript) and MUI (5.4.2), I'm trying to put everything regarding styles within a single file, wrapping everything in my App.tsx.
Issue: The custom MUI theme does not apply to the rest of my app (fallback to default MUI theme)
The whole thing worked fine when the ThemeProvider component was placed directly within the App.tsx file, but broke as soon as I placed it elsewhere. I need to keep a separated component, for I'll add Elastic UI on top of MUI later on.
My App.tsx file:
function App() {
<UiProvider>
// ...whole app
</UiProvider>
}
The UiProvider component is a simple wrapper component as it follows:
import {ThemeProvider} from "#mui/styles";
import {CustomTheme} from "../../themes/CustomTheme";
import {createTheme, Theme} from "#mui/material/styles";
const UiProvider = (props: any) => {
return (
<ThemeProvider theme={CustomTheme}>
{props.children}
</ThemeProvider>
)
}
export default UiProvider
Because #mui/styles is the legacy styling solution for MUI, if this is for v5, perhaps the import for ThemeProvider should be:
import { ThemeProvider } from '#mui/material/styles';

How to access MUI 5 theme variables in deep functional component?

The MUI 5 docs on Theming have a section on "Accessing the theme in a component". However, it's really just one sentence that links to the legacy style docs.
Here's the example they give in those legacy docs:
import { useTheme } from '#mui/styles';
function DeepChild() {
const theme = useTheme();
return <span>{`spacing ${theme.spacing}`}</span>;
}
Which is pretty much exactly what I want to do — I want to be able to access the theme color palette down in some deep functional component. However, my component complains
Module not found: Error: Can't resolve '#mui/styles' in...
Digging a little further, it seems they're rather strongly trying to discourage people from using this legacy Styles technique, and the MUI 5 way to do this is with "system design tokens", which I guess should Just Work. But, they're not.
I have my whole app wrapped in ThemeProvider:
import React from 'react';
import { CssBaseline } from '#mui/material';
import { ThemeProvider } from '#mui/material/styles';
import theme from './theme';
import Foo from './foo';
const App = () => {
return (
<Fragment>
<ThemeProvider theme={theme}>
<CssBaseline enableColorScheme />
<Foo />
</ThemeProvider>
</Fragment>
);
};
export default App;
And then in foo.js:
import React from 'react';
import { Box } from '#mui/material';
export const Foo = () => {
return (
<Box
sx={{
background: 'repeating-linear-gradient(-45deg, '
+ ' theme.palette.error.light, theme.palette.error.light 25px,'
+ ' theme.palette.error.dark 25px, theme.palette.error.dark 50px'
+ ')',
}}
>
<span>Test</span>
</Box>
);
};
I initially started with just error.light and error.dark. When that didn't work, I expanded it all to palette.error.light, etc..., and then ultimately to theme.palette.error.light, etc....
It seems no matter what I try, it's not accessing those theme variables, and is instead just passing through the text.
So, back to the question: how am I supposed to access MUI 5 theme variables in nested functional components?
Replace
import { useTheme } from '#mui/styles';
with
import { useTheme } from '#mui/material/styles';
#mui/styles is used for legacy, you can add it using yarn add or npm install, but first give a shot to what I mentioned above.

can't change background color in theme Material-UI

I have been trying to define a custom theme using material UI and defining a default background colour for it. But the changes are not taking effect while other pallete options are working. Can anybody tell me what I'm doing wrong? As far as I can tell this is the way to change the colour.
Here's my code
theme.ts
import { createTheme } from '#mui/material';
import {red} from '#mui/material/colors';
const theme = createTheme({
palette: {
background: {
default: '#FFD600',
paper: '#FFD600',
},
},
});
export default theme;
my entry file
import '../styles/globals.css';
import {ThemeProvider} from "#mui/material/styles"
import theme from '../theme'
function MyApp({ Component, pageProps }) {
return (
<ThemeProvider theme={theme}>
<Component {...pageProps} />
</ThemeProvider>
);
}
export default MyApp;
EDIT: It seems to be changing the background for the components I have used with material-UI but not for other components I may define.
e.g. Here. I used the card component of MUI and the background was changed but I need it to change the background colour of the whole page
EDIT2: The component one worked because I defined paper colour, but I still cant get default to work
So the reason it's still not working is that we need to import CssBaseline for it to work. CssBaseline implements background.default color according to the doc.
Here's how it'll work
import '../styles/globals.css';
import {ThemeProvider} from "#mui/material/styles"
import theme from '../theme'
import { CssBaseline } from '#mui/material/';
function MyApp({ Component, pageProps }) {
return (
<ThemeProvider theme={theme}>
<CssBaseline/>
<Component {...pageProps} />
</ThemeProvider>
);
}
export default MyApp;
Still weird how the paper property works but for default you need to import additional dependencies

How to apply my custom themes with ConfigProvider in Ant Design?

We are developing a using interface with React and Ant Design. We would like to override the default theme and colors. As an example we defines an array called themes. There is 4 differents themes as object. I defined a button to change theme. Reading the official docs I have included the following code in App.js to override the default theme but no success.
ConfigProvider.config(
{
theme:theme
}
)
Can anyone help me to override the default theme without less or anything else but just with ConfigProvider?
import "./App.css";
import "antd/dist/antd.css";
import { ConfigProvider } from "antd";
import { ThemeProvider } from "styled-components";
import ChangeTheme from "./components/ChangeTheme";
import { useContext } from "react";
import { AppContext } from "./_context";
const App = () => {
const { theme } = useContext(AppContext);
ConfigProvider.config({
theme: theme,
});
return (
<ThemeProvider theme={theme}>
<ConfigProvider>
<div className="App">
<ChangeTheme />
</div>
</ConfigProvider>
</ThemeProvider>
);
};
export default App;
First Step
you need to import antd.variable.min.css in one of your root files, like src/index.js which is recommended in the document,
import 'antd/dist/antd.variable.min.css';
Second Step
you also need to import antd's ConfigProvider in src/index.js:
import { ConfigProvider } from 'antd';
Third Step
then you need to modify the theme variables in config method of ConfigProvider like below:
ConfigProvider.config({ theme: { primaryColor: "#f00" } });
ps the vriables that you can modify in theme are:
primaryColor
errorColor
infoColor
processingColor
successColor
warningColor
Fourth Step
finally you wrap ConfigProvider around the <App/> component in src/index.js
<ConfigProvider>
{/* some other codes you might have */}
<App />
</ConfigProvider>

What does the CssBaseline class do?

I've been wondering what the CssBaseline class in the Material-UI React library does, but I can't seem to find an answer anywhere, and the page I linked doesn't do much explaining about what the class does. Does anyone here know what this component is supposed to do?
CssBaseline is sort of css reset added to the <head /> of your document. If you are familiar with similar approaches like normalize.css which adds some default visual styling to default elements, resets paddings and etc ...
Material-UI provides some reset styles as you can observe here CssBasline.js mainly box-sizing and body font color and background color
'#global': {
html: {
WebkitFontSmoothing: 'antialiased', // Antialiasing.
MozOsxFontSmoothing: 'grayscale', // Antialiasing.
// Change from `box-sizing: content-box` so that `width`
// is not affected by `padding` or `border`.
boxSizing: 'border-box',
},
'*, *::before, *::after': {
boxSizing: 'inherit',
},
'strong, b': {
fontWeight: 'bolder',
},
body: {
margin: 0, // Remove the margin in all browsers.
color: theme.palette.text.primary,
...theme.typography.body2,
backgroundColor: theme.palette.background.default,
'#media print': {
// Save printer ink.
backgroundColor: theme.palette.common.white,
},
},
The docs say that its a collection of HTML element and attribute style-normalizations. It's based on normalize.js, which is a modern cross-browser CSS reset for your HTML elements that preserves some of the defaults.
Basically, it resets your CSS to a consistent baseline. That way, you can restyle your HTML doc so that you know you can expect all of the elements to look the same across all browsers.
What normalize.js does, from the readme linked above:
Preserves useful defaults, unlike many CSS resets.
Normalizes styles for a wide range of elements. Corrects bugs and common browser
inconsistencies.
Improves usability with subtle modifications.
Explains what code does using detailed comments.
import { createMuiTheme } from "#material-ui/core/styles";
const theme = createMuiTheme({
overrides: {
MuiCssBaseline: {
"#global": {
"*, *::before, *::after": {
boxSizing: "content-box",
},
body: {
backgroundColor: "#fff",
},
},
},
},
});
export default theme;
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import { BrowserRouter } from "react-router-dom";
import { MuiThemeProvider } from "#material-ui/core/styles";
import theme from "./Theme/Theme";
ReactDOM.render(
<MuiThemeProvider theme={theme}>
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
</MuiThemeProvider>,
document.getElementById("root")
);
serviceWorker.unregister();
Basically, The MUI provides MuiCssBaseline that overrides some of our CSS styles. But MUI
provides the flexibility to override its default style. Here is what I have implemented
1: Create a theme.js and import createMuiTheme. Then override the styles of MuiBaseline based on your requirements and export the theme.js.
2.If you want the overridden style all over your application then import theme.js, MuiThemeProvider from material-ui/core/styles into your index.js, MuiThemeProvider takes the theme as an argument and then applies the style to its children components.
Related to - but I can't seem to find an answer anywhere.
You can find code for CssBaseLine in the repository for the Material-UI library on Github by following link.
By putting at top of your component is used for providing a lot of default styling for your material UI applications so that you don't have to worry about basic styles of your component

Resources