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

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>
);
}

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?!

TypeError: Cannot read properties of undefined (reading 'up') MUI

In my Header component my custom styling are coming from style.js where I've used makeStyles from #mui/styles. But In there while setting up the [theme.breakpoints.up("sm")] I'm getting the error above. I tried wrapping the index.js with themeProvider and passed createTheme as prop. but it is giving me another error. I tried looking up the docs but couldn't figure it out.
styles.js
import { makeStyles } from "#mui/styles";
import { alpha } from "#mui/material/styles";
export default makeStyles((theme) => ({
title: {
display: "none",
[theme.breakpoints.up("sm")]: {
display: "block",
},
},
...
})
)
Header component
import React from "react";
import useStyles from "./styles";
import { AppBar, Toolbar, Typography, InputBase, Box } from "#mui/material";
import { Autocomplete } from "#react-google-maps/api";
import { SearchIcon } from "#mui/icons-material/Search";
const Header = () => {
const classes = useStyles();
return (
<AppBar position="static">
<Toolbar className={classes.toolbar}>
<Typography variant="h5" className={classes.title}>
Travel Companion
</Typography>
<Box display="flex">
<Typography variant="h6" className={classes.title}>
Explore new places
</Typography>
<Autocomplete>
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
classes={{ root: classes.inputRoot, input: classes.inputInput }}
placeholder="Search"
/>
</div>
</Autocomplete>
</Box>
</Toolbar>
</AppBar>
);
};
export default Header;

changing background color in drawer - MUI

i cannot change backgroundColor in Drawer component. I do as I found in other refs and it is not working for me. I created two classes
import { makeStyles } from '#mui/styles'
import { Drawer, Typography } from '#mui/material';
const drawerWidth = 240;
const useStyles = makeStyles({
drawer: {
width: drawerWidth,
},
drawerPaper: {
width: drawerWidth,
backgroundColor: "#fcba03"
},
});
export default function Sidebar() {
const classes=useStyles()
return (
<>
<Drawer
className={classes.drawer}
variant="permanent"
anchor="left"
classes={{paper: classes.drawerPaper},
{root:classes.drawerRoot}}
>
<div>
<Typography variant='h5'> Home </Typography>
</div>
</Drawer>
</>
)
}
thanks for answer!
You're not passing the classes in correct way. The classes prop expects an object with keys containing the class names from makeStyle hook. The correct syntax should be like
classes={{ paper: classes.drawerPaper, root: classes.drawerRoot }}
The updated code could be
import { makeStyles } from "#mui/styles";
import { Drawer, Typography } from "#mui/material";
const drawerWidth = 240;
const useStyles = makeStyles({
drawer: {
width: drawerWidth
},
drawerPaper: {
"&&": {
width: drawerWidth,
backgroundColor: "#fcba03"
}
}
});
export default function Sidebar() {
const classes = useStyles();
return (
<>
<Drawer
className={classes.drawer}
variant="permanent"
anchor="left"
classes={{ paper: classes.drawerPaper, root: classes.drawerRoot }}
>
<div>
<Typography variant="h5"> Home </Typography>
</div>
</Drawer>
</>
);
}
Note: && is added to increase the specificity of the applied styles to the paper.
Also, the support of makeStyles is going to be a legacy solution at sometime in future. If possible, you should probably look at the newer styling option provided in the mui v5.
Yes, this "improved" props like p, px, my, bgcolor etc are on the component listed above, but MUI expose for each of their components, a sx prop, that is an object that accept this kind of prop ! Also, I don't know if it could help, but you still can customize MUI components from the theme object if you want this style to be applied on all components occurences

target pseudo selectors in material ui

I'm wondering if there's a way to target psedo selectors (::before, ::after) in material ui?
For example, in a component like this?
const useStyles = makeStyles((theme) => ({
root: {
textAlign: 'center',
'&::before': {
content: '"blabla"'
},
'&::after': {
content: '"blabla"'
},
':before': {},
after: {}
}
}));
function App(props) {
const classes = useStyles();
return (
<Typography
className={{ root: classes.root, before: classes.before, after: classes.after }}>
{props.children}
</Typography>
);
}
I have created this sandbox project, you can check, things are working fine or correct me if I am missing something to understand your problem
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Typography from "#material-ui/core/Typography";
const useStyles = makeStyles(theme => ({
root: {
textAlign: "center",
"&::before": {
content: '"-"'
},
"&::after": {
content: '"-"'
}
}
}));
export default function App(props) {
const classes = useStyles();
return (
<Typography className={classes.root} {...props}>
Hello
</Typography>
);
}
I think you are using the className props in a wrong way, you have to pass the string, not an object.
classes props expect an object, we generally use classes props on the component which have exposed class names to override their inner styles, for example in case of Typography Component you can override root element style like this.
export default function App(props) {
const classes = useStyles();
return (
<Typography classes={{ root: classes.root }} {...props}>
Hello
</Typography>
);
}
so classes and classNames are two different things in Material-UI, but sometimes(when you want to apply the style to root element of component) both provide the same solution.
I have created one more Sandbox project with the second solution

Reference to theme's primary color instead of a specific color in MUI

Using ReactJS and MUI, I have a project in which I have changed the theme colors.
const newTheme = getMuiTheme({
fontFamily: 'Roboto, sans-serif',
palette: {
primary1Color: cyan500,
primary2Color: cyan700,
primary3Color: grey400,
accent1Color: amberA400,
accent2Color: grey100,
accent3Color: grey500,
textColor: darkBlack,
alternateTextColor: white,
canvasColor: white,
borderColor: grey300,
disabledColor: fade(darkBlack, 0.3),
pickerHeaderColor: cyan500,
clockCircleColor: fade(darkBlack, 0.07),
shadowColor: fullBlack,
},
});
// App class
render() {
return(
<ThemeProvider theme={newTheme}>
<Project />
</ThemeProvider>
)
}
Everything works as expected. Certain components, like buttons have the ability to set the color based on the primary prop. However, I have a component that uses an icon that needs the primary color. I can import the color and set it directly:
import React from 'react';
import ActionLock from 'material-ui/svg-icons/action/lock';
import {cyan500} from 'material-ui/styles/colors';
export default class LockIcon extends React.Component {
render() {
return(
<ActionLock color={cyan500} />
)
}
}
Is there some way to reference the theme's primary color, rather than setting the color in each component individually? Something like:
import React from 'react';
import ActionLock from 'material-ui/svg-icons/action/lock';
import {primary1Color} from 'somewhere';
export default class LockIcon extends React.Component {
render() {
return(
<ActionLock color={primary1Color} />
)
}
}
If you're using React v16.8.0 and Material-UI v3.5.0 or greater, you can utilize the useTheme() hook:
import { useTheme } from '#material-ui/core/styles';
function LockIcon = () => {
const theme = useTheme();
return (
<ActionLock color={theme.palette.primary1Color} />
}
Yes you have!
using muiThemeable..
import muiThemeable from 'material-ui/styles/muiThemeable';
class LockIcon extends React.Component {
render() {
return(
<ActionLock color={this.props.muiTheme.palette.primary1Color} />
)
}
}
export default muiThemeable()(LockIcon)
from material-ui docs
Adding how to access theme colors in material-ui v1.0.0 (currently beta) Using withTheme component.
Also check the following Example.
import React, {Component} from 'react';
import { withTheme } from 'material-ui/styles';
class WithThemeExample extends Component {
render() {
const { theme } = props;
const {primary, secondary} = theme.palette.text;
return (
<div>
<div style={{color: primary}}>Hi in Primary color</div>
<div style={{color: secondary}}>Bye in Secondary color</div>
</div>
);
}
}
export default withTheme()(WithThemeExample);
If you're using system properties, you can define a string path of the Palette object to the color value like below:
<Box sx={{ color: "primary.main" }}>primary.main</Box>
<Box sx={{ color: "secondary.main" }}>secondary.main</Box>
<Box sx={{ color: "error.main" }}>error.main</Box>
<Box sx={{ color: "warning.main" }}>warning.main</Box>
<Box sx={{ color: "info.main" }}>info.main</Box>
<Box sx={{ color: "success.main" }}>success.main</Box>
<Box sx={{ color: "text.primary" }}>text.primary</Box>
<Box sx={{ color: "text.secondary" }}>text.secondary</Box>
<Box sx={{ color: "text.disabled" }}>text.disabled</Box>
The above is the same as:
<Box sx={{ color: theme => theme.palette.primary.main }}>primary.main</Box>
<Box sx={{ color: theme => theme.palette.secondary.main }}>secondary.main</Box>
<Box sx={{ color: theme => theme.palette.error.main }}>error.main</Box>
<Box sx={{ color: theme => theme.palette.warning.main }}>warning.main</Box>
<Box sx={{ color: theme => theme.palette.info.main }}>info.main</Box>
<Box sx={{ color: theme => theme.palette.success.main }}>success.main</Box>
<Box sx={{ color: theme => theme.palette.text.primary }}>text.primary</Box>
<Box sx={{ color: theme => theme.palette.text.secondary }}>text.secondary</Box>
<Box sx={{ color: theme => theme.palette.text.disabled }}>text.disabled</Box>
The example using the callback is more verbose but is type-safe, the shorter one with only string is quicker and good when prototyping, but you may want to store the string in a constant to prevent any typo errors and help the IDE refactor your code better.
Live Demo
Ok if you are using material-ui version greater than 4, then the above solution might not work for you. Follow the below's code
import { withTheme } from '#material-ui/core/styles';
function DeepChildRaw(props) {
return <span>{`spacing ${props.theme.spacing}`}</span>;
}
const DeepChild = withTheme(DeepChildRaw);
Reference: https://material-ui.com/styles/advanced/
With react hooks, now you don't need to warp component in withTheme, just use useTheme:
import { useTheme } from '#material-ui/core/styles';
export default function MyComponent() {
const theme = useTheme();
return <span>{`spacing ${theme.spacing}`}</span>;
}
MUI V5
For the users of MUI v5, you can specify a function inside the sx css style directly, ex:
<Box sx={{ color: (theme) => theme.palette.primary1Color }} />
You can use the useTheme() hook and access the colors like the example below.
There are also some other color variants as well.
Mui 5:
import * as React from 'react';
import PropTypes from 'prop-types';
import { NavLink } from "react-router-dom";
import { useTheme } from "#mui/material/styles";
function VinNavLink(props) {
const theme = useTheme();
return (
<NavLink {...props} style={({ isActive }) => isActive ? { textDecoration: "underline", color: theme.palette.primary.main} : undefined}>{props.children}</NavLink>
);
}
export default VinNavLink;

Resources