What is the correct way to extend MUI v5 component with additional components and styled utility? - material-ui

What is the correct way to extend build-in components of MaterialUI v5? What I'd like to do:
Style the build-in component
Make a wrapper on top of my styled component with additional components
The current code:
import {Box, Link, LinkProps} from '#mui/material';
import {styled} from '#mui/material/styles';
const StyledLink = styled(Link)<LinkProps>({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
color: '#6b7688',
fontWeight: 500,
fontSize: '12.8px',
textTransform: 'uppercase',
textDecoration: 'none',
'&:hover, &.Mui-focusVisible': {
color: '#313bac',
transition: 'all 0.3s ease-in-out',
// LinkHoverElement
'& .MuiBox-root': {
backgroundColor: '#313bac',
},
},
});
const LinkHoverElement = styled(Box)({
width: '5px',
height: '5px',
marginBottom: '5px',
borderRadius: '50%',
backgroundColor: 'transparent',
});
const MenuLink = ({children, ...restProps}: LinkProps) => {
return (
<StyledLink {...restProps}>
<LinkHoverElement />
{children}
</StyledLink>
);
};
export default MenuLink;
It works, I also may use all props ('sx' prop as well)
<MenuLink
sx={{mx: '1rem'}}
key={page}
href={`#${page}`}>
{page}
</MenuLink>
seems like a 'god object', I've read documentation and uses this articles:
Reusable component
styled()
but haven't found an complicated example and feel like the code above isn't a best practice
The codesandbox example

Related

MUI DataGrid - Need to Add custom styling property to the data-grid

This is what I'm getting on building
This is how I want the build to be
I'm using a template and its has a predefined style class for dataGrid which is being applied to all the data-grid throughout the template.
I need to add a custom styled component for my data-grid in-order to achieve the design on the IMG-2.
Dependencies: #emotion/styled
The code for customize data grid:
const StyledDataGrid = styled(DataGrid)(({ theme }) => ({
root: {
'& .MuiDataGrid-renderingZone': {
maxHeight: 'none !important',
},
'& .MuiDataGrid-cell': {
lineHeight: 'unset !important',
maxHeight: 'none !important',
},
'& .MuiDataGrid-root .MuiDataGrid-cell ': {
maxHeight: 'none !important',
minHeight: 'mpne !important'
},
'& .MuiDataGrid-virtualScrollerRenderZone .MuiDataGrid-row ' : {
maxHeight: 'none !important',
}
},
}));
Data-Grid:
<StyledDataGrid
rows={(temp.length === count ? rows : temp)}
columns={columns}
pageSize={20}
autoHeight
rowHeight={465}
getRowSpacing={getRowSpacing}
disableSelectionOnClick
getRowClassName={(params) => `super-app-theme--${params.row.qa_status} && ${params.row.pkg_status}`}
components={{ Toolbar: GridToolbar }}
/>
```
add a property in your <DataGrid> name sx :{} just like this
<DataGrid
columns={col}
rows={Players}
pageSize={10}
rowsPerPageOptions={[8]}
sx={{
p: 4,
fontSize: 16,
fontFamily: 'Montserrat',
font: 'center',
borderColor: 'primary.light',
'& .MuiDataGrid-cell:hover': {
color: 'primary.main',
},
}}
autoHeight
/>

Material UI Alerts using custom colors

Can I set a custom color for a MUI Alert component? The docs suggest that the only color options are the four that match the four severity props.
For MUI V5 in case someone is looking to change the background color in the theme this worked for me.
export const theme = createTheme({
components: {
MuiAlert: {
styleOverrides: {
standardSuccess: {
backgroundColor: 'green',
color: 'white'
},
standardError: {
backgroundColor: 'red',
color: 'white'
},
standardWarning: {
backgroundColor: 'orange',
color: 'white'
},
standardInfo: {
backgroundColor: 'grey',
color: 'black'
}
}
},
},
});
And is working by setting the variant:
<Alert severity="success">Success</Alert>
<Alert severity="error">Error</Alert>
<Alert severity="warning">Warning</Alert>
<Alert severity="info">Info</Alert>
It's possible. Quoting the API docs:
You can override the style of the component thanks to one of these
customization points:
With a rule name of the classes object prop.
With a global class name.
With a theme and an overrides property.
A crude example in this codesandbox
A simple approach would be:
const useStyles = makeStyles((theme) => ({
myAlert: {
color: "#ffffff",
backgroundColor: "#000000"
}
});
function MyCustomAlert() {
const classes = useStyles();
return (
<Alert severity="error" className={classes.myAlert}>
<AlertTitle>Error</AlertTitle>
{"I am an error message !"}
</Alert>
);
}
I guess another option, if you don't wanna deal with css classes, could be:
(using mui v5 and typescript)
first u define your styled component:
interface IAlert extends AlertProps {
background?: string
}
export const Alert = styled(MUIAlert)<IAlert>(({ background }) => ({
background,
}))
then, on your component that uses the Alert:
const Component = ({type}) => {
...
const CUSTOM_COLORS_MAPPING = {
success: palette.success[500],
info: palette.secondary[500],
error: palette.error[500],
warning: palette.warning[500],
}
return (
...
<Alert severity={type} background={CUSTOM_COLORS_MAPPING[type]}>
{message}
</Alert>
)

MaterialUI - global font settings

How do you change the default 16px browser font-size to 10px using Material UI? As I understand it, MUI uses Nomralize.css under the hood?
In the my theme file I have
export default createMuiTheme({
overrides: {
MuiCssBaseline: {
'#global': {
html: {
padding: '0',
},
},
},
},
typography: {
htmlFontSize: 10,
fontSize: 8,
fontFamily: [
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
].join(','),
fontWeight: 400,
},
})
but I don't know if this is right..
My app is also wrapped with CssBaseLine
ReactDOM.render(
<Provider store={store}>
<MuiThemeProvider theme={theme}>
<CssBaseline />
<App />
</MuiThemeProvider>
</Provider>,
document.getElementById('root'),
Is this correct? I remember the 62.5% trick and trying to accomplish something similar I guess
Your code is just fine and for future reference use use React DevTools to verify if your properties really apply or not (after React DevTools setup look for the ThemeProvider props).

Material-UI Style Override?

I'm updating my app from Material-UI v1 to v2. I'm trying to use a style override to set the color of a selected <BottomNavigationAction> element.
const styles = {
bottomNavStyle: {
position: 'fixed',
left: '0px',
bottom: '0px',
height: '50px',
width: '100%',
zIndex: '100'
},
'&$selected': {
color: "#00bcd4" //<==trying to add this color to selected items
},
};
class bottom_nav extends Component {
state = {
selectedIndex: -1,
};
handleChange = (event, value) => {
this.setState({value});
};
render() {
const { classes } = this.props;
return (
<Paper className={classes.bottomNavStyle}>
<BottomNavigation
value={this.props.selectedBottomNavIndex}
onChange={this.handleChange}
showLabels
>
<BottomNavigationAction
label="Appointments"
icon={theApptsIcon}
/>
<BottomNavigationAction
label="Contacts"
icon={theEmailIcon}
/>
<BottomNavigationAction
label="Video Call"
icon={theVideoCall}
/>
</BottomNavigation>
</Paper>
);
}
}
export default withStyles(styles)(bottom_nav);
But, this does not do anything to the color of selected items.
I've read the Material-UI docs on CSS in JS and JSS, but haven't quite gotten it yet. What is the correct syntax for this?
UPDATE
Based on a response to this thread I've tried this:
const styles = {
bottomNavStyle: {
position: 'fixed',
left: '0px',
bottom: '0px',
height: '50px',
width: '100%',
zIndex: '100'
},
actionItemStyle: {
'&$selected': {
color: "#00bcd4 !important"
},
},
}
[.....]
return (
<Paper className={classes.bottomNavStyle}>
<BottomNavigation
value={this.props.selectedBottomNavIndex}
onChange={this.handleChange}
showLabels
>
<BottomNavigationAction
label="Appointments"
icon={theApptsIcon}
className={classes.actionItemStyle}
/>
<BottomNavigationAction
label="Contacts"
icon={theEmailIcon}
className={classes.actionItemStyle}
/>
<BottomNavigationAction
label="Video Call"
icon={theVideoCall}
className={classes.actionItemStyle}
/>
</BottomNavigation>
</Paper>
);
}
...but have not yet gotten the new color to appear on the web page.
Your updated solution looks good, there are just a few small changes...
You need to include an empty .selected class in your styles rules.
const styles = {
// Root styles for `BottomNavigationAction` component
actionItemStyles: {
"&$selected": {
color: "red"
}
},
// This is required for the '&$selected' selector to work
selected: {}
};
You need to pass classes={{selected: classes.selected}} to BottomNavigationAction. This is required for the '&$selected' selector to work.
<BottomNavigation
value={value}
onChange={this.handleChange}
className={classes.root}
>
<BottomNavigationAction
classes={{
root: classes.actionItemStyles,
selected: classes.selected
}}
label="Recents"
value="recents"
icon={<RestoreIcon />}
/>
</BottomNavigation>
Live Example:
There are couple of things I would like to suggest.
1) Write the name of the component with first letter capitalized since it is not treated the same way if it is named with small first letter and with capitalized.
2) If there is no other way for your cs rule to be applied, if it is overridden always because of some css specificity, use !iportant at the end of the rule.
3) Try this type of nesting of css in jss:
const styles = {
bottomNavStyle: {
position: 'fixed',
left: '0px',
bottom: '0px',
height: '50px',
width: '100%',
zIndex: '100',
'&:selected': {
color: "#00bcd4"
},
},
};

Styling react-select v2 with material-ui - Replace Input component

I'm having an issue with replacing the Input component for react-select v2 with the Input component from Material UI.
I've made an attempt so far in the codesandbox below, but unable to invoke the filtering upon typing into the Input?
https://codesandbox.io/s/jjjwoj3yz9
Also, any feedback on the Option replacement implementation would be appreciated. Am I going about it the right way with grabbing the text of the clicked option and search for the Option object from my options list to pass to the selectOption function?
Much appreciated,
Eric
V1
refer the documentation from here : https://material-ui.com/demos/autocomplete/
it provides clear documentation about how to use react-select with material-ui
here is a working example for your question: https://codesandbox.io/s/p9jpl9l827
as you can see material-ui Input component can take react-select as inputComponent.
V2
It's almost same as the previous approach :
implement the Input component:
<div className={classes.root}>
<Input
fullWidth
inputComponent={SelectWrapped}
value={this.state.value}
onChange={this.handleChange}
placeholder="Search your color"
id="react-select-single"
inputProps={{
options: colourOptions
}}
/>
</div>
and then SelectWrapped component implementation should be:
function SelectWrapped(props) {
const { classes, ...other } = props;
return (
<Select
components={{
Option: Option,
DropdownIndicator: ArrowDropDownIcon
}}
styles={customStyles}
isClearable={true}
{...other}
/>
);
}
and I overrides the component Option and DropdownIndicator to make it more material and added customStyles also:
const customStyles = {
control: () => ({
display: "flex",
alignItems: "center",
border: 0,
height: "auto",
background: "transparent",
"&:hover": {
boxShadow: "none"
}
}),
menu: () => ({
backgroundColor: "white",
boxShadow: "1px 2px 6px #888888", // should be changed as material-ui
position: "absolute",
left: 0,
top: `calc(100% + 1px)`,
width: "100%",
zIndex: 2,
maxHeight: ITEM_HEIGHT * 4.5
}),
menuList: () => ({
maxHeight: ITEM_HEIGHT * 4.5,
overflowY: "auto"
})
};
and Option:
class Option extends React.Component {
handleClick = event => {
this.props.selectOption(this.props.data, event);
};
render() {
const { children, isFocused, isSelected, onFocus } = this.props;
console.log(this.props);
return (
<MenuItem
onFocus={onFocus}
selected={isFocused}
onClick={this.handleClick}
component="div"
style={{
fontWeight: isSelected ? 500 : 400
}}
>
{children}
</MenuItem>
);
}
}
please find the example from here: https://codesandbox.io/s/7k82j5j1qx
refer the documentation from react select and you can add more changes if you wish.
hope these will help you.