TextField has an InputProps prop to pass values down to the OutlinedInput. But I need to pass a className prop down to the InputBase, which is the root element of OutlinedInput. I don't want to do this at the theme/global level. Is there a way to do this?
const StyledTextField = withStyles({
root: {
'& .MuiInputBase-root': {
// apply your styles here
}
}
})(TextField);
const useStyles = makeStyles({
root: {
'& .MuiInputBase-root': {
// apply your styles here
}
}
});
const classes = useStyles();
<TextField classes={classes} />
Related
I am using Mui and Gatsby.
I have created the theme in a layout.js like so:
const Layout = ({ children, location, pageTitle, crumbs }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<>
<ThemeProvider theme={theme}>
<Header siteTitle={data.site.siteMetadata?.title || `Title`} />
<CssBaseline />
<Main >
<CustomBreadcrumbs
crumbLabel={pageTitle}
location={location}
crumbs={crumbs}
/>
{children}</Main>
<footer
style={{
marginTop: `2rem`,
}}
>
© {new Date().getFullYear()}, Built with
{` `}
Gatsby
</footer>
</ThemeProvider>
</>
)
}
I have a page component, that has some styles, and are trying to pass theme to page template but when I check the props from the page template Component, theme is undefined and I can also not use it in the styles object I have created.
Page template is like this:
class ProductDetail extends React.Component {
render() {
console.log(this.props)
const product = get(this.props.data, 'contentfulProduct')
const { classes } = this.props
const {
breadcrumb: { crumbs },
} = this.props.pageContext
let images = []
if (product.packagePhoto) {
images.push(product?.packagePhoto)
}
if (product.kibblePhoto) {
images.push(product?.kibblePhoto)
}
if (product.productPhoto) {
images.push(product?.productPhoto)
}
if (product.ambPhoto) {
images.push(product?.ambPhoto)
}
return (
<Layout location={this.props.location} pageTitle={`${product.brand.brandName} ${product.name}`} crumbs={crumbs}>
....some code here
</Layout>
)
}
}
export default withStyles(styles, { withTheme: true })(ProductDetail)
I can not use theme in styles object in page template:
const styles = theme => ({
root: {
width: '100%'
},
paragraph: {
marginBottom: '20px'
},
halfWidthParagraph:{
marginBottom: '20px',
width: '50%',
/* [theme.breakpoints.down('sm')]:{
width: '100%'
} */
}
})
How can I load the "theme" into the Page Component and use it in the styles object?
I currently have lots of dialogs and want to change DialogTitle to have Typography h5 heading. Currently this works:
<DialogTitle>
<Typography variant="h5">Create Exercise</Typography>
</DialogTitle>
But I want this to be applied to all dialogs without having to add use the typography component. I also have tried the following with createTheme, but this does not change the fontSize.
const theme = createTheme({
components: {
MuiDialogTitle: {
styleOverrides: {
root: {
// Set this to h5
fontSize: "1.5rem",
},
},
},
},
});
Modify the DialogTitle component as mention below 👇
import MuiDialogTitle from "#material-ui/core/DialogTitle";
import Typography from "#material-ui/core/Typography";
import { withStyles } from "#material-ui/core/styles";
const styles = (theme) => ({
root: {
margin: 0,
padding: theme.spacing(2),
},
});
const DialogTitle = withStyles(styles)((props) => {
const { children, classes, ...other } = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="h5">{children}</Typography>
</MuiDialogTitle>
);
});
export default DialogTitle;
use this component as DialogTitle, even you can modify the style and also able to add extra component into DialogTitle, like closing icon or some secondary title.
I have various resource components that sit inside the react-admin Admin component. The admin component has a custom layout. Each of the resource screens has a different primary colour though, to represent the section that you are in and the content type. How is it possible to pass a specific theme object variable of primary colour to each resource that is in then used inside my custom Layout?
<Admin
authProvider={AuthProvider}
dashboard={Dashboard}
dataProvider={graphQLProvider}
history={history}
layout={Layout}
title="Home"
<Resource name="User" options={{label: 'Administrators'}} list={UserList} show={UserShow} edit={UserEdit}
create={UserCreate} icon={UserIcon}/>
Should I be using the className prop which is available on 'every react-admin component' or is there a better way?
React-admin doesn't support this feature, but you can achieve it using a custom layout (see Replacing the appbar) and a listener on the history location to get the resource from the URL. Something like:
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { AppBar } from 'react-admin';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
posts: {
backgroundColor: 'red',
},
comments: {
backgroundColor: 'blue',
}
});
const MyAppBar = ({ children }) => {
const [resource, setResource] = useState();
const history = useHistory();
const classes = useStyles();
useEffect(() => {
const newResource = extractResourceFromPathname(history.location.pathname); // left as an exercise to the reader
if (newResource !== resource) {
setResource(newResource);
}
}, [history.location.pathname]);
return <AppBar className={classes[resource]} {...props} />
}
I have a header and want to style all of it's buttons differently than my global theme. I have tried using a child theme like:
<ThemeProvider
theme={(outerTheme) =>
_.merge(outerTheme, {
overrides: {
MuiButton: {
label: {
color: "#fff",
},
},
},
})
}
>
However, while I had expected this to override only MuiButton's in the child theme, it overrode them in them globally.
I know I can use makeStyles but, then, as far as I know, I have to reference it in all the child components which want to use the style. I'd like to wrap a higher level component and have all child components pick up the style. How is this done?
You can do this:
import Button from '#material-ui/core/Button';
import { purple } from '#material-ui/core/colors';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles((theme) => ({
header: {
"& button": {
marginRight: theme.spacing(1),
color: theme.palette.getContrastText(purple[500]),
backgroundColor: purple[500],
"&:hover": {
backgroundColor: purple[700],
},
},
},
});
function CustomHeader(props) {
const classes = useStyles();
return (
<div className={classes.header}>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button disabled>Button 3</Button>
</div>
)
};
Thinking of the concept of a SASS mixin, what would be the best approach to enable the re-use of style blocks that incorporate the current theme.
For example I have two components that import their respective styles:
Component 1
index
styles
Component 2
index
styles
Each component has a text block
Component 1
import { styles } from './styles'
....
<div className={classes.richText}>...</div>
Component 2
import { styles } from './styles'
....
<div className={classes.richText}>...</div>
The styles for richText are the same but I would rather not duplicate them in the imported styles file.
I would rather have a single file that exposes reusable CSS properties based on the theme.
The only way I can currently do this is by returning an object that I have passed the theme to e.g.
const RichText = (theme) => {
return {
fontWeight: 100,
color: theme.typography.body1.color
}
}
Then import this into the styles
Component 1
styles.js
import { RichText } from '../mixins/'
const styles = theme => ({
richText: {
...RichText(theme),
fontSize: '1rem'
}
Component 2
styles.js
import { RichText } from '../mixins/'
const styles = theme => ({
richText: {
...RichText(theme),
fontSize: '1.2rem'
}
Feels like there has to be a better way: utilising withTheme() maybe?
Let's say you want to custom a checkbox as below:
import { makeStyles } from '#material-ui/core/styles';
import CheckBox from '#material-ui/core/CheckBox';
const useStyles = makeStyles((theme) => ({
root: {
color: theme.status.danger,
'&$checked': {
color: theme.status.danger,
},
},
checked: {},
}));
function CustomCheckbox() {
const classes = useStyles();
return (
<Checkbox
defaultChecked
classes={{
root: classes.root,
checked: classes.checked,
}}
/>
);
}
And you want to reuse its style as many components as you can.
You have two options: ThemeProvider or export your custom style.
Changing the component's theme
Themes let you apply a consistent tone to your app. It allows you to customize all design aspects of your project in order to meet the specific needs of your business or brand.
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
import orange from '#material-ui/core/colors/orange';
const myTheme = createMuiTheme({
status: {
danger: orange[500],
},
});
export default function CustomStyles() {
return (
<ThemeProvider theme={myTheme}>
<CustomCheckbox />
</ThemeProvider>
);
}
Exporting your custom styles
Separate your components in a proper folder, i.e: ./assets/styles:
import { makeStyles } from '#material-ui/core/styles';
export const useCheckBoxStyles = makeStyles((theme) => ({
root: {
color: theme.status.danger,
'&$checked': {
color: theme.status.danger,
},
},
checked: {},
}));
And your components tree ./components:
import { useCheckBoxStyles } from './assets/styles';
function CustomCheckbox() {
const classes = useCheckBoxStyles();
return (
<Checkbox
defaultChecked
classes={{
root: classes.root,
checked: classes.checked,
}}
/>
);
}
References
https://material-ui.com/customization/theming