InputProps Material-UI in React - reactjs

I have to make the TextField in material-ui to be uppercase. Right now, I need to put inputProps={{ style: { textTransform: 'uppercase' } }} in everything TextField. So I have define a theme in my react app for this and I wanted something to look like this.
Please also check picture on how I do them
https://i.stack.imgur.com/lnukB.png
MuiTextField.js
export default {
root: {
textTransform: 'capitalize',
},
};

You can create a theme and override the textTransform to capitalize in every MuiInputBase class of your project, as below:
const theme = createMuiTheme({
overrides: {
MuiInputBase: {
input: {
textTransform: "uppercase"
}
}
}
});
then wrap your project in a ThemeProvider and pass theme as a prop to the ThemeProvider:
ReactDOM.render(
<ThemeProvider theme={theme}>
<Demo />
</ThemeProvider>,
document.querySelector("#root")
);
sandbox link
Using this method, you no longer need to manually add textTransform: "capitalize" to every TextField component.

Related

Material-UI custom theming

I want to create a custom theme and customize some Material-UI components. I followed this customization tutorial provided by Material-UI. With this, I was able to do the following:
Creating costume theme:
//MUI THEMING
import {
createMuiTheme,
makeStyles,
ThemeProvider,
} from "#material-ui/core/styles";
import Theme from "./../../theme";
const useStyles = makeStyles((theme) => ({
root: {
backgroundColor: Theme.palette.primary.main,
},
}));
const theme = createMuiTheme({
normal: {
primary: Theme.palette.primary.main,
secondary: Theme.palette.secondary.main,
},
});
Using costume theme:
<ThemeProvider theme={theme}>
<AppBar
position="static"
classes={{
root: classes.root,
}}>
...
</AppBar>
</ThemeProvider>
As expected, this resulted in a costume colored AppBar:
However, when I tried the same with bottom navigation, -trying to change the default primary color-, I could not get it to work. I figured that based on the tutorial, I have to use "&$selected": in the create them to get it to work, but even with this my best result was something like this:
How do I change the primary color of Bottom Navigation with no label?
Sidenote: While I was searching for the solution, I stumbled on the default theme ovject. How can I access this, how can I overwrite it?
In my project, I create a global MUI theme to override the default theme. In makeStyle you can pass a param theme in the callback function like this to get the whole MUI theme object:
const useStyles = makeStyles(theme => {
console.log(theme) // print mui global theme object
return {...your classes here}
})
After that, copy this object to a new file like muiTheme.js to create your own theme. Change these values in this object that you want to override.
// muiTheme.js
import { createMuiTheme } from '#material-ui/core/styles'
const theme = createMuiTheme({
breakpoints: {
keys: ['xs', 'sm', 'md', 'lg', 'xl'],
values: {
xs: 0,
sm: 600,
md: 960,
lg: 1280,
xl: 1920,
},
},
...
})
export default theme
Then, in index.js, use ThemeProvider to override MUI's theme.
import { ThemeProvider } from '#material-ui/core/styles'
import muiTheme from './theme/muiTheme'
import App from './App'
const Root = () => (
<BrowserRouter>
<ThemeProvider theme={muiTheme}>
<App />
</ThemeProvider>
</BrowserRouter>
)
ReactDOM.render(<Root />, document.getElementById('root'))

Override Material UI Button Text

Material UI button defaults the text within the button to uppercase. I want to override the text with the button to be the same as I have typed and not be uppercase.
I have tried to override the styling by using texttransform - none
viewButton:
{
backgroundColor: "#00D2BC",
radius: "3px",
color: "#FFFFFF",
texttransform: "none"
}
<Button
className={classes.viewButton}
data-document={n.id}
onClick={this.handleView}
>
View Document
</Button>
Can anyone help with this.
Thanks
The only problem I see with the code in your question is that you have "texttransform" instead of "textTransform".
This aspect of the buttons is controlled by the theme (here, here, and here) so it is also possible to change this via the theme. I have demonstrated both approaches in the code below.
import React from "react";
import ReactDOM from "react-dom";
import {
makeStyles,
createMuiTheme,
MuiThemeProvider
} from "#material-ui/core/styles";
import Button from "#material-ui/core/Button";
const useStyles = makeStyles({
button: {
textTransform: "none"
}
});
const defaultTheme = createMuiTheme();
const theme = createMuiTheme({
typography: {
button: {
textTransform: "none"
}
}
});
function App() {
const classes = useStyles();
return (
<MuiThemeProvider theme={defaultTheme}>
<Button>Default Behavior</Button>
<Button className={classes.button}>Retain Case Via makeStyles</Button>
<MuiThemeProvider theme={theme}>
<Button>Retain Case Via theme change</Button>
</MuiThemeProvider>
</MuiThemeProvider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Here's a similar example but for v5 of Material-UI:
import React from "react";
import ReactDOM from "react-dom";
import { styled, createTheme, ThemeProvider } from "#material-ui/core/styles";
import Button from "#material-ui/core/Button";
const StyledButton = styled(Button)(`
text-transform: none;
`);
const defaultTheme = createTheme();
const theme1 = createTheme({
typography: {
button: {
textTransform: "none"
}
}
});
const theme2 = createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
textTransform: "none"
}
}
}
}
});
function App() {
return (
<ThemeProvider theme={defaultTheme}>
<Button>Default Behavior</Button>
<StyledButton>Retain Case Via styled</StyledButton>
<ThemeProvider theme={theme1}>
<Button>Retain Case Via theme change</Button>
</ThemeProvider>
<ThemeProvider theme={theme2}>
<Button>Retain Case Via alternate theme change</Button>
</ThemeProvider>
</ThemeProvider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
For those who don't wanna go an do this everywhere inside each components try global ovverrides,
const myTheme = createMuiTheme({
overrides: {
MuiButton: {
root: {
textTransform: 'none'
}
}
},
});
You make a theme object like so, and provide it to the theme provider which should wrap your app component in the index.js file
<ThemeProvider theme={myTheme}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</ThemeProvider>
Imports:
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
Per the docs, you should use the label class to override the text-transform property:
Use this style:
viewButtonLabel: { textTransform: "none" }
With this button:
<Button
className={classes.viewButton}
data-document={n.id}
onClick={this.handleView}
classes={{ label: classes.viewButtonLabel }}
>
This seems to work with V5
<Button sx={{ textTransform: 'none' }}>
Label
</Button>
https://mui.com/system/the-sx-prop/
I used Typography without playing with stying!
<Button>
<Typography style={{ textTransform: 'none' }}>Test Button</Typography>
</Button>
The answer of #Shamseer Ahammed provided the clue that finally solved this problem for me.
The use of the "overrides" property in the custom theme finally did the trick for me. I've spent days trying to do this with MuiTab instead of Button. I THINK this is the heuristic:
Use "overrides" in my theme to specify that I want to customize components
Use the component name (MuiButton or MuiTab) to specify a component to customize
Provide a key:value pair for the customization (textTransform: 'none').
I really wish the material-ui docs would make usage patterns like this more clear. I'd like there to be a middle-ground between trivial HelloWorld examples and the Component API nitty-gritty.
At least for me and my purposes, the answer from Shamseer Ahammed opened the door to my solution in a way that accepted answer did not.
import { createTheme, ThemeOptions } from '#mui/material/styles'
const defaultTheme: ThemeOptions = {
typography: {
button: {
textTransform: 'none',
},
},
}
export const lightTheme = createTheme({
palette: {
mode: 'light',
primary: {
main: '#ff2449',
light: '#ff6675',
dark: '#c40022',
},
},
...defaultTheme,
})
export const darkTheme = createTheme({
palette: {
mode: 'dark',
primary: {
main: '#f93c5b',
light: '#ff7588',
dark: '#bf0032',
},
},
...defaultTheme,
})
The MUI text transformation really sucks
I ended up changing the transformation for all the components which works great for me.
import { createTheme } from "#mui/material/styles";
import { ThemeProvider } from "#mui/material";
const theme = createTheme({
typography: {
allVariants: {
textTransform: "none",
},
},
});
<ThemeProvider theme={theme}>....</ThemeProvider>
instead of this long answer i will suggest a short answer
<Button>
<span style={{textTransform: 'none'}}>View Document</span>
</Button>

Styled-components - Override part of theme

I'm using styled-components to handle my styling in a react app.
Using the ThemeProvider wrapper, I'm able to get access to my theme in all of my styled components
However, i was wondering if it was possible to override just a part of the theme.
Here's a quick example:
Let's say I got the following theme:
const theme = {
color: 'red';
backgroundColor: 'blue';
}
I pass it to my app:
<ThemeProvider theme={theme}>
<MyStyledComponent>
<p>Hi</p>
<MyStyledComponent>
</ThemeProvider>
MyStyledComponent is a styled div which receives my theme:
import styled, { css } from 'styled-components'
const StyledButton = styled.button`
${props => ({
color: props.theme.color,
background-color: props.theme.backgroundColor,
})}
`
export default StyledButton
If I display this, I will have a blue div with some red text in it.
Now, if I use the following:
<ThemeProvider theme={theme}>
<MyStyledComponent theme={{color: 'green',}}>
<p>Hi</p>
<MyStyledComponent>
</ThemeProvider>
My text will turn green, BUT, no more blue background-color.
Is there a generic way to make sure that custom themes only override the properties that are found in both theme objects ?
The theme used by MyStyledComponentgets indeed totally overridden by the closest ThemeProvider defined.
Previous solution works well but to avoid to duplicate everywhere {{...theme.color, color: 'green'}} for instance, one can create a small wrapper:
const WithMainTheme = ({ theme: localTheme, children, ...props }) => {
return (
<ThemeProvider theme={{ ...theme, ...localTheme }}>
{React.cloneElement(children, props)}
</ThemeProvider>
);
};
which will allow you to write :
<WithMainTheme theme={{ color: "green" }}>
<MyStyledComponent>Hi</MyStyledComponent>
</WithMainTheme>
to get your button with color: green
See this for a running example
you can just do like normal Object in JS using spread operator and overriding the ones you want at the end.
<ThemeProvider theme={theme}>
<MyStyledComponent theme={{...theme,color: 'green'}}>
<p>Hi</p>
<MyStyledComponent>
</ThemeProvider>

Material-UI React: Global theme override for Paper component

I have a React app built with the latest Material-UI component library.
I use many instances of the Paper component. I want to apply margins and padding to all them at once, without manually repeating this process for every instance.
I looked up the Material-UI documentation on the topic, and from what I can tell, the following code should correctly override how Paper looks:
const theme = createMuiTheme({
overrides: {
Paper: {
root: {
padding: '10px',
marginBottom: '10px',
},
},
},
});
Below is where overridden style should apply:
<ThemeProvider theme={theme}>
{/* ... */}
<Paper>
Content goes here
</Paper>
{/* ... */}
</ThemeProvider>
But the overridden values aren't being applied. Any suggestions as to what's going on?
Thanks!
in your App.js add (please note MuiPaper and not Paper):
const theme = createMuiTheme({
overrides: {
MuiPaper: {
root: {
padding: '10px',
marginBottom: '10px'
},
},
}
});
at the same App.js file, wrap your HTML:
class App extends Component {
render() {
return (
<MuiThemeProvider theme={theme}>
<div className="App">
<YourComponent1 />
<YourComponent2 />
...
</div>
</MuiThemeProvider>
);
}
}
this way, any Paper component rendered by React will have your CSS.
BTW, I created MUI schematics module which adds Material UI support, generates several Material UI components automatically and adds general theme rules in App.js. You are welcome to take a look / try it...
You can also use your CssBaseline component if you're already using it for global reset...all depends on how you're structuring your theme.
Eg below is from the Mui docs:
<CssBaseline.js>
const theme = createMuiTheme({
overrides: {
MuiCssBaseline: {
'#global': {
html: {
WebkitFontSmoothing: 'auto',
},
},
},
},
});
// ...
return (
<ThemeProvider theme={theme}>
<CssBaseline />
{children}
</ThemeProvider>
);
You can get more details from the docs here using CssBaseline to inject global theme overrides.
I found out the problem.
The internal component name used for CSS is MuiPaper, not simply Paper. The following produces the desired result:
overrides: {
MuiPaper: {
root: {
padding: '10px',
marginBottom: '10px',
},
},
},
createMuiTheme is depreciated in MUI5.
Instead, you should be using createTheme as follows:
export const myTheme = createTheme({
components:{
MuiPaper:{
defaultProps:{
sx:{
padding: '10px',
marginBottom: '10px'
}
}
}
}
})
Additionally, make sure that you wrap your app in the Theme component and add the CssBaseline component:
import { ThemeProvider } from '#mui/material';
import { myTheme } from './themes/my-theme';
import CssBaseline from '#mui/material/CssBaseline';
<ThemeProvider theme={myTheme}>
<CssBaseline />
<MyApp/>
</ThemeProvider>
Here is the official documentation for MUI5

Set the background color of a Snackbar in MUI

I am using a Snackbar component from MUI. At the moment the Snackbar appears in black. Do you know how I can change the color? Setting background-color only changes the color of the whole div in which the Snackbar is presented. It does not change the color of the Snackbar.
With material-ui 1.0 (or higher) you should override the root CSS class from the SnackbarContent component with the prop ContentProps.
Here is an example:
const styles = {
root: {
background: 'red'
}
};
class MySnackbar extends Component {
render() {
const { classes } = this.props;
return (
<Snackbar
ContentProps={{
classes: {
root: classes.root
}
}}
message={<span>Some message</span>}
/>
);
}
}
export default withStyles(styles)(MySnackbar);
If someone do not want to pass style as props, we can also write a class in a css file and assign it to the ContentProps, like this:
ContentProps={{
classes: {
root: 'errorClass'
}
}}
and in index.css file:
.errorClass { color: 'red' }
With the current material-ui version (4.3.0) there is a even simpler approach than the ContentProps way. Instead of the message attribute you can use a SnackbarContent as child and simply call style={} on it
<Snackbar
open={this.state.showSnackbar}
autoHideDuration={3000}
onClose={() => {this.setState({showSnackbar: false})}}
>
<SnackbarContent style={{
backgroundColor:'teal',
}}
message={<span id="client-snackbar">Hello World</span>}
/>
</Snackbar>
You have to set the bodyStyle property:
<Snackbar bodyStyle={{ backgroundColor: 'teal', color: 'coral' }} />
You can find more info about how you customize the snackbars in the documentation
The root component of the Snackbar only concerns about positioning itself correctly, if you want to change the appearance of the physical Snackbar, you need to target the SnackbarContent via ContentProps prop. In v5, you can use the sx to do that easily:
<Snackbar
ContentProps={{
sx: {
background: "red"
}
}}
Another way is to create a custom variant for your Snackbar:
import { createTheme, ThemeProvider } from "#mui/material/styles";
const theme = createTheme({
components: {
MuiSnackbar: {
variants: [
{
props: { variant: "trouble" },
style: {
"& .MuiSnackbarContent-root": {
background: "orange"
}
}
},
{
props: { variant: "bigTrouble" },
style: {
"& .MuiSnackbarContent-root": {
background: "red"
}
}
}
]
}
}
});
<Snackbar variant="bigTrouble"
To use with typescript, you also need to update the prop type of Snackbar:
declare module "#mui/material/Snackbar" {
interface SnackbarProps {
variant: "trouble" | "bigTrouble";
}
}
With MUI v5 the optimal option to customize Snackbar (background, text color or any other styles) is to use sx prop and specific classNames for variants:
<Snackbar
sx={{
'& .SnackbarItem-variantSuccess': {
backgroundColor: colors.primary, //your custom color here
},
'& .SnackbarItem-variantError': {
backgroundColor: colors.alert, //your custom color here
},
'& .SnackbarItem-variantWarning': {
backgroundColor: colors.attention, //your custom color here
},
'& .SnackbarItem-variantInfo': {
backgroundColor: colors.secondary, //your custom color here
},
}}
autoHideDuration={10000}
//...other props here>
</Snackbar>
The same approach can be applied to notistack library to customize their snackbar.

Resources