How to remove Accordion gap when expanded? - reactjs

I'm trying to have the Accordion MUI component NOT move and NOT apply top and bottom margins to some elements while it is in the expanded mode.
Example follows like this, but it's not working, my component is still too "jumpy" (when expanded it increases in width and like some invisible margins are being added)
...
expanded: {
margin: '0px',
},
test: {
'&$expanded': {
margin: '0px',
},
},
...
<Accordion
classes={{
root: classes.test,
expanded: classes.expanded,
}}
expanded={expanded}
>
<AccordionSummary
onClick={() => setExpanded(!expanded)}
classes={{
expanded: classes.expanded,
}}
>
The Summary
</AccordionSummary>
<AccordionDetails>
<p>the details</p>
</AccordionDetails>
</Accordion>

In MUI v5, it's as easy as setting disableGutters to true. This prevents all up/down repositioning when expanding the Accordion. More info here: https://mui.com/material-ui/api/accordion/#props.

You can do that by setting the Accordion margin to auto which should be the same as setting it to 0. Make sure the style is applied to every Accordions on the screen. See this example here.
The Accordion is being moved when expanding is just a side effect of positive margin plus the transition effect when expanded. Removing the margin will likely fix your issue.
import { withStyles } from "#material-ui/core/styles";
import MuiAccordion from "#material-ui/core/Accordion";
import AccordionSummary from "#material-ui/core/AccordionSummary";
import AccordionDetails from "#material-ui/core/AccordionDetails";
import Typography from "#material-ui/core/Typography";
const Accordion = withStyles({
root: {
"&$expanded": {
margin: "auto"
}
},
expanded: {}
})(MuiAccordion);
Live Demo

If people are still struggling with it, write a div or Box and wrap it around each accordion.
Example:
export const AccordionStyled = styled(Accordion)(
sx({
border: 'none',
boxShadow: 'none',
})
);
export const BoxStyled = styled(Box)(
sx({
'& AccordionStyled': {
margin: '0px !important',
},
})
);
<BoxStyled>
<AccordionStyled>
[your code here]
</AccordionStyled>
<BoxStyled>
This overrides margin and also helps control/remove any other styles applied by default. This also works for any MUI component that people find hard to remove or override.

Related

Changing material ui IconButton hovered style doesn't work

I am trying to make the custom hovered style of IconButton and I am doing it as
const useStyles = makeStyles((theme) => ({
root: {
"&:hover": {
borderRadius: "4px",
padding: "3px",
},
},
}));
return (
<div className="App">
<IconButton aria-label="previous" className={classes.root}>
<ArrowLeftIcon />
</IconButton>
</div>
);
But when I hover it, it's flickering and not changing smoothly. I think I am missing some styles to add, but I can't find a way what I'm doing wrong. You can see my codesandbox example here.
If you look at the default styles for IconButton, you'll find that the borderRadius and padding are set directly in the root styles. Only the backgroundColor changes on hover.
If you make the corresponding change to your styles, then it works fine:
const useStyles = makeStyles((theme) => ({
root: {
borderRadius: "4px",
padding: "3px"
}
}));
It's flickering on hover because the padding (the space between its content and border) is modified. Either remove the padding or put it in the default style.
not changing smoothly
This can be easily solved by using css transition. Material-UI theme has a utility method theme.transition.create() to help you create transition quickly.
const useStyles = makeStyles((theme) => ({
root: {
transition: theme.transitions.create(["border-radius"]),
// padding: 3;
"&:hover": {
borderRadius: "4px"
}
}
}));
Live Demo

Material UI Overriding styles with increased specificity

How can I override a rule of a class which has high specificity?
For example, the .MuiAccordionSummary-content.Mui-expanded class in the AccordionSummary
const useStyles = makeStyles(() => ({
expanded: {
marginBottom: 0,
},
}));
in combination with:
<AccordionSummary classes={{
expanded: classes.expanded,
}}/>
is applied but overridden.
Note: marginBottom: '0 !important' works, but doesn't feel like an optimal solution.
You could use global overrides to change the default margin of the AccordionSummary. However, this will affect all AccordionSummary components in your application.
The better approach (the one you are already using) is to wrap the component and alter its classes. If you look into the source of the AccordionSummary, you will find that the expanded property is an empty block. The margin gets set by the referencing selector in the content property:
content: {
display: 'flex',
flexGrow: 1,
transition: theme.transitions.create(['margin'], transition),
margin: '12px 0',
'&$expanded': {
margin: '20px 0',
},
},
If you add the same reference in your custom styles, the priority becomes higher and you won't need !important. You will have to add the expanded className to your custom styles though:
import React from 'react';
import makeStyles from '#material-ui/core/styles/makeStyles'
import Accordion from '#material-ui/core/Accordion';
import AccordionDetails from '#material-ui/core/AccordionDetails';
import AccordionSummary from '#material-ui/core/AccordionSummary';
const useStyles = makeStyles(() => ({
expanded: {},
content: {
'&$expanded': {
marginBottom: 0,
},
},
}));
const MyAccordion = ({ summary, details }) => {
const classes = useStyles();
return (
<Accordion>
<AccordionSummary classes={{ content: classes.content, expanded: classes.expanded }}>
{summary}
</AccordionSummary>
<AccordionDetails>
{details}
</AccordionDetails>
</Accordion>
)
};
export default MyAccordion;

How can I remove line above the accordion of Material UI?

I'm trying to implement an Accordion component with Material UI.
The problem I'm facing is that a gray line is automatically inserted above the component although I prefer white background. How can I remove it? Here is demo code.Material UI accordion component demo
With the release of Material-UI v5.0.0-beta.0, custom styling has become much easier via use of the new sx prop.
The sx prop may be used on all Material-UI components as of v5. In our world, this has eliminated the need for hack-ish style overrides and custom classes.
Here's how to remove the "line above the accordion" with the sx={} prop.
return (
<Accordion
disableGutters
elevation={0}
sx={{
'&:before': {
display: 'none',
}
}}>
<AccordionSummary expandIcon={<ExpandMore/>}>
...your summary here...
</AccordionSummary>
<AccordionDetails sx={{ maxWidth: '480px' }}>
...your details here...
</AccordionDetails>
</Accordion>
);
Note that I've passed the sx prop to <AccordionDetails/> as well.
You must pass an object to sx so you're always going to have a double set of curly braces...
sx={{ borderBottom: '1px solid #dddddd', borderRadius: '4px' }}
To make gray line white you have to override the css classes of Accordion element.
The grey line comes from .MuiAccordion-root:before style. So at first change Accordion props adding classes props like:
...
<Accordion
elevation={0}
classes={{
root: classes.MuiAccordionroot
}}
>
...
And then on your useStyles add:
MuiAccordionroot: {
"&.MuiAccordion-root:before": {
backgroundColor: "white"
}
}
and grey line becames white. Here your code modified.
Try adding some css file and access this class MuiAccordion-root:before and change it's height to 0px. It's the pseudo-element that's showing the gray line above the Accordian.
// in my TS project i did it like this:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
test: {
'&:before': {
display: 'none',
},
);
<Accordion
classes={{
root: classes.test,
}}
expanded={expanded}
>
To remove line between Accordion summary and Accordion details you just need to pass borderBottom='none !important'
const useStyles = makeStyles({
Summary:{
borderBottom:'none !important'
});
const AccordionComp=()=>{
const classes = useStyles();
return(
<Accordion>
<AccordionSummary className={classes.Summary}>
......
</AccordionSummary>
<AccordionDetails>......</AccordionDetails>
</Accordian>
)}
export default AccordionComp;
You can wrap the Accordion component in a div and it will remove the line. It comes from a :before property that I imagine is helpful when you have more than one in a row to visually divide.

How to change the hover color of Material-UI table?

I am using React and Material UI for my web application. I want to change the hover color of table row but cannot do that.
Sample code:
x={
hover:{
color:'green'
}
}
<TableRow
hover
key={lead.id} className={classes.row}
classes={{
hover:x.hover
}}
onClick={() => {}}
>
I've got this solution so far. Maybe there are other approaches to override css of tableRow but this one works like a charm:
const styles = theme => ({
tableRow: {
"&:hover": {
backgroundColor: "blue !important"
}
}
});
<TableRow hover
key={lead.id} className={classes.tableRow}
onClick={() => {}}>
Feel free to ask any question.
tableRow: {
hover: {
"&$hover:hover": {
backgroundColor: '#49bb7b',
},
},
}
<TableRow className={classes.tableRow} key={n.id} hover onClick={event => this.handleClick(event)}>Text</TableRow>
The implementation of the TableRow component and the customizing components page show that you need to override two classes, root.hover:hover and .hover to change the hover color.
const useStyles = makeStyles((theme) => ({
/* Styles applied to the root element. */
root: {
// Default root styles
color: 'inherit',
display: 'table-row',
verticalAlign: 'middle',
// We disable the focus ring for mouse, touch and keyboard users.
outline: 0,
'&$hover:hover': {
// Set hover color
backgroundColor: theme.palette.action.hover,
},
},
/* Pseudo-class applied to the root element if `hover={true}`. */
hover: {},
}));
Then in your component, you can apply the styles to the classes prop.
const HelloWorld = () => {
const classes = useStyles();
return (
<TableRow classes={classes}><TableCell></TableCell></TableRow>
);
};
You can maintain dependency on the Material UI hover prop by using
hover: {
'&:hover': {
backgroundColor: 'green !important',
},
},
just put hover in the TableRow, but not the header Tablerow
<StyledTableRow hover key={row.name}>
#material-ui/core/TableRow has built in code to deal with hover, it worked for me.
This is a trivial task in MUI v5. See the docs here:
<Table
sx={{
"& .MuiTableRow-root:hover": {
backgroundColor: "primary.light"
}
}}
>
Live Demo
Just in case, if you are using the component overrides and want to do a style override you have to target the root and not the hover rule. I spent quite a while trying to get the pseudo :hover to work on that but it wouldn't ever work.
Here's what I have.
MuiTableRow: {
styleOverrides: {
// Even though there is a hover rule we have to override it here. Don't ask.
root: {
'&.MuiTableRow-hover:hover': {
backgroundColor: 'blue',
},
},
},
},
Use this is you want to override the component at the theme level vs styled overrides, sx or useStyles.
If you're using withstyles you can just override it in the root element like so:
An example of how to do it is here: https://codesandbox.io/s/7249117670

How to remove greyed out color with clicks on material-ui chips?

Trying to figure something out with the material-ui chips. When you click them, they hold a grey color until you click again somewhere else. I want to be able to click and have my active class and click again and have my inactive class. I can't figure out why there is a grey step in the middle.
<div className={classes.root}>
{this.props.chipData.map(data => {
return (
<Chip
key={data.key}
clickable={false}
clickableColorSecondary="white"
label={data.label}
onClick={this.props.toggleChipProperty(data.key)}
className={(data.showing ? classes.active : classes.inactive )}
/>
);
})}
</div>
CSS:
active: {
backgroundColor:"#4054B2",
color:"white",
height:"20px"
},
inactive: {
backgroundColor:"white",
color:"#575b6e",
border:"1px solid #8080806e",
height:"20px"
}
});
This image shows the grey part. You click, it shows grey on the button, then it finally shows the right color once you click off. I find this to be not intuitive. I want to click and have it simply toggle.
enter image description here
I had the same problem with Select Component of Material-UI.
I guess that you can do the same with Chip Component,
just change the MuiIconButton to MuiChip (and maybe select to root also):
Override MaterialUI Component Focus
Let me know if that works for you.
I had the same problem with Select component. I tried with the solution of Konstantinos and I end up solving this problem with 2 steps:
#1 Create a new theme
const theme1 = createMuiTheme({
overrides: {
MuiSelect: {
select: {
'&:focus': {
backgroundColor: 'none'
}
}
}
}
});
#2 Wrap component with theme provider
<MuiThemeProvider theme={theme1}>
<Select...
</MuiThemeProvider>
This is how I solved it and it worked for me. I used styled() Just set the
"&:focus": {
backgroundColor: bgColor
}
Component example:
const AutocompleteChipSemiIncluded = styled(Chip, {
shouldForwardProp: (prop) => prop !== 'bgColor',
})(({ bgColor, theme }) => ({
...(bgColor && {
maxWidth: '180px',
padding: "15px 5px",
backgroundColor: colors.primary.contrastText,
border: `1px dashed ${bgColor}`,
color: bgColor,
'& .MuiChip-deleteIcon': {
color: bgColor,
},
"&:focus": {
backgroundColor: bgColor
}
}),
}));

Resources