Overriding input class in TextField using makeStyles - reactjs

When trying to override the padding property in TextField input using MakeStyles, a new class is created called .makeStyles-input which is priorotized under MuiOutlinedInput-root class.
How do I inject a property into the input class (not depending on whether the OutlineInput or FilledInput component is used, and without using the important css tag)?
import { TextField } from '#mui/material';
import { makeStyles } from '#mui/styles';
const useStyles = makeStyles({
input: {
padding: 0,
},
});
function CustomTextField(props) {
const classes = useStyles();
return (
<TextField
InputProps={{
classes: {
root: classes.input,
},
}}
{...props}
/>
);
}

I don't believe that MUI 4 allows for that level of customization on their TextField component.
My recommendation comes from the MUI (v4) docs, I would be to use the InputBase component to customize, or use one of the three input variants that do allow for more customization, namely the OutlinedInput, FilledInput or Input components.
TextField is an abstraction on top of those components, so you lose a bit of customization due to the fact that a lot of the props are decided for you.
Look at the Google Maps input form demo on MUI, it's a good starter for what you're trying to do.

Related

How to apply chakra-ui styles to custom components? (react-datepicker)

I'd like to define styles for my Datepicker component through the Chakra-ui styles.
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { chakra } from '#chakra-ui/react';
const StyledDatepicker = chakra(DatePicker);
I've used the chakra factory function to be able to give the StyledDatepicker some styles through props, as shown in the code above, but I'd like to define everything in a separate styles .ts file like I've done for the built-in chakra components.
I've made a Datepicker.ts file with some style definitions and added it to the overrides object which is exported here as styles:
const styles = extendTheme(overrides);
export { styles };
which is imported in App.tsx and assigned to the theme prop of my ChakraProvider.
I've made some custom components which was fine, though not exactly what I'm looking for, and I'm looking to change the styles of the header container, the element with classname react-datepicker__header - no examples of making a custom component for this on react-datepicker website. I know I can do it with CSS files, but I'd really like to do all of it in the styles file for consistency.
The answer turned out to be fairly straightforward, but imo, chakra could have made it a bit easier to learn about this possibility.
To target a css class, you just add the classname into your styles object like this:
const DatepickerStyles = {
baseStyle: {
color: 'black',
'.react-datepicker__header': {
background: 'white',
},
},
};
Then do something like this where you want to use the component (In my case, the datepicker, but this will work for any component):
function MyDatePickerComponent(props) {
const datepickerStyles = useStyleConfig('Datepicker');
return (
<Datepicker
__css={datepickerStyles}
//some required props omitted for simplicity
/>
);
}
You can use sx instead of __css, I use __css for readability.
For react-datepicker and my case of styling the header specifically, I had to use a custom calendarContainer component, where I also applied the style in a similar manner by using useMultiStyleConfig instead of useStyleConfig. Hope this can be of help to someone.

Material-UI styles overriding my styles cause of ordering

Hello there fellow programmers.
I am currently experiencing an issue with my own styles created using makeStyles(...). What's happening is; when I import my styles constant which is exported from another module, the style block is placed before the other MUI styles which causes mine to be overriden. I have not yet been able to find any solution to this what so ever and that is why I am here today, trying to figure out how I could possibly go my ways to fix this. Here's an image that contains the order of the style blocks that is playing with my mind currently.
PLEASE NOTE: The style block that's mine is the one with the data meta of makeStyles. Another thing is, I've attempted to use StylesProvider.
IMPORTANT: This only happens when uploaded. It works just fine on localhost, but this is the outcome of being uploaded to vercel.
Here's two examples of usages:
import { Theme } from '#material-ui/core';
import { makeStyles } from '#material-ui/core/styles';
const DarkTheme = makeStyles((theme: Theme) => ({
mdButton: {
backgroundColor: "#404040"
},
}));
export default DarkTheme;
import {Button} from '#material-ui/core';
import React from "react";
import DarkTheme from 'DarkTheme';
export default function Example() {
const styles = DarkTheme();
return (
<Button className={styles.mdButton}>
Example
</Button>
)
}
Any help is appreciated, thank you in advance.
As you may know, f you have two CSS classes applied to the same element with the same degree of specificity, then the winner will be the CSS class that is defined last within the document (based on the order of the elements in the , NOT the order of the class name strings in the class attribute of the element being styled). As: Material UI v4 makeStyles exported from a single file doesn't retain the styles on refresh
So, you can change order of imports. Import Button before import style.
Let try with what is different from:
import React from "react";
import {Button} from '#material-ui/core';
import DarkTheme from 'DarkTheme';
and
import React from "react";
import DarkTheme from 'DarkTheme';
import {Button} from '#material-ui/core';
makeStyles returns a function which must be called as a React hook. So please name it in consequence.
const useDarkTheme = makeStyles((theme: Theme) => ({
mdButton: {
backgroundColor: "#404040"
},
}));
export default useDarkTheme;
https://reactjs.org/docs/hooks-intro.html
If you don't want to use hooks you can check withStyles alternative: https://material-ui.com/styles/basics/#higher-order-component-api
You can also check how CSS injection works in material-ui https://material-ui.com/styles/advanced/#css-injection-order (tl;dr: order of makeStyles calls matter).

What exactly is makeStyles in material-ui? [duplicate]

This question already has answers here:
Internal implementation of "makeStyles" in React Material-UI?
(2 answers)
Closed 1 year ago.
I just started learning React material-ui and I found this makeStyles function, and they said it returns a Hook.
I remember from React hooks that a custom hook is made by wrapping a built-in hook. I tried looking inside makeStyles, and it has some interoperability and some css-in-javascript pattern.
I am really fed up with rules coming over and over again. For now can someone please tell me what is this makeStyle function and perhaps suggest a better approach to reading about material-ui.
Thank you good people of Stack Overflow.
If you are familiar with the older version of Material-UI, you might have used withStyles, to use your custom styles in MUI components.
withStyles is just a HOC(Higher Order Component), used as a wrapper, to assign the classes prop to your component. You can furthur use the classes object to assign specific classes to your DOM or MUI elements in your component.
makeStyles is just a successor, which returns a hook(to access the custom classes). Now this is only a modern-react way of doing things in order to avoid HOCs.
MUI v3.9.3
import { withStyles } from '#material-ui/core/styles';
const styles = {
root: {
backgroundColor: 'red'
},
};
class MyComponent extends React.Component {
render () {
return <div className={this.props.classes.root} />;
}
}
export default withStyles(styles)(MyComponent);
MUI v4.9.5
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
root: {
backgroundColor: 'red'
},
});
export default function MyComponent(props) {
const classes = useStyles(props);
return <div className={classes.root} />;
}

Reusing custom styles in material-ui

New to material-ui here and trying to work out the best way of using the css in js. I can see from the demo code that inserting styles as classes is pretty easy using 'withStyles' but if I do the following I'd need to re-create the 'grow' and 'defaultPadding' styles in every component.
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
import Paper from '#material-ui/core/Paper';
function Dashboard(props) {
const { classes } = props;
return (
<Paper className={classes.defaultPadding}>
Hello
</Paper>
);
}
const styles = theme => ({
grow: {
flexGrow: 1
},
defaultPadding: {
padding: theme.spacing.unit * 3 + 'px'
}
});
export default withStyles(styles)(Dashboard);
I could easily create a factory method in an external file that returns a massive object containing all my default styles but I'd need to be able to pass the existing theme to it if I want to use things like 'theme.spacing.unit'.
So, is there a way to create a bunch of re-usable styles of my own, using theme values, then import them into any component?
Bonus question: Is it possible to create nested objects so I can do things like this? ...
className={classes.layout.header}
I think creating an external factory method would work or you could also create a ThemeProvider to pass your theme to every component that needs the same styles.
In the Codesandbox I created two Dashboard components. One with styled-components just to show how a ThemeProvider works and the other component is using withStyles.
For withStyles factory I called it sharedStyles in the demo and with this you can create a new style object inside your components by calling it and spreading it to a new style (just if you need to add more styles).
Nesting inside styles seems not supported. You could create keys like layout.heading or flatten the object before using it (see code in the demo). Both not perfect and I wouldn't use it.
I'm personally prefering styled-components but you don't need to switch to it. You can look at the source code how they implemented it and use it in your code to pass the theme to your component.
The ThemeProvider is using React Context-Api.

Overriding with classes in material-ui v1.0.0-beta-1 shows "the key provided to the classes property is not implemented" warning

I'm trying to override the styling of Material-UI v1 components, using the overriding by classes method.
When I try to override a nested property, for example the :hover pseudo class on the root key I get the following warning:
Warning: Material-UI: the key `.MyButton-root-w:hover` provided to
the classes property object is not implemented in Button.
You can only overrides one of the following:
See for example:
import React from "react";
import { createStyleSheet, withStyles } from "material-ui/styles";
import Button from "material-ui/Button";
const buttonStyle = createStyleSheet("MyButton", {
root: {
backgroundColor: "#f99",
"&:hover": {
backgroundColor: "#99f"
}
}
});
export default withStyles(buttonStyle)(Button);
Or see it in action at https://codesandbox.io/s/gRgGrYvr
As the example button does get a different background color when hovering, I was wondering if this is an issue in Material-UI or if I don't yet fully grasp how to override its styling.
Thanks to #kybarg who helped me on Material-UI's Gitter I know how to fix this, see the CodeSandbox he made to help me.
The warning occurs because the classes property will next to the root key also contain a .MyButton-root-p:hover property which the Button obviously doesn't support. To solve this make sure you only pass the supported keys to the Button, for example by:
export default withStyles(buttonStyle)(({ classes, ...restProps}) => (
<Button classes={{ root: classes.root }} {...restProps} />
));

Resources