I would like to create an external stylesheet using the MaterialUI 'makeStyles' and 'createStyles' like you can in React Native however, I don't know how to do it.
export const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
display: 'flex'
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
}
}),
);
So this would be called 'globalStyle.tsx' and then in any other file I can import it then do something like styles.root, etc. I've done it before in React Native but as said previously, I'm stuck on how to proceed.
React Native way: https://reactnative.dev/docs/stylesheet
First you should import the makeStyles like:
import { makeStyles } from "#material-ui/core/styles";
and then you can use it with something like this:
export const useStyles = makeStyles((theme) => ({
container: {
width: "100%",
},
}));
Related
Hi im try to place my code Breakpoints but in output show me error
import { makeStyles } from "#material-ui/styles";
const useStyle = makeStyles((theme)=>({
LogoLg:{
display:'none',
[theme.breakpoints.up('sm')]:{
display:'block'
}
}
}))
export default useStyle;
In the following stress test, you can update the theme color and the background-color property live:
const useStyles = makeStyles((theme) => ({
root: (props) => ({
backgroundColor: props.backgroundColor,
color: theme.color,
}),
}));
Using the theme context
Starting from v5, MUI no longer uses JSS as its default styling solution. If you still want to use the utilities exported by #mui/styles and they depend on the theme, you will need to provide the theme as part of the context. For this, you can use the ThemeProvider component available in #mui/styles, or, if you are already using #mui/material, you should use the one exported from #mui/material/styles so that the same theme is available for components from '#mui/material'.
import { makeStyles } from '#mui/styles';
import { createTheme, ThemeProvider } from '#mui/material/styles';
const theme = createTheme();
const useStyles = makeStyles((theme) => ({
root: {
color: theme.palette.primary.main,
}
}));
const App = (props) => {
const classes = useStyles();
return <ThemeProvider theme={theme}><div {...props} className={classes.root}></ThemeProvider>;
}
I have an older external component library which is still in the process of being migrated from MUI v4 to v5.
One of these components which is still using v4 needs to be used in a brand new codebase, which is set up for v5.
The problem is, this external component completely loses all of its styles when I attempt to use it in the newer codebase.
I would like to avoid having to install and set up MUI v4 o this new codebase. Did I miss something in the setup to be able to use components that are still on MUI v4?
Here is a rough sketch of my setup:
Older component from an external library
import { Grid, Button, makeStyles } from '#material-ui/core'
const useStyles = makeStyles((theme) => ({
gridRoot: {
// a bunch of styles
},
buttonRoot: {
// more styles
}
}))
const SomeOldComponent = () => {
const classes = useStyles()
return (
<Grid classes={{ root: classes.gridRoot }}>
I am an old component from an external library. I still use MUI v4.
<Button classes={{ root: classes.buttonRoot }}>Some button</Button>
</Grid>
)
}
export default SomeOldComponent
New codebase
import React from "react"
import { ThemeProvider } from "#mui/material/styles"
import { StylesProvider, createGenerateClassName } from '#mui/styles'
import { createTheme } from "./myTheme"
const classNameOpts = {
productionPrefix: '',
disableGlobal: true,
seed: 'mySeed',
}
const generateClassName = createGenerateClassName(classNameOpts)
export const ApplicationWrapper = ({ children }) => (
<StylesProvider generateClassName={generateClassName}>
<ThemeProvider theme={createTheme()}>{children}</ThemeProvider>
</StylesProvider>
)
export default ApplicationWrapper
Usage of the older component in the new codebase
The issue I have here is that in SomeOldComponent, none of its styles set in useStyles are being applied.
import { Grid, Button } from '#mui/material'
import SomeOldComponent from 'external-library'
const MyComponent = () => {
return (
<Grid>
I am a new component in a new MUI v5 only codebase
<SomeOldComponent/>
<Button>Do something!</Button>
</Grid>
)
}
export default MyComponent
I'm studying MUI, and in the course, the instructor asks me to style just one component and not the entire theme.
For that, it uses the makeStyles function and spreads the theme.mixins.toolbar. The problem is when I do this, I have the following error:
TypeError: Cannot read properties of undefined (reading 'toolbar')
This course is apparently in version 4, and I am using version 5. Despite this, my code appears to follow the changes that the documentations asks for. So what could be causing this error?
app.js
import "./App.css";
import Header from "./components/ui/Header";
import { ThemeProvider } from "#material-ui/core/styles";
import theme from "./components/ui/Theme";
function App() {
return (
<ThemeProvider theme={theme}>
<Header />
</ThemeProvider>
);
}
export default App;
Theme.js
import { createTheme } from "#material-ui/core/styles";
const arcBlue = "#0B72B9";
const arcOrange = "#FFBA60";
export default createTheme({
typography: {
h3: {
fontWeight: 100,
},
},
palette: {
common: {
blue: `${arcBlue}`,
orange: `${arcOrange}`,
},
primary: {
main: `${arcBlue}`,
},
secondary: {
main: `${arcOrange}`,
},
},
});
header/index.jsx
import React from "react";
import AppBar from "#mui/material/AppBar";
import Toolbar from "#mui/material/Toolbar";
import useScrollTrigger from "#mui/material/useScrollTrigger";
import Typography from "#mui/material/Typography";
import { makeStyles } from "#material-ui/styles";
function ElevationScroll(props) {
const { children, window } = props;
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0,
target: window ? window() : undefined,
});
return React.cloneElement(children, {
elevation: trigger ? 10 : 0,
});
}
const useStyles = makeStyles((theme) => ({
toolbarMargin: { ...theme.mixins.toolbar },
}));
function Header() {
const classes = useStyles();
return (
<React.Fragment>
<ElevationScroll>
<AppBar color="primary">
<Toolbar>
<Typography variant="h3" component="h3">
Nome de teste
</Typography>
</Toolbar>
</AppBar>
</ElevationScroll>
<div className={classes.toolBarMargin} />
</React.Fragment>
);
}
export default Header;
Since you're using v5, change your ThemeProvider, createTheme and makeStyles import path from:
import { ThemeProvider, createTheme, makeStyles } from "#material-ui/core/styles";
To:
import { ThemeProvider, createTheme } from "#mui/material/styles";
import { makeStyles } from "#mui/styles";
#material-ui/core is v4 package and #mui/material is the v5 equivalent. The API from the 2 versions are not compatible. In v5, makeStyles is also moved to a legacy package called #mui/styles, if you are using MUI v5 in a new project, you should switch completely to styled/sx API as recommended by the MUI team.
Related answers
Difference between #mui/material/styles and #mui/styles?
Cannot use palette colors from MUI theme
MUI createTheme is not properly passing theme to MUI components
I created a project on CodeSandbox and it doesn't seem the problem in code.
I guess you need to check the version of package you installed in package.json file.
Here is the link to the CodeSandbox project and you can see the console.log message on console tab.
https://codesandbox.io/s/check-makestyle-eq67m?file=/src/components/ui/Header/index.js
I faced similar issue with Can not read properties of undefined, reading refs thrown by makeStyles. In my case it was mui v5 and the issue occurred after upgrading to React 18.
In my case it turned out I had some legacy makeStyles(()=>createStyles) wrapped in a manner:
const useStyles = (minWidth: number) =>
makeStyles((theme: Theme) => ...
I had to change it to:
const useStyles =
makeStyles((theme: Theme) => ...
Perhaps it will be useful for somebody else facing the issue.
Solution
Install #mui/styles
npm install #mui/styles
Change
import { ThemeProvider, createTheme } from "#material-ui/core/styles";
To
import { ThemeProvider, createTheme } from "#mui/material/styles";
And
import { makeStyles } from "#material-ui/styles";
To
import { makeStyles } from "#mui/styles";
And
<div className={classes.toolBarMargin} />
To
<div className={classes.toolbarMargin} />
I'm making a tricky nav component using MUI Persistent Drawers with a React + Next structure. In order to get the content shrinking thanks to the state change, I had to put the whole navigation system inside of the _app.js file instead of having it in a distinct component.
Even though it clearly works, I wonder if it'll not impact rendering and performance once built. The makeStyles((theme) seems to work just fine but is not highlighted in VScode, probably because I used both of makeStyles, useTheme and ThemeProvider in the same file, as below :
import { makeStyles, useTheme } from '#material-ui/core/styles';
import { ThemeProvider } from '#material-ui/core/styles';
const useStyles = makeStyles((theme) => ({ ...
(className example:) appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
}, ... etc
Was it a good idea to put it all together in _app.js, or do I need to refactor everything into a new component passing props to parent somehow ?
Thanks for considering, best regards to all of you
I recommend you to put your theme inside a folder theme/theme.js and use createMuiTheme then in your app.js wrap your whole component with the theme provider ! That would spread your theme across the app and let you use it where you want ! Is the convention we got with material-ui.
theme/theme.js:
import { createMuiTheme } from "#material-ui/core/styles"
export const themeObject = {
palette: {
primary: { main: "#333333" },
secondary: { main: "#FD8C7C" },
},
backgroundColor: {
primary: { main: "#FEF8F8" },
secondary: { main: "#FFFFFF" },
},
breakpoints: {
values: {
xs: 0,
sm: 600,
md: 960,
lg: 1280,
xl: 1920,
},
},
overrides: {
MuiDivider: {
root: {
backgroundColor: "#FFFFFF",
},
},
},
}
export default createMuiTheme(themeObject)
pages/app,js:
import React from "react"
import { ThemeProvider } from "#material-ui/styles"
import Box from "#material-ui/core/Box"
import defaultTheme from "../theme/theme"
const App = () => {
return (
<Box>
<ThemeProvider theme={defaultTheme}>
...
</ThemeProvider>
</Box>
)
}
export default App
component/SideBar.js:
import React from "react"
import { makeStyles } from "#material-ui/core/styles"
const useStyles = makeStyles((theme) => ({
drawer: {
width: theme.sidebar.width,
color: theme.palette.primary
flexShrink: 0,
whiteSpace: "nowrap",
"& .MuiDrawer-paper": {
top: "unset",
},
},
drawerClose: {
transition: theme.transitions.create("width", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: "hidden",
width: theme.spacing(7) + 1,
[theme.breakpoints.up("sm")]: {
width: theme.spacing(7) + 1,
},
},
expandButton: {
[theme.breakpoints.up("sm")]: {
marginLeft: theme.spacing(-2.5),
marginRight: theme.spacing(2.5),
},
},
}))
export default function Sidebar(props) {
const classes = UseStyles()
return (...)
}
In the SideBar you can see that i have use the theme.zindex.drawer who come from directly theme.js.
I also recommend you to go check this MUI THEMING that would let you dive into the theming more deeply !
I'm trying to create an AvatarGroup with MaterialUi, all my avatars obey a previously created style.
All, except the avatar automatically generated by AvatarGroup when the "max" parameter has been defined. :(
const styles = makeStyles((theme) => createStyles({
avatar: {
marginRight: theme.spacing(4),
borderWidth: '1px',
borderStyle: 'solid',
borderColor: grey[200],
width: theme.spacing(3),
height: theme.spacing(3)
}
}))
export default function GroupAvatars() {
const classes = styles();
const nameList = ['Alexandre', 'Regis', 'Leo', 'Thing', 'ola', 'que', 'tal']
const avatarList = nameList.map(name => {
return (<Avatar key={name}
className={classes.avatar}
alt={name}
/>)
})
return (
<AvatarGroup max={4} >
{avatarList}
</AvatarGroup>
);
}
it gives me this:
GroupAvatar with last avatar too big
as you can see the last avatar (+4) is way bigger than the others.
You can test the code on website like stackblitz.com using react:
stackblitz where you can test project
here are the import
import React from 'react';
import Avatar from '#material-ui/core/Avatar';
import { createMuiTheme } from '#material-ui/core/styles';
import { withStyles, WithStyles, createStyles, makeStyles, Theme } from '#material-ui/core/styles';
import { grey, blue } from '#material-ui/core/colors'
import AvatarGroup from '#material-ui/lab/AvatarGroup';
how do i make my avatar "+4" the same size as the other avatars ?
Target the avatar rule name for AvatarGroup instead of the individual Avatar components
<AvatarGroup max={4} classes={{avatar: classes.avatar}}>