In Mui, how do I use theme values in my css - css

My React app is using mui themes; index.js contains:
let theme = createTheme({
palette: {
primary: {
main: "#00aaa0",
contrastText: '#fcf4d9',
},
secondary: {
main: "#D55B3E",
contrastText: '#fcf4d9',
},
},
});
theme = responsiveFontSizes(theme);
ReactDOM.render(
<ThemeProvider theme={theme}>
<CssBaseline />
<App />
</ThemeProvider>
document.getElementById('root')
);
In one of my components (footer) I want to be able to add a top border which is in the primary colour. So far footer.tsx contains:
const Footer= () => {
return (
<div className="pageFooter">Footer Text</div>
);
};
export default Footer;
I want to style "pageFooter" so that it uses theme.palette.primary.main as a top border colour. With regular css I would link in my css file containing:
.pageFooter {
border-top: 2px solid "#00aaa0";
}
but I want to make sure that the colour is always the same as the primary colour, so I want to do something like this:
.pageFooter {
border-top: 2px solid theme.palette.primary.main;
}
This doesn't work, though, presumably because the theme is not available to the css file. I've read the docs and I can't really follow them. Can anyone explain what I should be doing here?

import { makeStyles } from '#material-ui/core'
const useStyles = makeStyles(theme => ({
pageFooter: {
borderColor: theme.palette.primary.main,
}
});
const Footer= () => {
const classes = useStyles()
return (
<div className={classes.pageFooter}>Footer Text</div>
);
};
export default Footer;

according to the MUI docs:
#mui/styles is the legacy styling solution for MUI. It depends on JSS as a styling solution, which is not used in the #mui/material anymore, deprecated in v5.
and also
#mui/styles is not compatible with React.StrictMode or React 18.
MUI use JSS for styling. so we don't have access to theme in CSS files.
my solution:
you can define a CSS variable same color as your theme palette color. then use it in CSS files.
:root {
--primary-main: #00aaa0;
}
.pageFooter {
border-top: 2px solid var(--primary-main);
}

It's supported now by MUI v5.6.0 as an experimental feature. They export theme variables as CSS variables. Read the docs.
Example:
/* external-scope.css */
.external-section {
background-color: var(--mui-palette-grey-50);
}

Related

Why custom material UI styles not reflecting after deployment?

I was trying to implement a customized material UI element. Here is how I was trying to increase the size of the icon.
Here is my style code:
export const Icon = styled(Box)({
color: "gray",
position: "relative",
"& .css-i4bv87-MuiSvgIcon-root": {
fontSize: "2rem",
},
"&:hover": {
color: "black",
},
});
App.js:
<Icon>{icon}</Icon>
While development the style is showing properly as intended, but when I have deployed my app I could see that the style
"& .css-i4bv87-MuiSvgIcon-root": {
fontSize: "2rem",
}
is not reflecting in my application.
Can someone guide me?
the thing is that you are using MuiSvgIcon-root to add the style but in your styled(Box) see that you have a Box. So you need to add style to the correct css class.
If you inspect the css you will see that with your style code the class used is the MuiBox-root:
I've tried in a react codesanbox with this:
import "./styles.css";
import { styled, Box } from "#mui/material";
const Icon = styled(Box)({
color: "gray",
position: "relative",
"&.MuiBox-root": {
fontSize: "2rem",
":hover": {
color: "black"
}
}
});
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Icon>my icon</Icon>
</div>
);
}
LINK: https://codesandbox.io/s/priceless-zeh-yhgqob?file=/src/App.js
Make their precedence higher by making it important may be some other class overriding it! Check on inspect after deployed version.

How to style Material-UI's BottomNavigationAction, so the selected icon is a different color?

I need some help with this problem I'm having with Material-UI styled components
I'm trying to create a BottomNavigation bar on react using Material-UI v5. I want that the icon of the selected option in the bar shows a specific color, let's say red (#f00) and the not-selected icons show green (#00f), for this I'm using the styled function to generate a custom-themed component for BottomNavigationAction, following the guidelines on the documentation: styled(). The problem: For the selected button, the icon is not grabbing the correct color and is showing the default one. At this point I'm not sure if I'm using the styled function wrong or is something super obvious I'm not seeing. Thanks in advance for any advice!
PS: I don't have enough reputation to post the image directly, sorry for that
The BottomNavigation is defined as follows:
const BottomNav = () => {
return(
<BottomNavigation
showLabels
value={value}
onChange={(event, newValue) => {setValue(newValue)}}
>
<TabBarButton
id='Home'
label='Home'
icon= {home_icon? <AiFillHome size = "30" />: <AiOutlineHome size='30'/> }
onClick={
(value)=>{
iconHandler(value.currentTarget.id)
}
}
/>
<TabBarButton
id='Documentos'
label='Documentos'
icon= {documentos_icon? <RiEditBoxFill size='30'/>: <RiEditBoxLine size='30'/>}
onClick={
(value) =>
iconHandler(value.currentTarget.id)
}
}
/>
</BottomNavigation>
);
}
To define TabBarButton I firstly tried defining the component like this:
import {BottomNavigation, BottomNavigationAction} from "#mui/material";
import { styled} from '#mui/system';
// Styled BottomNavigationAction
const TabBarButton = styled(BottomNavigationAction)({
root: {
color: '#f00',
},
selected: {
color: '#0f0',
}
});
But the rule names: root and selected didn't work, resulting in the default colors being applied:
first-try-bottom-navigation-image
So I changed them to the Global Class instead : BottomNavigationAction CSS :
// Styled BottomNavigationAction
const TabBarButton = styled(BottomNavigationAction)({
color: '#0f0',
'.Mui-selected':{
color: '#f00',
}
});
Which worked with the not-selected icon and the labels:
second-try-bottom-navigation-image
But the selected icon 'Home' is still using the default colors, I tried using a variation of the answer provided on this post Bottom Navigation Material UI Override
// Styled BottomNavigationAction
const TabBarButton = styled(BottomNavigationAction)({
color: '#0f0',
'.Mui-selected, svg':{
color: '#f00',
}
});
But this affects both icons resulting in :
third-try-bottom-navigation-image
I think TabBarButton need to add '&.Mui-selected' selector to have the styles attached to itself correctly, otherwise with '.Mui-selected' the rules only apply to nested elements:
Tested the example on: stackblitz
// Styled BottomNavigationAction
const TabBarButton = styled(BottomNavigationAction)({
color: 'royalblue',
'&.Mui-selected': {
color: 'crimson',
},
});

Trouble styling TablePagination to-from on material-table

I am attempting to style the from-to of x rows number on a Material-Table, via
import MaterialTable from 'material-table'
import { TablePagination, withStyles } from '#material-ui/core'
const StyledPagination = withStyles({
caption: {
'&.MuiTypography-caption': {
fontSize: '1.5rem !important'
},
fontSize: '1.5rem !important'
}
})(TablePagination)
<MaterialTable
**Other Props Here**
components={{
Pagination: props => (
<StyledPagination
{...props}
labelRowsPerPage={<div>{props.labelRowsPerPage}</div>}
labelDisplayedRows={row => (
<div>{props.labelDisplayedRows(row)}</div>
)}
/>
)
}}
/>
I feel like those two css selectors should be redundant, but neither is working. I feel like material-table is overriding them as the computed font size is 0.75rem .MuiTypography-caption. Have also attempted styling via the root rather than caption with no difference there either.
I have been able to style the dropdown selector for number of rows to display, which seems like the same should apply to this. Originally started with this approach, which also did not work.
Ended up solving this with MuiThemeProvider, I dont think the normal ThemeProvider is working with Material-table
import { createMuiTheme, MuiThemeProvider } from '#material-ui/core/styles'
const theme = createMuiTheme({
overrides: {
MuiTypography: {
caption: {
fontSize: '1.5rem'
}
}
})
then,
<MuiThemeProvider theme={theme}>
<MaterialTable />
</MuiThemeProvider>
Although, this will style anything with class MuiTypography-caption

How can I dynamically set style of a mapped element without using inline styling?

I'm coding a React function with parent component containing an array of objects:
let const ingredients = [
{name:"lettuce",color:"green"},
{name:"tomato",color:"red"}
]
...
In a child component, there is a map function that breaks down an array to single items to be displayed in a div.
What is the best practice for defining CSS styling for an object className:"name" to set backgroundColor: {ingredient.color};? I'm trying to avoid manual entry of the entire set of key/values of 'ingredients', to allow updating the object without breaking the code.
I'm currently using inline styling, which I have been advised against. Currently using:
let burg = props.toppings.map((item) => {
const divColor = {backgroundColor: item.color};
return (<div style={divColor}>{item.name}</div>)
Inline style is bad when you have other solution to do what you want. Here, you have a string that is the color (red, green, etc.) so you could write a css class for every color, but that is of course a really bad idea. Inline style is the good way to do it here.
I would suggest setting the class of the div instead of the style. That way you can change the look without resorting to inlining the style.
You could create a css class for lettuce with the background color green, instead of using the item.color you'd set class={ item.name }
You can use this way.
css can be more handy if you use scss
// css
.color-green {
color: green;
}
.color-red {
color: red;
}
import React from "react";
import "./styles.css";
const ingredients = [
{ name: "lettuce", color: "green" },
{ name: "tomato", color: "red" }
];
const Vegetable = ({ color, text }) => {
return (
<p>
this is <span className={`color-${color}`}>{text}</span> color{" "}
</p>
);
};
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
{ingredients.map((item, index) => {
return <Vegetable key={index} color={item.color} text={item.name} />;
})}
</div>
);
}

Styling material UI components

Not really a problem but something I’m not happy with. I'm using react + typescript + css modules + https://material-ui-next.com/. Problem is that when I need to style material ui components I have to use !important a lot. Question is if there is a way to create styles without important. I create a sample project to reproduce the problem https://github.com/halkar/test-css-modules
material-ui exposes many of their components for styling. There two ways to go about doing this.
Apply styles globally
You could style the components globally and apply it to the theme. An example of this would be something like this (copied from the docs http://www.material-ui.com/#/customization/themes):
import React from 'react';
import {cyan500} from 'material-ui/styles/colors';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import AppBar from 'material-ui/AppBar';
// This replaces the textColor value on the palette
// and then update the keys for each component that depends on it.
// More on Colors: http://www.material-ui.com/#/customization/colors
const muiTheme = getMuiTheme({
palette: {
textColor: cyan500,
},
appBar: {
height: 50,
},
});
class Main extends React.Component {
render() {
// MuiThemeProvider takes the theme as a property and passed it down the hierarchy
// using React's context feature.
return (
<MuiThemeProvider muiTheme={muiTheme}>
<AppBar title="My AppBar" />
</MuiThemeProvider>
);
}
}
export default Main;
As you can see in here, appBar component have a height of 50px meaning that every time you add an appbar component to your app down the tree where you applied the muiTheme, it will give it a height of 50px. This is a list of all the styles you can apply for each component https://github.com/callemall/material-ui/blob/master/src/styles/getMuiTheme.js.
Apply styles using style attribute
To apply the styles to individual components, you can usually use the style property and pass it the styles you want.
This is another example from the docs where a margin of 12px is applied to a RaisedButton.
import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';
const style = {
margin: 12,
};
const RaisedButtonExampleSimple = () => (
<div>
<RaisedButton label="Default" style={style} />
<RaisedButton label="Primary" primary={true} style={style} />
<RaisedButton label="Secondary" secondary={true} style={style} />
<RaisedButton label="Disabled" disabled={true} style={style} />
<br />
<br />
<RaisedButton label="Full width" fullWidth={true} />
</div>
);
export default RaisedButtonExampleSimple;
Now, the styles are defined in the same file but you could define them in a separate file and import them to the file where you are using the components.
If you want to apply multiple styles then you can use the spread operator like so: style={{...style1,...style2}}.
Usually, you are styling a specific thing in the component (root element) with the style property but some components have more than one property to style different elements of the component. Under properties in this page http://www.material-ui.com/#/components/raised-button, you can see that there are style property, labelStyle and rippleStyle to style different parts of RaisedButton.
Check the properties under the component that you are using and see which style property you could use, otherwise check the available global style properties you could override. Hope this helps!
I should've used JssProvider and tell it to put material UI styles before mine in the page head section.
import JssProvider from 'react-jss/lib/JssProvider';
import { create } from 'jss';
import { createGenerateClassName, jssPreset } from 'material-ui/styles';
const generateClassName = createGenerateClassName();
const jss = create(jssPreset());
// We define a custom insertion point that JSS will look for injecting the styles in the DOM.
jss.options.insertionPoint = document.getElementById('jss-insertion-point');
function App() {
return (
<JssProvider jss={jss} generateClassName={generateClassName}>
...
</JssProvider>
);
}
export default App;
you have to use the component API's. You can't set style to the components imported from libraries just with css if the component has API's to get style.
*Update
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Button from 'material-ui/Button';
const styles = {
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
borderRadius: 3,
border: 0,
color: 'white',
height: 48,
padding: '0 30px',
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .30)',
},
label: {
textTransform: 'capitalize',
},
};
function Classes(props) {
return (
<Button
classes={{
root: props.classes.root, // class name, e.g. `classes-root-x`
label: props.classes.label, // class name, e.g. `classes-label-x`
}}
>
{props.children ? props.children : 'classes'}
</Button>
);
}
Classes.propTypes = {
children: PropTypes.node,
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(Classes);

Resources