MakeStyles (Material UI) apply style to child element - reactjs

I was wondering if it's possible to apply a style to a child element only, using MakesStyles, for example in a normal HTML/CSS project:
<div className="parent">
<h1>Title!</h1>
</div>
.parent h1 {
color: #f00;
}
This would color every title inside the div.
I have tried a few differnt ways, one of them was this:
// Function
const { parent } = homeStyle()
return (
<div className={parent}>
<h1>Title!</h1>
</div>
)
// Style
const homeStyle = makeStyles(theme => ({
parent: {
background: "#fff",
h1: {
color: "#f00",
}
},
}))
But it didn't work.

If you are looking to just style material-ui H1 titles, you can select it with:
.parent .MuiTypography-h1 {
color: #f00;
}
In the photo below for an alternative solution, you'll see the classes that are applied to elements with material-ui. The inspector can be handy in identifying the names of the material-ui elements you want to select.
Your mileage may vary, depending on your CSS setup.
What I read from your question however, is a desire to select a single H1, within perhaps a <div> amonst other styled H1s. This can be done with ThemeProvider in the material-ui library (docs here):
import { Typography } from "#material-ui/core";
import {
createMuiTheme,
responsiveFontSizes,
ThemeProvider
} from "#material-ui/core/styles";
const Themed = ({ children }) => {
const theme = createMuiTheme({
overrides: { {/* <-- create a style override */}
MuiTypography: {
h1: {
"&.styled": { {/* <-- specify a className for overrides */}
color: "red"
}
}
}
}
});
return (
<ThemeProvider theme={responsiveFontSizes(theme)}>
<>{children}</>
</ThemeProvider>
);
};
const App = () => {
return (
<Themed>
<Typography
className="styled" {/* <-- add the style from above */}
variant="h1">
Styled H1
</Typography>
<Typography
variant="h1">
Not styled H1
</Typography>
<Typography
variant="h1">
Me neither
</Typography>
</Themed>
);
};
export default App;
Working CodeSandbox.

Related

MUI Theme hook version 5 : creating global theme

I'm trying to create a theme for my Next.JS application with MUI version 5. I created the Theme in my layout component, and I expected the Theme to have effect in other child components. but I can't seem to get my Button to change from the default primary colour. It does work with the "h1"tag, and I'm wondering why it works for the h1 tag and not for the Button component.
//layout component
import { AppBar, Container, CssBaseline, Toolbar, Typography ,createTheme, ThemeProvider} from '#mui/material';
import useStyles from '../utils/styles';
export default function Layout({ title, children, description }) {
const theme = createTheme({
typography: {
h1: {
fontSize: '1.6rem',
fontWeight: 400,
margin: '1rem 0', // this is working
},
h2: {
fontSize: '1.4rem',
fontWeight: 400, // this is working
margin: '1rem 0',
},
palette: {
type: 'light',
primary: { // this is not working
main: '#f0c000',
},
secondary: {
main: '#208080',
},
},
},
});
const classes = useStyles()
return (
<div>
<ThemeProvider theme={theme}>
<CssBaseline/>
<AppBar position="static" className={classes.navbar}>
<Toolbar>
<Typography>App</Typography>
</Toolbar>
</AppBar>
<Container className={classes.main}>{children}</Container>
<footer className={classes.footer}>
<Typography>All right reserved</Typography>
</footer>
</ThemeProvider>
</div>
);
}
Component where I want to use the Theme :
import useStyles from '../../utils/styles'
import { useTheme } from '#mui/material';
export default function ButtonScreen() {
const theme = useTheme();
const classes = useStyles();
return (
// this h1 tag responds to the Theme style provided in the layout component
<Typography component="h1" variant="h1">
Button Action
</Typography>
//The button default colour still persist, even with the theme in place.
<Button fullWidth variant='contained' color="primary">Click me</Button>
)
}
Can someone help me figure out what I am missing here?!

How to override anchor <a> element in material ui v3?

I have tried to override the in typography with
root: {
'&a':{
color: '#FF6600'
},
},
but didn't work any suggestions ?
There are multiple ways to change the color(style) of Material-UI <Typography /> locally.
Mostly been used options would be considered as:
Add style based on the provided CSS API - refer to MUI Typography API document
Override style using the nesting selector for elements and classes - you can find the details inside the browser dev tools
import React from "react";
import "./styles.css";
import { makeStyles } from "#material-ui/core/styles";
import { Typography } from "#material-ui/core";
const useStyles = makeStyles(theme => ({
option1: {
color: "red"
},
option2: {
"&.MuiTypography-root": {
color: "blue"
}
}
}));
export default function App() {
const classes = useStyles();
return (
<div className="App">
<Typography
variant="h5"
component="h5"
classes={{ root: classes.option1 }}
>
Use CSS API with attribute: root
</Typography>
<Typography variant="h5" component="h5" className={classes.option2}>
Use nesting selector of className: MuiTypography-root
</Typography>
</div>
);
}

Material UI: Display sub-element on hover of parent

When the user hovers over a Card component, I'd like to show a button on that component that is otherwise invisible. In CSS, I'd do something like this:
.card:hover my-button {
display: block;
}
How do I replicate this in the "Material-UI" way?
All the Material-UI tips I found so far suggest something like this to add hover styling, but this applies the styles to the component that is being hovered over and not a different one.
'&:hover': {
background: 'blue'
}
You can do the exact same thing with CSS using the createMuiTheme:
export const theme = createMuiTheme({
overrides: {
// For label
MuiCard: {
root: {
"& .hidden-button": {
display: "none"
},
"&:hover .hidden-button": {
display: "flex"
}
}
}
}
});
Give the Button inside your Card the className hidden-button and you will get the same thing that you want.
Check it here: https://codesandbox.io/s/mui-theme-css-hover-example-n8ou5
It is not specific to Material UI but a react specific thing. you need a state variable to show/hide your button.
const App = () => {
const [show, setShow] = useState(false);
return (
<Card
onMouseOver={() => setShow(true)}
onMouseOut={() => setShow(false)}>
<CardBody>
// some content
{show && <Button>Click</Button>}
</CardBody>
</Card>
);
}
If you want to define this purely inside of a styled component instead of using either of createMuiTheme or makeStyles, then try the following.
We will give an id to each child component and reference them when defining the behaviour to implement when we hover over the parent component:
const NameCellBox = styled(Box)(({ theme }) => ({
...other styles,
"&:hover #cellBoxLengthTypo": {
display: "none",
},
"&:hover #cellBoxContentTypo": {
display: "inline-block",
},
}));
const CellBoxLengthTypo = styled(Typography)(({ theme }) => ({
fontFamily: theme.typography.fontFamily,
fontSize: theme.typography.h5.fontSize,
}));
const CellBoxContentTypo = styled(Typography)(({ theme }) => ({
display: "none",
fontFamily: theme.typography.fontFamily,
fontSize: theme.typography.h5.fontSize,
}));
const items: string[] = ["andrew", "barry", "chris", "debbie"];
return (
<>
<NameCellBox>
<CellBoxLengthTypo id="cellBoxLengthTypo">+{items.length}</CellBoxLengthTypo>
<CellBoxContentTypo id="cellBoxContentTypo">{items.join(", ")}</CellBoxContentTypo>
</NameCellBox>
</>
);
Found it useful for updating a DataGrid cell in Material UI when hover or other event fired.
I faced this problem today and after I discussed it with my mentor I made this result and it worked well for me. but first, let me tell you the disadvantage of using eventListener like onMouseEnter & on MouseLeave that it will cause so many renders.
I gave the (parent component) a movie-card class and the (child component) a movie-card-content class like the following
// movie-card.css
.movie-card-content {
opacity: 0;
}
.movie-card:hover .movie-card-content {
opacity: 1;
}
MUI allows you to add className prop so I gave the proper classNames
//MovieCard.jsx (component)
import "./movie-card.css";
function MovieCard () {
return (
<Card className="movie-card">
<CardContent className="movie-card-content">...<CardContent>
</Card>
);
}
and that's it 😉
import {
makeStyles
} from '#material-ui/core'
const useStyles = makeStyles(() => ({
root: {
"& .appear-item": {
display: "none"
},
"&:hover .appear-item": {
display: "block"
}
}
}))
export default function MakeTextAppearOnHover() {
const classes = useStyles()
return (
<div className = { classes.root }>
Hello world
<span className = 'appear-item' >
Appearing text Go
</span>
</div>
)
}
This is a material UI example that displays the sub-element on hover of the parent.
I also noticed that using some of the examples above, when using Material UI's makeStyles, the overlay item was flickering a lot when clicked. This solution below does not flicker when sub-element is clicked.
import React from "react"
import { Card, CardActionArea, CardContent, CardMedia } from "#material-
ui/core";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
card: {
// some styles
},
cardAction: {
position: "relative"
},
media: {
// some styles
},
overlay: {
position: "absolute",
top: "85px"
}
}));
const App = () => {
const classes = useStyles();
const [show, setShow] = React.useState(false);
const handleMouseOver = () => {
setShow(true);
};
const handleMouseOut = () => {
setShow(false);
};
return (
<Card>
<CardActionArea
onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut} className={classes.card} >
<CardMedia className={classes.media} component="img" >
// some content
</CardMedia>
<CardContent className={classes.overlay} style={{ display: show ?
'block' : 'none' }>
// some content
</CardContent>
</CardActionArea>
</Card>
);
}

change active tab background color in react material-ui

want to change background color on active tab from material-ui Tabs:
http://www.material-ui.com/#/components/tabs
already how to change the underline:
inkBarStyle={{background: 'red'}}
but background color changed
thank you very much
Try this
const CustomTab = withStyles({
root: {
backgroundColor: 'orange',
},
selected: {
backgroundColor: 'purple',
},
})(Tab);
and then
<Tabs>
<CustomTab label='One' />
<CustomTab label='Two' />
<CustomTab label='Three' />
</Tabs>
Rather than updating one instance of the tab, perhaps it's better to update the theme in general. Then you wouldn't have to add the style to every individual use of that particular component.
Typically you'd have a theme file such as:
./themes/default/index.ts
import { createMuiTheme } from '#material-ui/core/styles';
import { Breakpoint } from '#material-ui/core/styles/createBreakpoints';
const overrides = {
MuiTab: {
// general overrides for your material tab component here
root: {
backgroundColor: 'red',
'&$selected': {
backgroundColor: 'blue',
}
},
},
};
const theme = createMuiTheme( {
overrides,
breakpoints,
palette,
typography,
shape,
});
Then in your application you can use this as:
./src/index.ts
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { MuiThemeProvider } from '#material-ui/core/styles';
import { App } from './components';
ReactDOM.render(
<MuiThemeProvider theme={themeSpec.theme}>
<App />
</MuiThemeProvider>,
document.getElementById('root') as HTMLElement
);
Source: https://material-ui.com/customization/components/#global-theme-override
Default values can be found here: https://material-ui.com/customization/default-theme/
The overrides for components can be found here: https://github.com/mui-org/material-ui/blob/2726ab46b2b1789bdd0a9aa1a2ff249a443ab1a8/packages/material-ui/src/styles/overrides.d.ts#L91-L173
More info regarding the material themes: https://material-ui.com/customization/themes/#themes
Note: Examples in typescript to be a bit more thorough, but the same would go for vanilla javascript
You can simply do by the conditional rendering of styles, your styles should look like this
const styles = theme => ({
default_tabStyle:{
color: 'black',
fontSize:11,
backgroundColor: 'blue',
},
active_tabStyle:{
fontSize:11,
color: 'white',
backgroundColor: 'red',
}
})
Then in your Component
class YourComponent extends Component {
state = {
value: 0,
}
handleChange = (event, value, index) => {
this.setState({ value:value });
}
render(){
const { classes } = this.props;
return (
<div>
<AppBar position="static" className={classes.appBarStyle}>
<Tabs value={this.state.value} indicatorColor="#E18F68"
onChange={this.handleChange}
fullWidth={true}
scrollButtons="auto"
>
<Tab label="Tab01"
className=
{this.state.value===0 ? classes.active_tab :classes.default_tabStyle} />
<Tab label="Tab02"
className=
{this.state.value===1 ?classes.active_tab :classes.default_tabStyle}/>
<Tab label="Tab02"
className=
{this.state.value===2 ?classes.active_tab :classes.default_tabStyle
}/>
</Tabs>
</AppBar>
</div>
)
}
}
By default, your tab will be at index 0 and as there is change at the index of tab active_tabStyle will apply.
To customize the background color of the tabs and the color of the inkBar, it is recommended to customize the Material-UI theme itself. There are specific settings for these two colors.
const muiTheme = getMuiTheme({
tabs: {
backgroundColor: 'red'
},
inkBar: {
backgroundColor: 'yellow'
}
})
Details on customizing the theme can be found here: http://www.material-ui.com/#/customization/themes

How to apply different color in AppBar Title MUI?

I am trying to use my custom color for AppBar header. The AppBar has title 'My AppBar'. I am using white as my primary theme color. It works well for the bar but the 'title' of the AppBar is also using same 'white' color'
Here is my code:
import React from 'react';
import * as Colors 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';
import TextField from 'material-ui/TextField';
const muiTheme = getMuiTheme({
palette: {
textColor: Colors.darkBlack,
primary1Color: Colors.white,
primary2Color: Colors.indigo700,
accent1Color: Colors.redA200,
pickerHeaderColor: Colors.darkBlack,
},
appBar: {
height: 60,
},
});
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">
<div>
< TextField hintText = "username" / >
< TextField hintText = "password" / >
</div>
</AppBar>
</MuiThemeProvider>
);
}
}
export default Main;
But, the palette styles override the AppBar 'title' color and no title is displaying. Should I include something or I have misplaced any ?
And this is my output :
If you ant to change your Appbar background in material ui design ....try following code
<AppBar style={{ background: '#2E3B55' }}>
or if you want to apply className then follow this step
first of all make create const var
const style = {
background : '#2E3B55';
};
<AppBar className={style}>
MUI v5 update
1. Use sx prop
<AppBar sx={{ bgcolor: "green" }}>
2. Set primary.main color in Palette
The Appbar background color uses the primary color provided from the theme by default.
const theme = createTheme({
palette: {
primary: {
main: "#00ff00"
}
}
});
3. Set AppBar default styles in styleOverrides
Use this one if you don't want to touch the primary.main value and potentially affect other components:
const theme = createTheme({
components: {
MuiAppBar: {
styleOverrides: {
colorPrimary: {
backgroundColor: "red"
}
}
}
}
});
From what I see in the material-ui sources, appBar title color is set by palette.alternateTextColor. If you add it to your style definition like that:
const muiTheme = getMuiTheme({
palette: {
textColor: Colors.darkBlack,
primary1Color: Colors.white,
primary2Color: Colors.indigo700,
accent1Color: Colors.redA200,
pickerHeaderColor: Colors.darkBlack,
alternateTextColor: Colors.redA200
},
appBar: {
height: 60,
},
});
You should see your title without need to style it manually inside each component.
There are more styling parameters to MuiTheme described here
Create your style using makeStyles():
const useStyles = makeStyles(theme => ({
root: {
boxShadow: "none",
backgroundColor: "#cccccc"
}
}));
Use the above style in your component:
const classes = useStyles();
<AppBar className={classes.root} />
Please make theme.js first.
- theme.js
import { red } from '#material-ui/core/colors';
import { createMuiTheme } from '#material-ui/core/styles';
export default createMuiTheme({
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#19857b',
},
error: {
main: red.A400,
},
background: {
default: '#fff',
},
},
});
Add these lines to index.js
import { ThemeProvider } from '#material-ui/core/styles'
import theme from './theme'
ReactDOM.render(
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>,
document.getElementById('root')
);
<AppBar position='static' color='secondary' elevation={2}>
...
</AppBar>
*** important ***
secondary: {
main: '#19857b',
},
color='secondary'
Finally, I came to know about titleStyle for styling title in AppBar.
const titleStyles = {
title: {
cursor: 'pointer'
},
color:{
color: Colors.redA200
}
};
<AppBar title={<span style={titleStyles.title}>Title</span>} titleStyle={titleStyles.color}> .............
</AppBar>
By default it uses palette's contrastText prop (v3):
const theme = createMuiTheme({
palette: {
primary: {
contrastText: 'rgba(0,0,0,0.8)'
}
},
});
first of all, add const to the file. Then apply to the line u need as following shown.
const styles = { button: { margin: 15,}, appBarBackground:{ background : '#2E3B55' }};
Then add it to the line as shown down
style={styles.button}
style={styles.appBarBackground}
You cat add this inline your code
<AppBar title="My AppBar" style={{ backgroundColor: '#2196F3' }} >
or if your css
import './home.css';
put this to your code
.title {
text-align: left;
background-color: black !important;}
Hope to help.
Working on #NearHuscarl answer. If you want the styles to be applied no matter which appbar color you are on: E.g. <Appbar color="secondary" or <Appbar color="primary". You could alternatively use the root property:
const theme = createTheme({
components: {
MuiAppBar: {
root: {
colorPrimary: {
backgroundColor: "red"
}
}
}
}
});
The difference is the root keyword
You can set the background color directly using sx property
<AppBar variant='elevated' sx={{backgroundColor:'#19857b'}}>

Resources