In my app I am using React material-ui and I am heavily relying on storybooks. However, I have some overrides of themes settings.
Here is the settings:
import { createMuiTheme } from '#material-ui/core/styles';
export const egColorScheme = {
darkGray: '#494949',
transparent: 'transparent',
white: '#FFF',
};
const edvengoFont = {
fontFamily: "'Montserrat', sans-serif",
};
export const edvengoTheme = createMuiTheme({
overrides: {
MuiCssBaseline: {
'#global': {
'#font-face': [edvengoFont],
},
},
},
typography: {
fontFamily: "'Montserrat', sans-serif",
},
});
Now, in some of the components when I create a storybook and wrapping with ThemeProvider it works perfectly fine. Like in this component:
import { createStyles, List, ListItem, ListItemIcon, ListItemText, Theme } from '#material-ui/core';
import Card from '#material-ui/core/Card';
import CardActions from '#material-ui/core/CardActions';
import CardContent from '#material-ui/core/CardContent';
import makeStyles from '#material-ui/core/styles/makeStyles';
import Typography from '#material-ui/core/Typography';
import React from 'react';
import { egColorScheme } from '../../../../utils/styles/edvengo-theme';
import { EgButtonOutlined } from '../EgButton';
import { EmailIcon, PhoneIcon, SkypeIcon } from '../Icons';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
actions: {
marginTop: '10px',
paddingBottom: '30px',
paddingLeft: '30px',
},
content: {
padding: '30px 30px 0',
},
itemIcon: {
minWidth: '16px',
paddingRight: '11px',
},
itemText: {
color: egColorScheme.darkGray,
fontSize: '14px',
fontStyle: 'normal',
fontWeight: 'normal',
letterSpacing: '0.02em',
},
list: {
marginTop: '10px',
},
root: {
backgroundColor: egColorScheme.white,
borderRadius: '10px',
width: '100%',
},
title: {
color: egColorScheme.darkGray,
fontSize: '22px',
fontStyle: 'normal',
fontWeight: 'bold',
lineHeight: '27px',
},
}),
);
export interface InPageContactBoxProps {
phone?: string;
email?: string;
skype?: string;
buttonUrl?: string;
}
export const InPageContactBox: React.FC<InPageContactBoxProps> = ({ phone, email, skype, buttonUrl }) => {
const styles = useStyles();
return (
<Card className={styles.root} elevation={0}>
<CardContent className={styles.content}>
<Typography gutterBottom variant="h5" component="span" className={styles.title}>
Contact Us
</Typography>
<List className={styles.list}>
{phone ? (
<ListItem component={'a'} href={`tel:${phone}`} disableGutters={true}>
<ListItemIcon className={styles.itemIcon}>
<PhoneIcon />
</ListItemIcon>
<ListItemText className={styles.itemText} primary={phone} />
</ListItem>
) : (
<></>
)}
{email ? (
<ListItem component={'a'} href={`mailto:${email!}`} target={'_blank'} disableGutters={true}>
<ListItemIcon className={styles.itemIcon}>
<EmailIcon />
</ListItemIcon>
<ListItemText className={styles.itemText} primary={email} />
</ListItem>
) : (
<></>
)}
{skype ? (
<ListItem component={'a'} href={`skype:${skype!}?chat`} disableGutters={true}>
<ListItemIcon className={styles.itemIcon}>
<SkypeIcon />
</ListItemIcon>
<ListItemText className={styles.itemText} primary={skype} />
</ListItem>
) : (
<></>
)}
</List>
</CardContent>
<CardActions className={styles.actions}>
<EgButtonOutlined href={buttonUrl}>Submit Message</EgButtonOutlined>
</CardActions>
</Card>
);
};
And here is it's storybook:
const contactBox = () => (
<ThemeProvider theme={edvengoTheme}>
<div style={{ width: '300px', border: '5px solid lightgray', backgroundColor: 'lightgray' }}>
<InPageContactBox
phone={text('Phone #', '+1 (778) 668-1811')}
email={text('Email', 'contact#edvengo.com')}
skype={text('Skype', 'shurik_a')}
buttonUrl={text('Button Url', 'http://google.coms')}
/>
</div>
</ThemeProvider>
);
storiesOf('Web|Common', module)
.addDecorator(withKnobs)
.add('Contact Box', contactBox);
The problem begins here...
One of my components look like this:
import { createStyles, Paper, Theme } from '#material-ui/core';
import Link from '#material-ui/core/Link';
import makeStyles from '#material-ui/core/styles/makeStyles';
import React from 'react';
import { egColorScheme } from '../../../../utils/styles/edvengo-theme';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
backgroundColor: egColorScheme.white,
borderRadius: '10px',
display: 'flex',
height: '100%',
overflow: 'hidden',
},
title: {
alignItems: 'center',
color: egColorScheme.darkGray,
fontSize: '22px',
fontStyle: 'normal',
fontWeight: 'bold',
lineHeight: '28px',
padding: '36px 23px',
textAlign: 'center',
textDecoration: 'none',
width: '100%',
},
}),
);
export interface TitleBlockProps {
title: string;
href?: string;
}
export const TitleBlock: React.FC<TitleBlockProps> = ({ title, href }) => {
const styles = useStyles();
return (
<Paper className={styles.root} elevation={0}>
<Link className={styles.title} href={href}>
{title}
</Link>
</Paper>
);
};
with a storybook as follows:
import { ThemeProvider } from '#material-ui/core/styles';
import { text, withKnobs } from '#storybook/addon-knobs';
import { storiesOf } from '#storybook/react';
import React from 'react';
import { edvengoTheme } from '../../../../utils/styles/edvengo-theme';
import { TitleBlock } from './TitleBlock';
const titleBlock = () => (
<ThemeProvider theme={edvengoTheme}>
<div style={{ width: '300px', border: '5px solid lightgray', backgroundColor: 'lightgray' }}>
<TitleBlock title={text('Title', 'Ontario')} href={text('Url', 'http://edvengo.com')} />
</div>
</ThemeProvider>
);
storiesOf('Web|Common', module)
.addDecorator(withKnobs)
.add('Title Block', titleBlock);
For some reason, the styling from the edvengoTheme are not applied. Specifically font-family.
What am I missing here?
I encountered a similar issue where my dev environment was not the same as the build/deployed version.
This article was helpful for config preferences using Storybook & Material UI.
Storybook/MaterialUI/StyledComponents
In short, some important storybook configuration should include:
styles-decorator.js
export const StylesDecorator = storyFn => (
<ThemeProvider theme={customTheme}>
<StylesProvider injectFirst>
{storyFn()}
</StylesProvider>
</ThemeProvider>
);
config.js
addDecorator(StylesDecorator)
configure(require.context('../src/stories', true, /\.stories\.js$/), module);
In your case, you may just be missing StyleProvider 'injectFirst' inside of your ThemeProvider
Related
I am mapping over an array and rendering a custom card component for each index in the array. However, I am receiving the error "Each child in a list should have a unique "key" prop" 1. Although, I am passing the index as the key. I have tried with a React.fragment and passing the index down to the card component and adding the key there. Both methods are still throwing the same error.
Main Component
import React from "react";
import { useRouter } from "next/router";
import { Button, Container } from "#mui/material";
import { makeStyles } from "#mui/styles";
import { InstructionsCard } from "../layout/directory";
import {
RiNumber1 as OneIcon,
RiNumber2 as TwoIcon,
RiNumber3 as ThreeIcon,
} from "react-icons/ri";
function InstructionSection() {
const router = useRouter();
const classes = useStyles();
const instructions = [
{
id: 1,
icon: OneIcon,
title: "step one",
text: [
"Navigate to the",
<Button
onClick={() => router.push("/requirements")}
size="small"
style={{ margin: "5px" }}
variant="outlined"
color="inherit"
>
requirements
</Button>,
"page for our most frequently asked questions and specific requirements before booking any activity. ",
],
},
{
id: 2,
icon: TwoIcon,
title: "step two",
text: [
"Find the activity you are interested in and read through the information carefully. Be sure to fully understand the,",
<Button
onClick={() => router.push("/#upgrades")}
size="small"
style={{ margin: "5px" }}
variant="outlined"
color="inherit"
>
entry fee
</Button>,
" and",
<Button
onClick={() => router.push("/#upgrades")}
size="small"
style={{ margin: "5px" }}
variant="outlined"
color="inherit"
>
upgrade
</Button>,
" packages",
],
},
{
id: 3,
icon: ThreeIcon,
title: "step three",
text: [
"Please, be sure to verify we are ",
<Button
onClick={() => router.push("/locations")}
size="small"
style={{ margin: "5px" }}
variant="outlined"
color="inherit"
>
located
</Button>,
" in your area. Select an experience, date, time-slot, toggle any upgrades, and continue through checkout.",
],
},
];
return (
<Container className={classes.root}>
{/* instructions iteration */}
{instructions.map((_instruction, index) => {
return (
<React.Fragment key={index}>
<InstructionsCard item={_instruction} />
</React.Fragment>
);
})}
</Container>
);
}
// custom styles
const useStyles = makeStyles((theme) => ({
root: {
[theme.breakpoints.down("md")]: {
flexDirection: "column",
},
width: "100%",
display: "flex",
justifyContent: "space-evenly",
},
}));
export default InstructionSection;
Card Component
import { makeStyles } from "#mui/styles";
import { Card, CardContent, Typography, Divider } from "#mui/material";
const InstructionsCard = ({ item }) => {
const classes = useStyles();
const Icon = item.icon;
return (
<Card className={classes.root}>
<CardContent>
<Icon className={classes.icon} />
<Typography className={classes.title} variant="h5" component="h6">
{item.title.toUpperCase()}
</Typography>
<Divider className={classes.divider} />
<Typography
variant="subtitle1"
component="p"
sx={{ mb: 1.5 }}
color="text.secondary"
>
{item.text}
</Typography>
</CardContent>
</Card>
);
};
const useStyles = makeStyles((theme) => ({
root: {
[theme.breakpoints.down("md")]: {
margin: theme.spacing(4, 0, 4, 0),
},
background: theme.palette.primary.main,
borderRadius: theme.spacing(5),
padding: theme.spacing(2),
margin: theme.spacing(5),
width: "100%",
textAlign: "center",
boxShadow: `0px 0px 10px 10px ${theme.palette.offset.main}`,
},
icon: {
background: theme.palette.secondary.dark,
width: "50px",
height: "50px",
padding: "15px",
borderRadius: theme.spacing(5),
},
divider: {
background: theme.palette.secondary.dark,
padding: "2px",
width: "20%",
margin: theme.spacing(1, "auto", 1, "auto"),
},
title: {
fontWeight: 800,
},
}));
export default InstructionsCard;
Change like this in your main component
React.Fragment we need to use One time it can't use multiple time
return (
<Container className={classes.root}>
<React.Fragment>
{instructions.map((_instruction, index) => {
<InstructionsCard key={index} item={_instruction} />;
})}
</React.Fragment>
</Container>
);
Thank You
I am trying to add font-feature-settings: 'pnum' on, 'lnum' on in material Ui makestyles React JS but it's giving me an error called unexpected token and how to pass backgroundColor props to change dynamically, below is my code
const useStyles=makeStyles({
root:{
backgroundColor: '#F8B817',
'&:hover': {
backgroundColor: "#F8B817",
},
width:'163px',
height:'50px',
borderRadius:'4px',
fontFamily: 'Manrope',
fontStyle: 'normal',
fontWeight: 'bold',
fontSize: '12px',
lineHeight: '170%',
fontFeatureSettings: 'pnum' on, 'lnum' on;
},
})
here is the button of material UI
<Button className={classes.root} disableRipple><p>{buttonText}</p></Button>
and here is the buttonText props that I am passing
<Link style={{ textDecoration: 'none' }} to='/Dashboard'><Button onClick={handleSetLogIn} buttonText='Get Started'></Button></Link>
I think you missed quotations
import React from 'react';
import { Button, makeStyles } from '#material-ui/core';
const useStyles = (bgColor) =>
makeStyles({
root: {
backgroundColor: bgColor,
'&:hover': {
backgroundColor: bgColor,
},
width: '163px',
height: '50px',
borderRadius: '4px',
fontFamily: 'Manrope',
fontStyle: 'normal',
fontWeight: 'bold',
fontSize: '12px',
lineHeight: '170%',
fontFeatureSettings: `'pnum' on, 'lnum' on`,
},
});
export const CustomButton = (props) => {
const { buttonText, bgColor, ...rest } = props;
const classes = useStyles(bgColor)();
return (
<Button {...rest} className={classes.root} disableRipple>
<p>{buttonText}</p>
</Button>
);
};
And
<CustomButton buttonText={"Test"} bgColor={"red"} />
I am trying to populate ListItems( ListItemIcon and ListItemText) on Material UI mini Drawer in vertical align mode. Some how my ListItemText not aligning properly to the ListItemIcons.
Here is my styles:
link: {
textDecoration: "none",
"&:hover, &:focus": {
backgroundColor: theme.palette.background.yellow
}
},
linkActive: {
backgroundColor: theme.palette.background.light
},
linkIcon: {
marginRight: theme.spacing(1),
marginBottom: theme.spacing(4),
color: theme.palette.text.secondary + "99",
transition: theme.transitions.create("color"),
width: 24,
display: "flex",
justifyContent: "center"
},
linkText: {
marginTop: theme.spacing(1),
color: theme.palette.text.secondary + "CC",
transition: theme.transitions.create(["opacity", "color"]),
fontSize: 13,
display: "flex",
justifyContent: "flex-end"
}
Component
import React from "react";
import {
ListItem,
ListItemIcon,
ListItemText,
} from "#material-ui/core";
import { Link } from "react-router-dom";
import classnames from "classnames";
// styles
import useStyles from "./styles";
export default function SidebarLink({
link,
icon,
label,
location,
}) {
var classes = useStyles();
var isLinkActive =
link &&
(location.pathname === link || location.pathname.indexOf(link) !== -1);
return (
<ListItem
button
component={link && Link}
to={link}
className={classes.link}
>
<ListItemIcon
className={classnames(classes.linkIcon, {
[classes.linkIconActive]: isLinkActive
})}
>
{icon}
</ListItemIcon>
<ListItemText
classes={{
primary: classnames(classes.linkText, {
[classes.linkIconActive]: isLinkActive
})
}}
primary={label}
></ListItemText>
</ListItem>
);
}
How to align ListItems in vertical mode properly? I tried adding textAlign and alignItems to center to linkText css class but not them worked.
Any Help is Appreciated
Thanks,
react-router-dom Link uses html < a > tag under the hood.
< a > children will be displayed in column as default.
You just need to style your link properly:
link: {
display: 'flex',
flexDirection: 'row',
textDecoration: "none",
"&:hover, &:focus": {
backgroundColor: theme.palette.background.yellow
}
},
I using ReactJS and Material-UI in my web application. When I define props search for search bar, it's working except borderRadius. I checked Style tab in the Developer Tools (F12), border-radius property was overwritten but search bar not change. Please help me.
My code:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from './../actions/index';
import AppBar from '#material-ui/core/AppBar';
import Badge from '#material-ui/core/Badge';
import IconButton from '#material-ui/core/IconButton';
import Tooltip from '#material-ui/core/Tooltip';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import { withStyles } from '#material-ui/core/styles';
import InputBase from '#material-ui/core/InputBase';
import { fade } from '#material-ui/core/styles/colorManipulator';
import MenuIcon from '#material-ui/icons/Menu';
import MailIcon from '#material-ui/icons/Mail';
import HomeIcon from '#material-ui/icons/Home';
import QuestionIcon from '#material-ui/icons/QuestionAnswer';
import CartIcon from '#material-ui/icons/ShoppingCart';
import PersonIcon from '#material-ui/icons/Person';
import SearchIcon from '#material-ui/icons/Search';
const styles = theme => ({
root: {
width: '100%',
},
grow: {
flexGrow: 1,
},
appBar: {
zIndex: 1300,
},
//search props for search bar
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing.unit * 2,
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing.unit * 3,
width: 'auto',
},
},
searchIcon: {
width: theme.spacing.unit * 9,
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
inputRoot: {
color: 'inherit',
width: '100%',
backgroundColor: '#EAE9E8'
},
inputInput: {
paddingTop: theme.spacing.unit,
paddingRight: theme.spacing.unit,
paddingBottom: theme.spacing.unit,
paddingLeft: theme.spacing.unit * 10,
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('md')]: {
width: 200,
},
},
})
class Header extends Component {
onToggleNav = () => {
this.props.onToggleNav()
}
render() {
const { classes } = this.props;
return (
<header className={classes.root}>
<AppBar color="inherit" className={classes.appBar}>
<Toolbar>
<IconButton color="inherit" className={"remove_outline"} onClick={this.onToggleNav}>
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" noWrap>
Watch Shop
</Typography>
{/* search bar */}
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
placeholder="Search…"
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
/>
</div>
<div className={classes.grow} />
<div>
<Tooltip title="Trang chủ">
<IconButton className="remove_outline">
<HomeIcon />
</IconButton>
</Tooltip>
<Tooltip title="Hỗ trợ">
<IconButton className="remove_outline">
<QuestionIcon />
</IconButton>
</Tooltip>
<Tooltip title="Phản hồi">
<IconButton className="remove_outline">
<MailIcon />
</IconButton>
</Tooltip>
<Tooltip title="Tài khoản">
<IconButton className="remove_outline">
<PersonIcon />
</IconButton>
</Tooltip>
<Tooltip title="Giỏ đồ">
<IconButton className="remove_outline">
<Badge badgeContent={4} color="secondary">
<CartIcon />
</Badge>
</IconButton>
</Tooltip>
</div>
</Toolbar>
</AppBar>
</header>
);
}
}
const mapDispatchToProps = (dispatch, props) => {
return {
onToggleNav: () => {
dispatch(actions.isShowNav())
}
}
}
export default connect(null, mapDispatchToProps)(withStyles(styles)(Header));
Style tab in the Developer Tools
Style tab in the Developer Tools
Search bar:
Search bar
I'm currently using the material-ui react library and have copied the responsive drawer component example.
Is there a possible way to separate the sidebar and header into a separate component and call the sidebar function and my own main content in the main section using the classes.content styling set in the sidebar component
<main className={classes.content}>
<Typography noWrap>{'You think water moves fast? You should see ice.'}
</Typography>
</main>
e.g my home function wants to use the side
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Drawer from 'material-ui/Drawer';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import List from 'material-ui/List';
import Typography from 'material-ui/Typography';
import IconButton from 'material-ui/IconButton';
import Hidden from 'material-ui/Hidden';
import Divider from 'material-ui/Divider';
import MenuIcon from 'material-ui-icons/Menu';
import { mailFolderListItems, otherMailFolderListItems } from './tileData';
const drawerWidth = 240;
const styles = theme => ({
root: {
width: '100%',
height: 430,
marginTop: theme.spacing.unit * 3,
zIndex: 1,
overflow: 'hidden',
},
appFrame: {
position: 'relative',
display: 'flex',
width: '100%',
height: '100%',
},
appBar: {
position: 'absolute',
marginLeft: drawerWidth,
[theme.breakpoints.up('md')]: {
width: `calc(100% - ${drawerWidth}px)`,
},
},
navIconHide: {
[theme.breakpoints.up('md')]: {
display: 'none',
},
},
drawerHeader: theme.mixins.toolbar,
drawerPaper: {
width: 250,
[theme.breakpoints.up('md')]: {
width: drawerWidth,
position: 'relative',
height: '100%',
},
},
content: {
backgroundColor: theme.palette.background.default,
width: '100%',
padding: theme.spacing.unit * 3,
height: 'calc(100% - 56px)',
marginTop: 56,
[theme.breakpoints.up('sm')]: {
height: 'calc(100% - 64px)',
marginTop: 64,
},
},
});
class ResponsiveDrawer extends React.Component {
state = {
mobileOpen: false,
};
handleDrawerToggle = () => {
this.setState({ mobileOpen: !this.state.mobileOpen });
};
render() {
const { classes, theme } = this.props;
const drawer = (
<div>
<div className={classes.drawerHeader} />
<Divider />
<List>{mailFolderListItems}</List>
<Divider />
<List>{otherMailFolderListItems}</List>
</div>
);
return (
<div className={classes.root}>
<div className={classes.appFrame}>
<AppBar className={classes.appBar}>
<Toolbar>
<IconButton
color="contrast"
aria-label="open drawer"
onClick={this.handleDrawerToggle}
className={classes.navIconHide}
>
<MenuIcon />
</IconButton>
<Typography type="title" color="inherit" noWrap>
Responsive drawer
</Typography>
</Toolbar>
</AppBar>
<Hidden mdUp>
<Drawer
type="temporary"
anchor={theme.direction === 'rtl' ? 'right' : 'left'}
open={this.state.mobileOpen}
classes={{
paper: classes.drawerPaper,
}}
onRequestClose={this.handleDrawerToggle}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
>
{drawer}
</Drawer>
</Hidden>
<Hidden mdDown implementation="css">
<Drawer
type="permanent"
open
classes={{
paper: classes.drawerPaper,
}}
>
{drawer}
</Drawer>
</Hidden>
<main className={classes.content}>
<Typography noWrap>{'You think water moves fast? You should see ice.'}</Typography>
</main>
</div>
</div>
);
}
}
ResponsiveDrawer.propTypes = {
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
};
export default withStyles(styles, { withTheme: true })(ResponsiveDrawer);
You can move separate styling into separate components by just moving the styling into the new React component. I've done your case as an example.
The main component:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Typography from 'material-ui/Typography';
const styles = theme => ({
content: {
backgroundColor: theme.palette.background.default,
width: '100%',
padding: theme.spacing.unit * 3,
height: 'calc(100% - 56px)',
marginTop: 56,
[theme.breakpoints.up('sm')]: {
height: 'calc(100% - 64px)',
marginTop: 64,
},
},
});
const Main = (props) => {
const { classes } = props;
return (
<main className={classes.content}>
<Typography noWrap>You think water moves fast? You should see ice.</Typography>
</main>
);
};
Main.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles, { withTheme: true })(Main);
The rest, using the extracted main component:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Drawer from 'material-ui/Drawer';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import List from 'material-ui/List';
import Typography from 'material-ui/Typography';
import IconButton from 'material-ui/IconButton';
import Hidden from 'material-ui/Hidden';
import Divider from 'material-ui/Divider';
import MenuIcon from 'material-ui-icons/Menu';
import { mailFolderListItems, otherMailFolderListItems } from './tileData';
const drawerWidth = 240;
const styles = theme => ({
root: {
width: '100%',
height: 430,
marginTop: theme.spacing.unit * 3,
zIndex: 1,
overflow: 'hidden',
},
appFrame: {
position: 'relative',
display: 'flex',
width: '100%',
height: '100%',
},
appBar: {
position: 'absolute',
marginLeft: drawerWidth,
[theme.breakpoints.up('md')]: {
width: `calc(100% - ${drawerWidth}px)`,
},
},
navIconHide: {
[theme.breakpoints.up('md')]: {
display: 'none',
},
},
drawerHeader: theme.mixins.toolbar,
drawerPaper: {
width: 250,
[theme.breakpoints.up('md')]: {
width: drawerWidth,
position: 'relative',
height: '100%',
},
},
});
class ResponsiveDrawer extends React.Component {
state = {
mobileOpen: false,
};
handleDrawerToggle = () => {
this.setState({ mobileOpen: !this.state.mobileOpen });
};
render() {
const { classes, theme } = this.props;
const drawer = (
<div>
<div className={classes.drawerHeader} />
<Divider />
<List>{mailFolderListItems}</List>
<Divider />
<List>{otherMailFolderListItems}</List>
</div>
);
return (
<div className={classes.root}>
<div className={classes.appFrame}>
<AppBar className={classes.appBar}>
<Toolbar>
<IconButton
color="contrast"
aria-label="open drawer"
onClick={this.handleDrawerToggle}
className={classes.navIconHide}
>
<MenuIcon />
</IconButton>
<Typography type="title" color="inherit" noWrap>
Responsive drawer
</Typography>
</Toolbar>
</AppBar>
<Hidden mdUp>
<Drawer
type="temporary"
anchor={theme.direction === 'rtl' ? 'right' : 'left'}
open={this.state.mobileOpen}
classes={{
paper: classes.drawerPaper,
}}
onRequestClose={this.handleDrawerToggle}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
>
{drawer}
</Drawer>
</Hidden>
<Hidden mdDown implementation="css">
<Drawer
type="permanent"
open
classes={{
paper: classes.drawerPaper,
}}
>
{drawer}
</Drawer>
</Hidden>
<Main />
</div>
</div>
);
}
}
ResponsiveDrawer.propTypes = {
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
};
export default withStyles(styles, { withTheme: true })(ResponsiveDrawer);
So, you can just pull the styling out with the React component that you're extracting. The docs give some more details about material-ui's styling system.