MUIButton outlined style change using ThemeProvider - material-ui

I wants to create 5 custom format for any type of button(variant=outlined/contained)
I found some articles to override existing or root component style like below
export const myTheme = createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
backgroundColor: colors.yellow[500]
},
outlined: {
backgroundColor: colors.orange[500]
,'&:hover': {
backgroundColor: colors.green[500],
}
}
},
},
}
})
I would like to create a set of styles to MuiButton Variant = outlined like below,
ButtonSubmit:{
backgroundColor: colors.lightBlue[500],
color: colors.cyan[100] //Text color
'&:hover': {
backgroundColor: colors.lightBlue[100]
}
}
ButtonCancel:{
backgroundColor: colors.Orange[500],
color: colors.cyan[100] //Text color
'&:hover': {
backgroundColor: colors.Orange[100]
}
}
ButtonNav:{
backgroundColor: colors.green[500],
color: colors.cyan[100] //Text color
'&:hover': {
backgroundColor: colors.green[100]
}
}
How to apply those styles to button variant outlined
<Button variant="outlined" size='small' sx={{ height: '30px'}}>ButtonSubmit</Button>
<Button variant="outlined" size='small' sx={{ height: '30px'}}>ButtonCacel</Button>
<Button variant="outlined" size='small' sx={{ height: '30px'}}>ButtonNav</Button>

Related

MUI v5 styles broken with makeStyles() hook

I am using MUI v5 with Next.js and I styled all my pages and components using makeStyles() hook. When my website loads, on initial render all the CSS are broken for 2 or 3 seconds.
I noticed MUI default styles are loaded first then my Custom CSS Loads.
I also used emotion and emotion cache but it didn't worked.
Below is the code how I Integrate MUI v5 With Next.js
_app.tsx
import Head from 'next/head'
import { AppProps } from 'next/app'
import { useEffect } from 'react'
import { ApolloProvider } from '#apollo/client'
import { ThemeProvider } from '#mui/material/styles'
import { SessionProvider } from 'next-auth/react'
import CssBaseline from '#mui/material/CssBaseline'
import client from '#/lib/apollo'
import { wrapper } from '#/redux/store'
import theme from '../theme'
import { CookiesProvider } from 'react-cookie'
const MyApp = (props: AppProps) => {
const { Component, pageProps } = props
const { session } = pageProps
useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector(`#jss-server-side`) as HTMLElement
if (jssStyles) {
jssStyles.parentElement?.removeChild(jssStyles)
}
}, [])
return (
<>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
<SessionProvider session={session}>
<ApolloProvider client={client}>
<CookiesProvider>
<Component {...pageProps} />
</CookiesProvider>
</ApolloProvider>
</SessionProvider>
</ThemeProvider>
</>
)
}
export default wrapper.withRedux(MyApp)
_document.tsx
import Document, { Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheets } from '#mui/styles'
import React from 'react'
import theme from '../theme'
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
<meta name="theme-color" content={theme.palette.primary.main} />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Pacifico|Raleway:100,400,400i,700|Roboto:300,400,500,700&display=swap"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
MyDocument.getInitialProps = async (ctx) => {
const sheets = new ServerStyleSheets()
const originalRenderPage = ctx.renderPage
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: [
...React.Children.toArray(initialProps.styles),
sheets.getStyleElement(),
],
}
}
theme.ts
import { createTheme, Theme, ThemeOptions } from '#mui/material'
import { red } from '#mui/material/colors'
const blueColor = `#0B72B9`
const orangeColor = `#FFBA60`
const greyColor = `#868686`
declare module '#mui/material/styles' {
interface CustomTheme extends Theme {
commonColors: {
blue: string
orange: string
}
tab: {
fontFamily: string
textTransform: string
fontSize: string
fontWeight: number
}
orangeButton: {
fontFamily: string
textTransform: string
fontSize: string
color: string
}
learnMoreButton: {
borderColor: string
color: string
borderWidth: number
textTransform: string
borderRadius: number
fontWeight: string
fontFamily: string
}
}
interface CustomThemeOptions extends ThemeOptions {
commonColors?: {
blue?: string
orange?: string
}
tab?: {
fontFamily?: string
textTransform?: string
fontSize?: string
fontWeight?: number
}
orangeButton?: {
fontFamily?: string
textTransform?: string
fontSize?: string
color?: string
}
learnMoreButton?: {
borderColor?: string
color?: string
borderWidth?: number
textTransform?: string
borderRadius?: number
fontWeight?: string
fontFamily?: string
}
}
export function createTheme(options?: CustomThemeOptions): CustomTheme
}
const theme = createTheme({
commonColors: {
blue: `${blueColor}`,
orange: `${orangeColor}`,
},
tab: {
fontFamily: `Raleway`,
textTransform: `none`,
fontSize: `1rem`,
fontWeight: 500,
},
orangeButton: {
fontSize: `1rem`,
fontFamily: `Pacifico`,
textTransform: `none`,
color: `white`,
},
learnMoreButton: {
borderColor: `${blueColor}`,
color: `${blueColor}`,
borderWidth: 2,
textTransform: `none`,
borderRadius: 50,
fontWeight: `bold`,
fontFamily: `Roboto`,
},
palette: {
primary: {
main: `${blueColor}`,
},
secondary: {
main: `${orangeColor}`,
},
error: {
main: red.A400,
},
},
typography: {
h5: {
fontWeight: 300,
},
h2: {
fontFamily: `Raleway`,
fontWeight: 700,
fontSize: `1.75em`,
color: `${blueColor}`,
lineHeight: 1.5,
},
h4: {
fontSize: `1.75rem`,
fontFamily: `Raleway`,
fontWeight: 700,
color: `${blueColor}`,
},
subtitle1: {
fontSize: `1.25rem`,
color: `${greyColor}`,
fontWeight: 300,
},
body1: {
fontSize: `1.25rem`,
color: `${greyColor}`,
fontWeight: 400,
},
caption: {
fontSize: `1rem`,
fontWeight: 300,
color: `${greyColor}`,
},
},
components: {
MuiInputLabel: {
styleOverrides: {
root: {
color: `${blueColor}`,
fontSize: `1rem`,
},
},
},
MuiInput: {
styleOverrides: {
root: {
fontSize: `1rem`,
fontWeight: 400,
color: `${greyColor}`,
'&.MuiInput-underline:after': {
borderBottom: `2px solid #000000`,
},
'&.MuiInput-underline:hover:before': {
borderBottom: `2px solid ${blueColor}`,
},
},
underline: {
'&:before': {
borderBottom: `2px solid ${blueColor}`,
},
},
},
},
},
})
export default theme
Hero.tsx (I styled all my component and pages like this)
/* eslint-disable #typescript-eslint/no-unsafe-call */
/* eslint-disable #typescript-eslint/no-unsafe-member-access */
/* eslint-disable #typescript-eslint/no-unsafe-assignment */
/* eslint-disable #typescript-eslint/no-unused-vars */
/* eslint-disable #typescript-eslint/no-explicit-any */
import { FC } from 'react'
import Lottie from 'react-lottie'
import Box from '#mui/material/Box'
import Button from '#mui/material/Button'
import Typography from '#mui/material/Typography'
import { makeStyles } from '#mui/styles'
import landingAnimation from '../../../animations/landing.json'
import ArrowIcon from '#mui/icons-material/ArrowForward'
const useStyles = makeStyles((theme?: any) => ({
mainContainer: {
display: `flex`,
justifyContent: `center`,
alignItems: `center`,
[theme.breakpoints.down(`md`)]: {
flexWrap: `wrap`,
},
width: `100%`,
},
heroText: {
[theme.breakpoints.down(`md`)]: {
fontSize: `1.6em`,
},
},
heroTextContainer: {
textAlign: `center`,
[theme.breakpoints.down(`md`)]: {
marginBottom: `1.2rem`,
},
},
learnButton: {
...theme.learnMoreButton,
fontSize: `0.9rem`,
height: 45,
width: 145,
},
learnButtonIcon: {
fontSize: `0.9rem`,
marginLeft: `0.3em`,
},
animationContainer: {
marginTop: `-28px`,
},
}))
const Hero: FC = (): JSX.Element => {
const classes = useStyles()
const defaultOptions = {
loop: true,
autoplay: true,
animationData: landingAnimation,
rendererSettings: {
preserveAspectRatio: `xMidYMid slice`,
},
}
return (
<Box component="div" className={classes.mainContainer}>
<Box className={classes.heroTextContainer} component="section">
<Typography className={classes.heroText} variant="h2">
Bringing West Coast Technologies
<br />
To The MidWest
</Typography>
<Button className={classes.learnButton} variant="outlined">
Learn More <ArrowIcon className={classes.learnButtonIcon} />
</Button>
</Box>
<Box className={classes.animationContainer} component="section">
<Lottie options={defaultOptions} height={`100%`} width={`100%`} />
</Box>
</Box>
)
}
export default Hero

useStyles not working as it should in mui5?

I am trying to custom style my icon adding a bigger font size, the background is working fine but the font size is not, I read that I can use important! but I want to know why it is not working as it has been working in version 4 .
const useStyles = makeStyles((theme: Theme) => ({
root: {
flexGrow: 1,
},
icon: {
fontSize: 140,
backgroundColor: 'red',
'&:hover': {
backgroundColor: 'red',
},
},
}));
<Box style={{ display: 'flex', alignItems: 'center' }}>
<EmojiObjectsIcon color='primary' className={classes.icon} onClick={switchTheme} />
</Box>
add px for fontSize like this :
const useStyles = makeStyles((theme: Theme) => ({
root: {
flexGrow: 1,
},
icon: {
fontSize: '140px',
backgroundColor: 'red',
'&:hover': {
backgroundColor: 'red',
},
},
}));
const PublicSidebar = () => {
const classes = useStyles();
return (
<Box style={{ display: 'flex', alignItems: 'center' }}>
<EmojiObjectsIcon color='primary' className={classes.icon} onClick={switchTheme} />
</Box>
)
}

Why doesn't Material UI use my custom theme palette colors?

I want to use a custom palette so that my site uses brand colors across all components. I want to be able to access these custom colors globally, including in makeStyles.
This is my theme file:
import { createMuiTheme } from '#material-ui/core/styles';
const theme = createMuiTheme({
palette: {
primary: {
main: '#467f0f'
},
},
});
export default theme;
This is my component:
import theme from './theme';
const useStyles = makeStyles(theme => ({
title: {
backgroundColor: theme.palette.common.white,
borderColor: theme.palette.primary.main,
borderRadius: theme.spacing(2),
borderStyle: 'solid',
borderWidth: theme.spacing(1),
color: theme.palette.primary.main,
fontSize: theme.spacing(4),
margin: theme.spacing(2, 'auto'),
padding: theme.spacing(1),
textAlign: 'center',
[theme.breakpoints.up('sm')]: {
fontSize: theme.spacing(8),
},
},
}));
function App(): JSX.Element {
const classes = useStyles();
return (
<ThemeProvider theme={theme}>
<Typography
className={classes.title}
variant='h1'
>
My App
</Typography>
</ThemeProvider>
);
}
export default App;
There are no errors being thrown or linter warnings or anything. But the color from my custom palette is not being used. What might I have missed along the way?
The reason it isn't working is because when your ThemeProvider is in the same component as your useStyles. So what is happening is you are trying to use your theme before it has actually been added to the rest of your app.
So what you might need to do is either import your ThemeProvider one level higher (I assume your index.js file), or have a child component inside ThemeProvider which renders your children, which is the example I have given below
import theme from './theme';
function App(): JSX.Element {
return (
<ThemeProvider theme={theme}>
<AppContent/>
</ThemeProvider>
);
}
export default App;
const useStyles = makeStyles(theme => ({
title: {
backgroundColor: theme.palette.common.white,
borderColor: theme.palette.primary.main,
borderRadius: theme.spacing(2),
borderStyle: 'solid',
borderWidth: theme.spacing(1),
color: theme.palette.primary.main,
fontSize: theme.spacing(4),
margin: theme.spacing(2, 'auto'),
padding: theme.spacing(1),
textAlign: 'center',
[theme.breakpoints.up('sm')]: {
fontSize: theme.spacing(8),
},
},
}));
function AppContent(): JSX.Element {
const classes = useStyles();
return (
<Typography
className={classes.title}
variant='h1'
>
My App
</Typography>
);
}
Also Rather then createMuiTheme try just createTheme It seems that it was renamed in one of the newer releases to make clearer
import { createTheme } from '#material-ui/core/styles';
const theme = createTheme({
palette: {
primary: {
main: '#467f0f'
},
},
});
export default theme;
And on another note. I would recommend not styling the typography that much other than things like color, fontSize, etc. Rather think about wrapping it in a Box and having that have the styles for the backgroundColor, borderRadius, etc

Override link color inside a tooltip?

I have a material ui tooltip component with a link component inside of it. I need to change the link colour. Is this possible?
I have tried the following, but it does not work:
Theme
MuiTooltip: {
tooltip: {
backgroundColor: "#222",
color: "#fff"
}
MuiLink: {
root: {
color: isLight(primaryColour) ? primaryColour : "#fff"
},
}
}
Reference the tooltip rule name with .MuiLink-root as descendant
const theme = createMuiTheme({
overrides: {
MuiTooltip: {
tooltip: {
backgroundColor: "#222",
color: "#fff",
"& .MuiLink-root": {
color: isLight(primaryColour) ? primaryColour : "#fff"
}
}
}
}
});

Material IU icon with rectangle background

I can't find any documentation on how to create an icon with rectangle backgrounds like here:
There are no props for <Icon /> or <SvgIcon /> that I can find that would do this out of the box. I can style them like that myself, but was wondering if there is an existing way.
You can use the useStyles to add colors to your elements:
const useStyles = makeStyles(theme => ({
root: {
"& > svg": {
margin: theme.spacing(1)
}
},
icon1: {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
borderRadius: theme.shape.borderRadius
},
icon2: {
backgroundColor: theme.palette.primary.main,
color: theme.palette.text.primary,
borderRadius: theme.shape.borderRadius
},
icon3: {
backgroundColor: theme.palette.text.primary,
color: theme.palette.primary.contrastText,
borderRadius: theme.shape.borderRadius
},
icon4: {
backgroundColor: theme.palette.text.secondary,
color: theme.palette.primary.contrastText,
borderRadius: theme.shape.borderRadius
}
}));
And inside your icon:
<div className={classes.root}>
<AddIcon fontSize="large" color="primary" className={classes.icon1} />
<AddIcon fontSize="large" color="primary" className={classes.icon2} />
<AddIcon fontSize="large" color="primary" className={classes.icon3} />
<AddIcon fontSize="large" color="primary" className={classes.icon4} />
</div>
Here is a working example: https://codesandbox.io/s/mui-icons-styling-8t4rb?file=/demo.js