Material UI Avatar component sizes not changing - reactjs

I have this component
import React, { FC } from "react";
import { Avatar } from "#material-ui/core";
export interface AvatarProps {
alt?: string;
src: string;
variant?: "circle" | "rounded" | "square";
sizes?: string;
}
const Component: FC<AvatarProps> = (props: AvatarProps): JSX.Element => {
return <Avatar {...props}></Avatar>;
};
export default Component;
I am trying to set the sizes property but it is not changing. What exactly does it take value?

MUI 5
Using the sx prop provided by the library:
<Avatar sx={{ height: '70px', width: '70px' }}></Avatar>
...or my preferred method, create a styled component outside your functional component or class. Something like this:
const StyledAvatar = ({ children, ...props }) => (
<Avatar sx={{ height: '70px', width: '70px' }} {...props}>
{children}
</Avatar>
);
Usage:
<StyledAvatar alt="add other props as normal">
Children can be nested here
</StyledAvatar>;
Material UI 4 (Original Answer)
Scroll down to the sizes attribute of img and have a read.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img
Or just use makeStyles as seen in the documentation:
https://v4.mui.com/components/avatars/#SizeAvatars.js
Or another option is a simple inline style:
<Avatar style={{ height: '70px', width: '70px' }}></Avatar>

You can set the size with a classname and the theme.spacing from Material UI.
const useStyles = makeStyles((theme) => ({
sizeAvatar: {
height: theme.spacing(4),
width: theme.spacing(4),
},
}));
...
const classes = useStyles();
<Avatar src="/path/to/image" alt="Avatar" className={classes.sizeAvatar} />

You can try setting additional Avatar Props
<AvatarGroup
componentsProps={{
additionalAvatar: {
sx: {
height: 30,
width: 30,
background: "red"
}
}
}
}
max={2}>
....
Formatted by https://st.elmah.io

Related

How to create custom component based on the mui component

I want to create a custom component based on the MUI component. I read the documentation, but I didn't find how to do it.
There is a Badge component. It has root and badge slots. I want to redefine the slot styles in my custom component.
Here's what I tried to do, but it doesn't work
import { Badge, BadgeProps, styled } from '#mui/material';
const StyledBadge = styled(Badge, {
name: 'Badge',
slot: 'badge',
overridesResolver: (props, styles) => styles.badge,
})(({ theme }) => ({
height: '40px',
width: '40px',
borderRadius: '50%',
fontSize: '16px',
lineHeight: '24px',
backgroundColor: theme.palette.secondary.dark,
})) as typeof Badge;
export interface IDeliveryBadgeProps {
props: BadgeProps;
children: React.ReactNode;
}
export function DeliveryBadge({ children, ...props }: IDeliveryBadgeProps) {
return <StyledBadge {...props}>{children}</StyledBadge>;
}
export default DeliveryBadge;

How do I extend Material-UI Button and create my own button component

I am a React newbie. Using Material-UI / React, how can I create my own Button component? Ideally, I would like the component to encapsulate certain properties.
Here is my code.
export const Button = withSytles((theme) => ({
root: {
backgroundColor: theme.palette.primary.main,
minWidth: '100px',
}
}))(MaterialButton);
This code is working however, is there a way to have the component employ all of the properties when I use color="primary" to the Material-UI Button. Do I need to include ALL of the properties or is there an easier way.
Also, I am sure using 100px is not the correct way for this control to be responsive. Is 100em correct or should I use something different?
This is possible in Material-UI v5, you can create a custom variant for your Button. A variant is just a specific styles of a component, each variant is identified by a set of component props. See the example below:
const defaultTheme = createMuiTheme();
const theme = createMuiTheme({
components: {
MuiButton: {
variants: [
{
props: { color: "primary", variant: "contained" },
style: {
backgroundColor: defaultTheme.palette.primary.main,
fontSize: 20,
minWidth: "200px"
}
},
{
props: { color: "secondary", variant: "contained" },
style: {
backgroundColor: defaultTheme.palette.secondary.main
}
}
]
}
}
});
When you render this component:
<Button color="primary" variant="contained">
Primary
</Button>
The first variant style specified above is used because they have the same props:
{ color: "primary", variant: "contained" }
Live Demo
You can create custom variant as mentioned by #NearHuscarl other way you can create component modifying style.
Something like.
import { makeStyles } from '#material-ui/core/styles'
import Button from '#material-ui/core/Button'
import PropTypes from 'prop-types'
const useStyles = makeStyles((theme) => ({
root: {
height: '48px',
width: '100%',
backgroundColor: '#232323',
color: '#fff',
fontSize: '16px',
borderRadius: '4',
minHeight: theme.spacing(6),
'&:hover, &:active, &:focus': {
backgroundColor: `rgba(0, 0, 0, 0.8)`,
},
'&.Mui-disabled': {
opacity: 0.75,
},
},
}))
const propTypes = {
loading: PropTypes.bool,
}
function PrimaryButton({ children, loading = false, ...props }) {
const classes = useStyles()
return (
<Button
variant="contained"
className={classes.root}
disabled={loading}
{...props}
>
{children}
</Button>
)
}
PrimaryButton.propTypes = propTypes
export default PrimaryButton
Created code sandbox
https://codesandbox.io/embed/boring-mayer-cjl0f?fontsize=14&hidenavigation=1&theme=dark

How do you change a style of a child when hovering over a parent using MUI styles?

I'm using MUI in react. Let's say I have this component with these styles:
const useStyles = makeStyles(theme => ({
outerDiv: {
backgroundColor: theme.palette.grey[200],
padding: theme.spacing(4),
'&:hover': {
cursor: 'pointer',
backgroundColor: theme.palette.grey[100]
}
},
addIcon: (props: { dragActive: boolean }) => ({
height: 50,
width: 50,
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
})
}));
function App() {
const classes = useStyles();
return (
<Grid container>
<Grid item className={classes.outerDiv}>
<AddIcon className={classes.addIcon} />
</Grid>
</Grid>
);
}
I want to change the style of addIcon when hovering over outerDiv using the styles above.
Here's my example.
Below is an example of the correct syntax for v4 ("& $addIcon" nested within &:hover). Further down are some v5 examples.
import * as React from "react";
import { render } from "react-dom";
import { Grid, makeStyles } from "#material-ui/core";
import AddIcon from "#material-ui/icons/Add";
const useStyles = makeStyles(theme => ({
outerDiv: {
backgroundColor: theme.palette.grey[200],
padding: theme.spacing(4),
'&:hover': {
cursor: 'pointer',
backgroundColor: theme.palette.grey[100],
"& $addIcon": {
color: "purple"
}
}
},
addIcon: (props: { dragActive: boolean }) => ({
height: 50,
width: 50,
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
})
}));
function App() {
const classes = useStyles();
return (
<Grid container>
<Grid item className={classes.outerDiv}>
<AddIcon className={classes.addIcon} />
</Grid>
</Grid>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
Related documentation and answers:
https://cssinjs.org/jss-plugin-nested?v=v10.0.0#use-rulename-to-reference-a-local-rule-within-the-same-style-sheet
how to use css in JS for nested hover styles, Material UI
Material UI: affect children based on class
Advanced styling in material-ui
For those who have started using Material-UI v5, the example below implements the same styles but leveraging the new sx prop.
import Grid from "#mui/material/Grid";
import { useTheme } from "#mui/material/styles";
import AddIcon from "#mui/icons-material/Add";
export default function App() {
const theme = useTheme();
return (
<Grid container>
<Grid
item
sx={{
p: 4,
backgroundColor: theme.palette.grey[200],
"&:hover": {
backgroundColor: theme.palette.grey[100],
cursor: "pointer",
"& .addIcon": {
color: "purple"
}
}
}}
>
<AddIcon
className="addIcon"
sx={{
height: "50px",
width: "50px",
color: theme.palette.grey[400],
mb: 2
}}
/>
</Grid>
</Grid>
);
}
Here's another v5 example, but using Emotion's styled function rather than Material-UI's sx prop:
import Grid from "#mui/material/Grid";
import { createTheme, ThemeProvider } from "#mui/material/styles";
import AddIcon from "#mui/icons-material/Add";
import styled from "#emotion/styled/macro";
const StyledAddIcon = styled(AddIcon)(({ theme }) => ({
height: "50px",
width: "50px",
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
}));
const StyledGrid = styled(Grid)(({ theme }) => ({
padding: theme.spacing(4),
backgroundColor: theme.palette.grey[200],
"&:hover": {
backgroundColor: theme.palette.grey[100],
cursor: "pointer",
[`${StyledAddIcon}`]: {
color: "purple"
}
}
}));
const theme = createTheme();
export default function App() {
return (
<ThemeProvider theme={theme}>
<Grid container>
<StyledGrid item>
<StyledAddIcon />
</StyledGrid>
</Grid>
</ThemeProvider>
);
}
And one more v5 example using Emotion's css prop:
/** #jsxImportSource #emotion/react */
import Grid from "#mui/material/Grid";
import { createTheme, ThemeProvider } from "#mui/material/styles";
import AddIcon from "#mui/icons-material/Add";
const theme = createTheme();
export default function App() {
return (
<ThemeProvider theme={theme}>
<Grid container>
<Grid
item
css={(theme) => ({
padding: theme.spacing(4),
backgroundColor: theme.palette.grey[200],
"&:hover": {
backgroundColor: theme.palette.grey[100],
cursor: "pointer",
"& .addIcon": {
color: "purple"
}
}
})}
>
<AddIcon
className="addIcon"
css={(theme) => ({
height: "50px",
width: "50px",
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
})}
/>
</Grid>
</Grid>
</ThemeProvider>
);
}
This denotes the current selector which is the parent component:
'&': { /* styles */ }
This means the parent component in hover state:
'&:hover': { /* styles */ }
This means the child component inside the parent that is in hover state:
'&:hover .child': { /* styles */ }
You can also omit the ampersand & if you're using a pseudo-class:
':hover .child': { /* styles */ }
Complete code using sx prop (The same style object can also be used in styled()):
<Box
sx={{
width: 300,
height: 300,
backgroundColor: "darkblue",
":hover .child": {
backgroundColor: "orange"
}
}}
>
<Box className="child" sx={{ width: 200, height: 200 }} />
</Box>
Possibly an obvious point, but just to add to the answer above: if you are referencing a separate className, don't forget that you also need to create it in the makeStyles hook or else it won't work. For instance:
const useStyles = makeStyles({
parent: {
color: "red",
"&:hover": {
"& $child": {
color: "blue" // will only apply if the class below is declared (can be declared empty)
}
}
},
// child: {} // THIS must be created / uncommented in order for the code above to work; assigning the className to the component alone won't work.
})
const Example = () => {
const classes = useStyles()
return (
<Box className={classes.parent}>
<Box className={classes.child}>
I am red unless you create the child class in the hook
</Box>
</Box>
)
}
If you were using makeStyles in MUI v4 and have migrated to MUI v5 then you are likely now importing makeStyles from tss-react. If that is the case, then you achieve the same by the following:
import { makeStyles } from 'tss-react';
const useStyles = makeStyles((theme, props, classes) => ({
outerDiv: {
backgroundColor: theme.palette.grey[200],
padding: theme.spacing(4),
'&:hover': {
cursor: 'pointer',
backgroundColor: theme.palette.grey[100],
[`& .${classes.addIcon}`]: {
color: "purple"
}
}
},
addIcon: (props: { dragActive: boolean }) => ({
height: 50,
width: 50,
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
})
}));
The third argument passed to the makeStyles callback is the classes object.

How to display a modal inside a parent container

I have a small sub-window like div in my app, and I need to display a modal inside the sub-window instead of the whole viewport.
So the backdrop of the modal should only cover the sub-window and not the entire screen
I am using material-ui, so any solution native to material-ui is preferred.
Add disablePortal prop to <Dialog> and add styles as given in the code snippet
For some reason the styles applied to root didn't work through classes or className so had to add the style prop
import { makeStyles, DialogContent, Dialog } from '#material-ui/core';
import React from 'react';
const useStyles = makeStyles({
root: {
position: 'absolute',
},
backdrop: {
position: 'absolute',
},
});
interface ISubWindow {
onClose: () => void;
open: boolean;
}
const SubWindow: React.FC<ISubWindow> = ({onClose, open}) => {
const classes = useStyles();
return (
<Dialog
disablePortal
onClose={onClose}
open={open}
fullWidth
className={classes.root}
classes={{
root: classes.root,
}}
BackdropProps={{
classes: { root: classes.backdrop },
}}
style={{ position: 'absolute' }}
>
<DialogContent />
</Dialog>
);
};
export default SubWindow;
#Rahul's example got me most of the way, but it didn't quite work until I combined it with #Scott Sword and #Gretchen F. 's answers from this similar question.
The most important part was setting the position property of the parent div to relative though I also passed in props slightly differently which has worked a little easier for me:
import { makeStyles, DialogContent, Dialog } from '#material-ui/core';
import React from 'react';
const useStyles = makeStyles({
root: {
height: 'max-content',
minHeight: '100%',
},
backdrop: {
position: 'absolute',
},
paperScrollPaper: {
overflow: 'visible',
}
});
interface ISubWindow {
onClose: () => void;
open: boolean;
}
const SubWindow: React.FC<ISubWindow> = ({onClose, open}) => {
const classes = useStyles();
return (
<Dialog
disableAutoFocus//disables rescrolling the window when the dialog is opened
disableEnforceFocus//allows user to interact outside the dialog
disableScrollLock//prevents the div from shrinking to make room for a scrollbar
disablePortal
onClose={onClose}
open={open}
fullWidth
className={classes.root}
classes={{
paperScrollPaper: classes.paperScrollPaper
}}
BackdropProps={{
classes: { root: classes.backdrop },
}}
style={{ position: 'absolute' }}
>
<DialogContent />
</Dialog>
);
};
export default SubWindow;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Custom color to Badge component not working

I need to add a custom color to my Badge component and it does not seem to work.
I have tried these:
<Badge className="badge" badgeStyle={{backgroundColor: '#00AFD7'}} variant="dot" />
<Badge className="badge" color='#00AFD7' variant="dot" />
These do not work. How can I pass a custom color to my Badge component
You can leverage withStyles and use the badge css class to customize this.
Here's an example:
import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import Badge from "#material-ui/core/Badge";
import MailIcon from "#material-ui/icons/Mail";
const styles = theme => ({
margin: {
margin: theme.spacing.unit * 2
},
customBadge: {
backgroundColor: "#00AFD7",
color: "white"
}
});
function SimpleBadge(props) {
const { classes } = props;
return (
<div>
<Badge
classes={{ badge: classes.customBadge }}
className={classes.margin}
badgeContent={10}
>
<MailIcon />
</Badge>
</div>
);
}
SimpleBadge.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(SimpleBadge);
In v4, you can use functions within the styles that leverage props.
Documentation here: https://material-ui.com/styles/basics/#adapting-the-higher-order-component-api
const styles = theme => ({
margin: {
margin: theme.spacing.unit * 2
},
customBadge: {
backgroundColor: props => props.color,
color: "white"
}
});
In MUI v5, you can use either the sx prop:
<Badge
badgeContent={130}
sx={{
"& .MuiBadge-badge": {
color: "lightgreen",
backgroundColor: "green"
}
}}
>
<MailIcon />
</Badge>
Or styled() function:
const StyledBadge = styled(Badge)({
"& .MuiBadge-badge": {
color: "red",
backgroundColor: "pink"
}
});
I left the bg property empty and it accepted the background from the style. I am using bootstrap-5.
<Badge bg="" style={{backgroundColor: '#00AFD7'}} variant="dot">...</Badge>

Resources