How to use multiple CSS classes with MUI 5 SX prop? - javascript

Does anyone know how to use multiple CSS classes with MUI 5 SX prop? I created a base class that I want to use with my Box components but use a second class specifically for the text inside of the Box. Applying base class, such as sx={styles.baseBoxStyle} works but sx={styles.baseBoxStyle styles.customBoxFontStyle} returns an error. Full code snippet and sandbox provided below. Any assistance is greatly appreciated!
Sandbox: https://codesandbox.io/s/mui-5-styling-uqt9m?file=/pages/index.js
import * as React from "react";
import Box from "#mui/material/Box";
const styles = {
baseBoxStyle: {
backgroundColor: "red",
borderRadius: "20px 20px 20px 20px",
border: "1px solid black",
maxWidth: "150px",
margin: "20px",
padding: "10px"
},
customBoxFontStyle: {
color: "yellow",
fontWeight: "bold"
}
};
export default function Index() {
return <Box sx={styles.baseBoxStyle styles.customBoxFontStyle}>This is a test</Box>;
}

I had a similar problem and came up with this solution.
<Box sx={[styles.baseBoxStyle, styles.customBoxFontStyle]}>
This is a test
</Box>
https://codesandbox.io/s/sweet-blackwell-oqp9ph?file=/src/App.js:416-517

For a simple solution, can deconstruct the style objects and compile into one object.
<Box sx={{...styles.baseBoxStyle,...styles.customBoxFontStyle}}>This is a test</Box>

If you want combine 2 calsses, and you get one of them as props you should work like this
const componnent = (styles) => {
return (
<ListItem
sx={[
{
width: 'auto',
textDecoration: 'underline',
},
...(Array.isArray(styles) ? styles : [styles]),
]}
/>
)
}
You cannot spread sx directly because SxProps (typeof sx) can be an array

You can try to use classnames as its commonly used library, or you can just make string from these styles that you pass into sx sx={styles.baseBoxStyle+' '+styles.customBoxFontStyle}

I think you cant use sx with classes. I have not seen any example in documentation.

To build on Aleksander's answer, there is a section about merging sx in MUI official documentation.
import * as React from 'react';
import ListItem from '#mui/material/ListItem';
import FormLabel from '#mui/material/FormLabel';
import { SxProps, Theme } from '#mui/material/styles';
interface ListHeaderProps {
children: React.ReactNode;
sx?: SxProps<Theme>;
}
function ListHeader({ sx = [], children }: ListHeaderProps) {
return (
<ListItem
sx={[
{
width: 'auto',
textDecoration: 'underline',
},
// You cannot spread `sx` directly because `SxProps` (typeof sx) can be an array.
...(Array.isArray(sx) ? sx : [sx]),
]}
>
<FormLabel sx={{ color: 'inherit' }}>{children}</FormLabel>
</ListItem>
);
}
export default function PassingSxProp() {
return (
<ListHeader
sx={(theme) => ({
color: 'info.main',
...theme.typography.overline,
})}
>
Header
</ListHeader>
);
}

Related

How can i change TextField border-radius in Mui

I am trying to change mui TextField border radius but it's not working. Can anyone help me to solve this problem.
Here is my code:
<TextField variant="outlined" sx={{ borderRadius: 5 }} />
Can anyone fix it this?
override MuiOutlinedInput-root clasee
sx={{
".MuiOutlinedInput-root": {
borderRadius: 5
}
}}
Try this
<TextField
className="inputRounded"
placeholder="Search"
variant="outlined"
size="small"
/>
</div>
If you are looking for a more generic solution for all the textfields you can set the borderRadius for the Textfield in yourr theme. So you don't have to add and repeat the sx property on each one.
Here is the code in your theme file:
export const theme = createTheme({
components: {
MuiTextField: {
styleOverrides: {
root: {
'& .MuiOutlinedInput-root': {
borderRadius: 5,
},
},
},
}
}
});
Or you can create a styled component like this:
import styled from "styled-components";
import { TextField } from "#mui/material";
export const InputStyled = styled(TextField)`
& .MuiOutlinedInput-root {
border-radius: 10px;
}
`;
//Use it like this:
<InputStyled label="email" variant="standard" />

Can I word-break at a specific character with react native?

I'm using react native to create a category table.
Is there any way I can make the characters(texts) inside the table to line break at after or before a specific character?
for example : apple/banana/avocado
I want it to render like this (line break at after 'slashes') :
apple/banana/</ br>avocado
Thanks,
Yes, it is possible. Like in a normal react application you can use the following javascript functions:
Split your string on each "/", example:
var elements = yuourString.split(/\//)
Then you can use Map to render an object for each element, example:
elements.map(x => <SomeReactNativeComponent />);
You could take match instead of split by taking some non breaking character, a breaking character and other non breking character.
const names='banana/apple/mango/grapes';
const result=names.match(/([A-z]+\/[A-z]+)/g);
console.log(result)
After breaking the names into an array you can simply map them in react native
Expanding on my comment demo:
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
const string = 'apple/banana/avocado';
export default function App() {
return (
<View style={styles.container}>
<Text style={{ marginBottom: 10 }}>
Before Change:{'\n '} {string}
</Text>
<Text style={{ marginBottom: 10 }}>
After Change:{'\n '} {string.replaceAll('/', '\n ')}
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});

using theme.spacing inside theme definition

I have the following theme setup:
export const themeDefault = createTheme({
themeName: 'Default (Mortgage Hub)',
spacing: 4,
...typography,
palette,
components: {
MuiButton: {
styleOverrides: {
root: {
paddingLeft: theme.spacing(12),
paddingRight: theme.spacing(4),
border: '10px',
},
},
},
},
})
And I would like to use theme.spacing inside however, of course. Theme is not defined yet. I have tried to use makeStyles & useTheme however these are hooks. So of course they will not work.
Are you able to supply styleOverrides once the theme has been indicated?
The styleOverrides feature of the theme is extremely powerful and versatile. In the Overrides based on props portion of the documentation, you can find an example of specifying a callback within the styleOverrides which then gives you access to the component's props and state (via ownerState) and the theme.
Below is an example showing how the callback syntax gives you access to the theme as well as showing how you can leverage ownerState to do conditional styles based on the props passed to a component (e.g. based on whether or not startIcon was specified or which variant was used or any combination of interest).
import * as React from "react";
import Stack from "#mui/material/Stack";
import Button from "#mui/material/Button";
import { createTheme, ThemeProvider } from "#mui/material/styles";
import SaveIcon from "#mui/icons-material/Save";
const theme = createTheme({
themeName: "Default (Mortgage Hub)",
spacing: 4,
components: {
MuiButton: {
styleOverrides: {
root: ({ ownerState, theme }) => {
const conditionalStyles = {};
if (ownerState.startIcon !== undefined) {
conditionalStyles.paddingLeft = theme.spacing(6);
if (ownerState.variant === "outlined") {
conditionalStyles.border = "5px solid black";
conditionalStyles["&:hover"] = { border: "5px solid grey" };
}
} else {
conditionalStyles.paddingLeft = theme.spacing(4);
}
return {
...conditionalStyles,
paddingRight: theme.spacing(4)
};
}
}
}
}
});
export default function BasicButtons() {
return (
<ThemeProvider theme={theme}>
<Stack spacing={2} direction="row">
<Button variant="text">Text</Button>
<Button variant="contained">Contained</Button>
<Button variant="outlined">Outlined</Button>
<Button startIcon={<SaveIcon />} variant="contained">
Contained with startIcon
</Button>
<Button startIcon={<SaveIcon />} variant="outlined">
Outlined with startIcon
</Button>
</Stack>
</ThemeProvider>
);
}

Updating an element of a components style in React Native [duplicate]

This question already has answers here:
Passing Styles Based on Parent Component in React Native
(2 answers)
Closed 5 years ago.
I have a custom component called CardSection
import React from 'react';
import { View } from 'react-native';
const CardSection = (props) => {
return (
<View style={styles.containerStyle}>
{props.children}
</View>
);
};
const styles = {
containerStyle: {
borderBottomWidth: 1,
padding: 5,
backgroundColor: '#fff',
justifyContent: 'flex-start',
flexDirection: 'row',
borderColor: '#ddd',
position: 'relative'
}
};
export { CardSection };
When I instantiate this component from another class I would like to update one of the style elements while the others remain unchanged. The code below will only update the justifyContent element.
<CardSection style={{ justifyContent: 'space-between' }}>
The solution I have at the minute does not seem to be working and I would like to avoid duplicating the element with just a change to one of the style elements.
You could do the following:
//destruct props
const CardSection = ({ style, children }) => {
return (
// prop 'style' overrides standard containerStyle
<View style={[styles.containerStyle, style]}>
{children}
</View>
);
};
You can merge styles if you pass an array to styles:
const CardSection = (props) => {
return (
<View style={[styles.containerStyle, props.style]}>
{props.children}
</View>
);
};
They 'cascade' from left to right, meaning that latter styles in the array overwrite the former.
Here is the documentation for styling in react-native by default.

MUI customize button color?

I am struggling to modify button colors in MUI next (v1).
How would I set muitheme to behave similarity to bootstrap, so I could just use "btn-danger" for red, "btn-success" for green... ?
I tried with custom className but it doesn't work properly (hover color does't change) and it seems repetitive. What options do I have?
In MUI v5, this is how you create customized colors in your theme for your MUI Button. The primary and secondary colors are created the same way under the hood:
const { palette } = createTheme();
const { augmentColor } = palette;
const createColor = (mainColor) => augmentColor({ color: { main: mainColor } });
const theme = createTheme({
palette: {
anger: createColor('#F40B27'),
apple: createColor('#5DBA40'),
steelBlue: createColor('#5C76B7'),
violet: createColor('#BC00A3'),
},
});
Usage
<Button color="anger" variant="contained">
anger
</Button>
<Button color="apple" variant="contained">
apple
</Button>
<Button color="steelBlue" variant="contained">
steelBlue
</Button>
<Button color="violet" variant="contained">
violet
</Button>
If you're using typescript, you also need to add additional types for the colors you just defined:
declare module '#mui/material/styles' {
interface CustomPalette {
anger: PaletteColorOptions;
apple: PaletteColorOptions;
steelBlue: PaletteColorOptions;
violet: PaletteColorOptions;
}
interface Palette extends CustomPalette {}
interface PaletteOptions extends CustomPalette {}
}
declare module '#mui/material/Button' {
interface ButtonPropsColorOverrides {
anger: true;
apple: true;
steelBlue: true;
violet: true;
}
}
Live Demo
Related Answers
How to add custom MUI palette colors
Change primary and secondary colors in MUI
You can try this
<Button
style={{
borderRadius: 35,
backgroundColor: "#21b6ae",
padding: "18px 36px",
fontSize: "18px"
}}
variant="contained"
>
Submit
</Button>
I came up with this solution using Brendans answer in this thread. Hopefully it'll help someone in a similar situation.
import React, { Component } from 'react'
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles'
import Button from 'material-ui/Button'
import { red, blue } from 'material-ui/colors'
const redTheme = createMuiTheme({ palette: { primary: red } })
const blueTheme = createMuiTheme({ palette: { primary: blue } })
class Buttons extends Component {
render = () => (
<div className="ledger-actions-module">
<MuiThemeProvider theme={redTheme}>
<Button color="primary" variant="raised">
Delete
</Button>
</MuiThemeProvider>
<MuiThemeProvider theme={blueTheme}>
<Button color="primary" variant="raised">
Update
</Button>
</MuiThemeProvider>
</div>
)
}
There is a mistake with Bagelfp's answer, and some other things to consider;
First, 'error' is not a supported color theme in material-ui#next v1's Button component. Only 'default', 'inherit', 'primary' and 'secondary' are accepted by the color prop.
Here is the approach I have found to be the easiest so far. First, choose your two most common theme colors and place them at the root of your app.
import React from 'react';
import { Component } from './Component.js'
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
const theme = createMuiTheme({
palette: {
primary: 'purple',
secondary: 'green',
error: 'red',
},
});
export class App extends Component {
render() {
return (
<MuiThemeProvider theme={theme}>
<Component />
...
</MuiThemeProvider>
);
}
}
Then in your component, choose the theme with your desired color;
import React from 'react';
import Button from 'material-ui/Button';
export const Component = (props) => (
<div>
<Button variant="fab" color="primary">
I am purple, click me!
</Button>
</div>
)
If you need a third and fourth color, you can export Component.js with a new palette just like you did in App.js.
This is the only solution I have found that allows me to retain the darkened hover effect (none of the official override examples retain functioning hover). I really wish I could find a way to simply drop in a new theme color when calling Button, but for now this is the most simple way to do it.
EDIT: My new preferred method is to create a CustomButton component using styled-components and material-ui buttonbase. I also place the styled-components theme provider at the root of my app alongside my MuiThemeProvider. This gives me easy access to additional theme colors in all my styled-components without importing and dropping in more ThemeProviders. In the case of my CustomButton, I just give it a theme prop, which is passed right down to the css in styled(ButtonBase). See the styled-component docs for more info.
Try this:
import * as React from 'react';
import Button, { ButtonProps } from "#material-ui/core/Button";
import { Theme } from '#material-ui/core';
import { withStyles } from '#material-ui/styles';
const styles: (theme: Theme) => any = (theme) => {
return {
root:{
backgroundColor: theme.palette.error.main,
color: theme.palette.error.contrastText,
"&:hover":{
backgroundColor: theme.palette.error.dark
},
"&:disabled":{
backgroundColor: theme.palette.error.light
}
}
};
};
export const ButtonContainedError = withStyles(styles)((props: ButtonProps) => {
const { className, ...rest } = props;
const classes = props.classes||{};
return <Button {...props} className={`${className} ${classes.root}`} variant="contained" />
});
Now you have a ButtonContainedError to use anywhere.
And it is consistent with your theme.
Here is an example typescript implementation:
import React from "react";
import { createStyles, Theme, makeStyles } from "#material-ui/core/styles";
import capitalize from "lodash/capitalize";
import MuiButton, {
ButtonProps as MuiButtonProps
} from "#material-ui/core/Button";
export type ColorTypes =
| "primary"
| "secondary"
| "error"
| "success"
| "warning"
| "default"
| "inherit"
| "info";
type ButtonProps = { color: ColorTypes } & Omit<MuiButtonProps, "color">;
const useStyles = makeStyles<Theme>(theme =>
createStyles({
outlinedSuccess: {
borderColor: theme.palette.success.main,
color: theme.palette.success.main
},
outlinedError: {
borderColor: theme.palette.error.main,
color: theme.palette.error.main
},
outlinedWarning: {
borderColor: theme.palette.warning.main,
color: theme.palette.warning.main
},
outlinedInfo: {
borderColor: theme.palette.info.main,
color: theme.palette.info.main
},
containedSuccess: {
backgroundColor: theme.palette.success.main,
color: theme.palette.success.contrastText,
"&:hover": {
backgroundColor: theme.palette.success.dark
}
},
containedError: {
backgroundColor: theme.palette.error.main,
color: theme.palette.error.contrastText,
"&:hover": {
backgroundColor: theme.palette.error.dark
}
},
containedWarning: {
backgroundColor: theme.palette.warning.main,
color: theme.palette.warning.contrastText,
"&:hover": {
backgroundColor: theme.palette.warning.dark
}
},
containedInfo: {
backgroundColor: theme.palette.info.main,
color: theme.palette.info.contrastText,
"&:hover": {
backgroundColor: theme.palette.info.dark
}
}
})
);
const Button: React.FC<ButtonProps> = ({ children, color, ...props }) => {
const classes = useStyles();
const className = classes?.[`${props.variant}${capitalize(color)}`];
const colorProp =
["default", "inherit", "primary", "secondary"].indexOf(color) > -1
? (color as "default" | "inherit" | "primary" | "secondary")
: undefined;
return (
<MuiButton {...props} color={colorProp} className={className}>
{children}
</MuiButton>
);
};
Button.displayName = "Button";
export default Button;
with this you can do <Button variant="contained" color="success"> with autocomplete and warning free :)
Update:
In Material UI V5 this is achievable in a much more elegant way. You can just add a color to the palette and the button will automatically support it! Their documentation has a great example of how to do this: https://mui.com/customization/palette/#adding-new-colors
You can use theme.palette.getContrastText() to calculate the correct text color based on a background color value.
import { Button, makeStyles } from '#material-ui/core';
const useStyles = makeStyles((theme) => ({
deleteButton: {
// to make a red delete button
color: theme.palette.getContrastText(theme.palette.error.main),
background: theme.palette.error.main,
}
}));
export const DeleteButton = () => {
const classes = useStyles();
return (
<Button className={classes.deleteButton}>Delete</Button>
);
}
first try to install npm install #material-ui/styles the
apply styles according to material documentation, for react class component you can use below code:
import React, {Component} from "react";
import { styled } from '#material-ui/styles';
import Button from '#material-ui/core/Button';
const MyButton = styled(Button)({
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
border: 0,
borderRadius: 3,
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
color: 'white',
height: 48,
padding: '0 30px',
});
class AprinClass extends Component {
render() {
return (
<MyButton>Styled Components</MyButton>
)
}
}
export default AprinClass;
for more information with references please check my blog in medium.
https://medium.com/#farbodaprin/how-to-make-a-customisable-material-ui-button-a85b6534afe5
You could create a theme with palettes defined for each of their 3 supported intentions (primary, secondary, error), and then use the color prop on <Button> to use those. In your example the btn-danger could be <Button color='error'>
EDIT: Brendan's answer is correct here that error is not supported for Button. According to the documentation Button only supports intentions that "make sense for this component.", so only primary and secondary would work here.
From their docs (trimmed down a little here):
const theme = createMuiTheme({
palette: {
primary: purple,
secondary: red
}
});
function Palette() {
return (
<MuiThemeProvider theme={theme}>
<div>
<Button color="primary">{'Primary'}</Button>
<Button color="secondary">{'Secondary'}</Button>
</div>
</MuiThemeProvider>
);
}
See Brendan's Answer for a more realistic example of creating themes for your components.
The easiest way to change the button color is to add the "style" attribute. Here's an example of a green button I created:
import Button from '#material-ui/core/Button';
<Button
variant="contained"
color="primary"
style={{ backgroundColor: '#357a38' }}
>
Run
</Button>
From 2022/05:
According to the official Doc: Customize MUI with your theme, you need to use ThemeProvider and createTheme.
First, customize the primary color like this,
import {ThemeProvider, createTheme} from '#mui/material/styles';
const theme = createTheme({
palette: {
primary: {
main: '#000000',
},
},
});
Then wrap your App or anywhere your want with the ThemeProvider component, and set the color props of your Button component to primary.
function YourApp() {
// logic omitted
return (
<ThemeProvider theme={theme}>
<YourApp>
<Button color="primary">Click me</Button>
</YourApp>
</ThemeProvider>
);
}
I found out that !important works in the classes. (React Hooks)
const styles "...etc..." = (theme: Theme) => ({
buttonWarning: {
backgroundColor: theme.palette.warning.dark + '!important'
}
}))
Then in the button
const classes = styles();
<Button className={classes.buttonWarning}>Hello</Button>
Use This sx props it gives more understanding and also more relative to the MUI. in most of the MUI components, they use these props.
import {Button} from '#mui/material'
<Button variant="contained" sx={{
borderRadius: 35,
backgroundColor: "#21b6ae",
padding: "18px 36px",
fontSize: "18px",
**color:"white"**
}} >
elevation
</Button>
Export any color from '#mui/material/colors'; (Docs)
import { pink } from '#mui/material/colors';
and use like this
<Button variant="contained" sx={{ backgroundColor: pink[700] }}>Check</Button>

Categories