MUI v5 styles broken with makeStyles() hook - material-ui

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

Related

How to make only the text label 'FontWeight: Bold' on Tooltip EChartJS

I need help here from you guys, Is there a way to make the text label in my tooltip BOLD ?? I mean only the label.
I try using the fontWeight: 'bold' but all text on my tooltip is bold.
i just want the label bold, not the data.
this is my script
var echartsConfig = function() {
if( $('#e_chart_07').length > 0 ){
var eChart_07 = echarts.init(document.getElementById('e_chart_07'));
var option07 = {
legend: {
display: true,
position: 'top',
labels: {
boxWidth: 15,
fontColor: 'black'
}
},
color: ['blue','purple','orange','red'],
tooltip: {
show: true,
trigger: 'axis',
backgroundColor: '#fff',
borderRadius:10,
padding:10,
axisPointer:{
lineStyle:{
width:0,
}
},
textStyle: {
color: '#324148',
fontFamily: '"Poppins", sans-serif',
fontSize: 12,
// fontWeight: 'bold'
}
},
grid: {
top: '13%',
left: '3%',
right: '3%',
bottom: '3%',
containLabel: true
},
xAxis : [
{
type : 'category',
data : [<?php foreach($duta as $dba){
echo '"'.$dba->agj_month_name.' '.$dba->agj_year.'",';
}?>
],
axisLine: {
show:false
},
axisTick: {
show:false
},
axisLabel: {
textStyle: {
color: 'Black'
}
}
}
],
yAxis : [
{
type : 'value',
axisLine: {
show:false
},
axisTick: {
show:false
},
axisLabel: {
textStyle: {
color: 'Black'
}
},
splitLine: {
lineStyle: {
color: 'transparent',
}
}
}
],
series : [
{
name:'0-30 ',
type:'bar',
barMaxWidth: 30,
data:[<?php foreach($duta as $dba){
echo '"'.$dba->agj_030.'",';
}?>],
itemStyle: {
normal: {
barBorderRadius: [3, 3, 0, 0] ,
}
}
},
{
name:'31-60 ',
type:'bar',
barMaxWidth: 30,
data:[<?php foreach($duta as $dba){
echo '"'.$dba->agj_3160.'",';
}?>],
itemStyle: {
normal: {
barBorderRadius: [3, 3, 0, 0] ,
}
},
},
{
name:'61-90 ',
type:'bar',
barMaxWidth: 30,
data:[<?php foreach($duta as $dba){
echo '"'.$dba->agj_6190.'",';
}?>],
itemStyle: {
normal: {
barBorderRadius: [3, 3, 0, 0] ,
}
},
},
{
name:'>90 ',
type:'bar',
barMaxWidth: 30,
data:[<?php foreach($duta as $dba){
echo '"'.$dba->agj_more90.'",';
}?>],
itemStyle: {
normal: {
barBorderRadius: [3, 3, 0, 0] ,
}
},
}
]
};
eChart_07.setOption(option07);
eChart_07.resize();
}
<div id="e_chart_07" class="echart" style="height:294px;"></div>
you should use formatter for that. you can see the code below.
tooltip: {
show: true,
trigger: 'axis',
backgroundColor: '#fff',
borderRadius:10,
padding:10,
axisPointer:{
lineStyle:{
width:0,
}
},
textStyle: {
color: '#324148',
fontFamily: '"Poppins", sans-serif',
fontSize: 12,
// fontWeight: 'bold'
},
formatter: (params) => {
let dataStr = `<div>${params[0].name}</div>`;
console.log(params[0]);
params.forEach((item) => {
let valueCal = ((params[1].value/params[0].value)*100).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") == undefined ? "-" : ((params[1].value/params[0].value)*100).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
dataStr = `
<div><strong>Persentase</strong></div>
<div>
<i class="fa fa-circle" style="color:${item.color}"></i>
${params[1].seriesName} :
${valueCal}
</div>
`;
});
return dataStr;
},
},

MUIButton outlined style change using ThemeProvider

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>

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

How to display input values in <Text> instead of alert in react native expo?

How to display form's input value in json format instead of alert?
Like this:
{
'username':'abcd',
'password':'kkkk'
}
this is the code
import React, { Component } from 'react';
import { Alert, Button, Text, TouchableOpacity, TextInput, View, StyleSheet } from 'react-native';
export default class App extends Component {
state = {
email: '',
password: '',
};
onLogin() {
const { email, password } = this.state;
Alert.alert('Credentials', `email: ${email} + password: ${password}`);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.titleText}>Hi, Welcome To</Text>
<Text style={styles.titleText}>Momento</Text>
<TextInput
value={this.state.email}
keyboardType = 'email-address'
onChangeText={(email) => this.setState({ email })}
placeholder='email'
placeholderTextColor = 'white'
style={styles.input}
/>
<TextInput
value={this.state.password}
onChangeText={(password) => this.setState({ password })}
placeholder={'password'}
secureTextEntry={true}
placeholderTextColor = 'white'
style={styles.input}
/>
<TouchableOpacity
style={styles.button}
onPress={this.onLogin.bind(this)}
>
<Text style={styles.buttonText}> Sign Up / Login </Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'salmon',
},
titleText:{
fontFamily: 'Baskerville',
fontSize: 50,
alignItems: 'center',
justifyContent: 'center',
},
button: {
alignItems: 'center',
backgroundColor: 'powderblue',
width: 200,
height: 44,
padding: 10,
borderWidth: 1,
borderColor: 'white',
borderRadius: 25,
marginBottom: 10,
},
buttonText:{
fontFamily: 'Baskerville',
fontSize: 20,
alignItems: 'center',
justifyContent: 'center',
},
input: {
width: 200,
fontFamily: 'Baskerville',
fontSize: 20,
height: 44,
padding: 10,
borderWidth: 1,
borderColor: 'white',
marginVertical: 10,
},
});
Try this might help
state = {
inputData:'',
};
onLogin() {
const { email, password } = this.state;
const data = {};
data.email = email;
data.password = password;
this.setState({inputData: JSON.stringify(data) });
// Alert.alert('Credentials', `email: ${email} + password: ${password}`);
}
<Text>{this.state.inputData}</Text>