-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Accordion] Additional actions in summary #9427
Comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@futbolistua were you able to work around this? I'm also trying to prevent the expansion by clicking on the summary (I just want to expand when you click on the icon). |
This comment has been minimized.
This comment has been minimized.
You can do what @codeskills-nl mentioned
|
Hi @stevewillard, Thanks for the suggestion. I have an MUI checkbox in the summary, so when I do stopPropagation, it's messing up check/unchecking the checkbox. Thanks, |
There is a way to get exactly the behavior you guys want (should also solve your problem @chathuraa):
You can manage the ExpansionPanel expanded state yourself, and by using the onClick event of the Icon which is passed to the ExpansionPanelSummary (which is the header line) you can open/close the expansion panel only via the icon) |
Amazing workaround Loktor! |
This is pretty common in even regular JS. One way to mitigate this that we're doing is ensuring all input components have a common wrapper. Then you can add the /* see: https://github.com/mui-org/material-ui/issues/9427 */
const stopPropagation = (e) => e.stopPropagation();
const InputWrapper = ({ children }) =>
<div onClick={stopPropagation}>
{children}
</div>
// usage:
<InputWrapper>
<MyCoolInput />
</InputWrapper> This would be a decent way to handle it, if you need to have the summary be clickable. This lets you control propagation selectively if you wish too. Otherwise @Loktor's method works well too, you just might need to override the cursor styles and some attributes because the Summary is still tabbable and has aria roles on it. |
Thanks @kamranayub your solution is the best here. |
This works fine. But I have an array which I populate using map function. Let's say I have 5 expansion panels and after clicking on the icon button, I change the state as mentioned in your answer. However, the problem with the approach is that it expands all expansion panels but I only want to expand the expansion panel being clicked |
You can use an arbitrary condition based on a local state to decide what panel will be opened. For example: state = {
panel: ''
};
const handleStateChange = panel => () => this.setState({ panel});
// This would be your list of available panels,
// which I suppose you go through to create your panels.
const panels = {
panelOne: 'panelOne',
panelTwo: 'panelTwo',
};
Object.keys(panels).map(panel => (
<ExpansionPanel expanded={this.state.panel === panel}>
<ExpansionPanelSummary
expandIcon={<ExpandMoreIcon onClick={handleStateChange(panel)} />}
>
...
</ExpansionPanelSummary>
...
</ExpansionPanel>
)); |
This comment has been minimized.
This comment has been minimized.
I have a checkbox inside I'm doing this on
but the can I stop this behaviour? |
Done: #14828. |
let's say I want to open expansion panel by clicking anywhere on the panel (which is the default behavior). But there is a button inside my expansion panel. When I click on that button, I don't want to open the expansion panel. How Can I achieve this? I tried to use z-index but I didn't help. |
@Usama-Tahir it was already covered by this comment from @kamranayub. |
I don't know how that solves my problem. |
I would try to do the distinction between event.currentTarget and event.target. |
@Usama-Tahir if you are talking about having a button into It's related to the const _handleButtonClick = event => {
event.stopPropagation();
... Do your stuff after here.
}
<ExpansionPanel>
<ExpansionPanelSummary>
<Button onClick={_handleButtonClick}>Click me</Button>
</ExpansionPanelSummary>
...
</ExpansionPanel> This should avoid the Does that make sense to your issue? |
yes, That solved my problem partially. Actually, I render expansion panels from an array. Initially, I was using |
What do you guys think of this approach? --- a/docs/src/pages/demos/expansion-panels/ControlledExpansionPanels.js
+++ b/docs/src/pages/demos/expansion-panels/ControlledExpansionPanels.js
@@ -1,8 +1,8 @@
import React from 'react';
-import { makeStyles } from '@material-ui/core/styles';
+import { makeStyles, withStyles } from '@material-ui/core/styles';
import ExpansionPanel from '@material-ui/core/ExpansionPanel';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
-import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
+import MuiExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import Typography from '@material-ui/core/Typography';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
@@ -21,18 +21,28 @@ const useStyles = makeStyles(theme => ({
},
}));
+const ExpansionPanelSummary = withStyles({
+ root: {
+ cursor: 'default',
+ },
+})(MuiExpansionPanelSummary);
+
function ControlledExpansionPanels() {
const classes = useStyles();
const [expanded, setExpanded] = React.useState(null);
- const handleChange = panel => (event, isExpanded) => {
- setExpanded(isExpanded ? panel : false);
+ const handleChange = panel => () => {
+ const isExpanded = expanded === panel;
+ setExpanded(isExpanded ? false : panel);
};
return (
<div className={classes.root}>
- <ExpansionPanel expanded={expanded === 'panel1'} onChange={handleChange('panel1')}>
+ <ExpansionPanel expanded={expanded === 'panel1'}>
<ExpansionPanelSummary
+ IconButtonProps={{
+ onClick: handleChange('panel1'),
+ }}
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1bh-content"
id="panel1bh-header"
@@ -47,8 +57,11 @@ function ControlledExpansionPanels() {
</Typography>
</ExpansionPanelDetails>
</ExpansionPanel>
- <ExpansionPanel expanded={expanded === 'panel2'} onChange={handleChange('panel2')}>
+ <ExpansionPanel expanded={expanded === 'panel2'}>
<ExpansionPanelSummary
+ IconButtonProps={{
+ onClick: handleChange('panel2'),
+ }}
expandIcon={<ExpandMoreIcon />}
aria-controls="panel2bh-content"
id="panel2bh-header"
@@ -65,8 +78,11 @@ function ControlledExpansionPanels() {
</Typography>
</ExpansionPanelDetails>
</ExpansionPanel>
- <ExpansionPanel expanded={expanded === 'panel3'} onChange={handleChange('panel3')}>
+ <ExpansionPanel expanded={expanded === 'panel3'}>
<ExpansionPanelSummary
+ IconButtonProps={{
+ onClick: handleChange('panel3'),
+ }}
expandIcon={<ExpandMoreIcon />}
aria-controls="panel3bh-content"
id="panel3bh-header"
@@ -83,8 +99,11 @@ function ControlledExpansionPanels() {
</Typography>
</ExpansionPanelDetails>
</ExpansionPanel>
- <ExpansionPanel expanded={expanded === 'panel4'} onChange={handleChange('panel4')}>
+ <ExpansionPanel expanded={expanded === 'panel4'}>
<ExpansionPanelSummary
+ IconButtonProps={{
+ onClick: handleChange('panel4'),
+ }}
expandIcon={<ExpandMoreIcon />}
aria-controls="panel4bh-content"
id="panel4bh-header"
diff --git a/packages/material-ui/src/ExpansionPanelSummary/ExpansionPanelSummary.js b/packages/material-ui/src/ExpansionPanelSummary/ExpansionPanelSummary.js
index 388667124..4ea5a86f1 100644
--- a/packages/material-ui/src/ExpansionPanelSummary/ExpansionPanelSummary.js
+++ b/packages/material-ui/src/ExpansionPanelSummary/ExpansionPanelSummary.js
@@ -19,9 +19,7 @@ export const styles = theme => {
minHeight: 8 * 6,
transition: theme.transitions.create(['min-height', 'background-color'], transition),
padding: '0 24px 0 24px',
- '&:hover:not($disabled)': {
- cursor: 'pointer',
- },
+ cursor: 'pointer',
'&$expanded': {
minHeight: 64,
},
@@ -30,6 +28,7 @@ export const styles = theme => {
},
'&$disabled': {
opacity: 0.38,
+ cursor: 'default',
},
},
/* Styles applied to the root element, children wrapper element and `IconButton` component if `expanded={true}`. */ https://codesandbox.io/s/jjy809l6ny I think that it would make a great demo. Does anyone want to handle it? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This issue is still a problem. |
This comment has been minimized.
This comment has been minimized.
@oliviertassinari your proposals seems to be focused on solving a different problem. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@Loktor's solution is great, but unfortunately since it was posted there has been a new warning added to material-ui warning that the clicks on the icon won't be seen by Firefox. Here's an alternative solution: `const CustomExpansionPanel = ({children, className, initiallyExpanded = false}) => {
}; |
@drericrobinson Could you explain the behavior you are looking for with this logic? I would hope we can simplify it. A significant amount of people have interacted with the issue, it seems to be an important concern. |
#9427 (comment) already had a simple but potentially inaccessible solution We can add a demo (without changing the ExpansionPanel implementation) but need to document how to improve a11y as much as possible: https://codesandbox.io/s/material-ui-expansionpanel-nested-action-u2bm6 should fix most of the a11y issues introduced by simply stopping click propagation of the nested actions. |
@eps1lon This sounds like a great approach, it works with a checkbox too: https://codesandbox.io/s/material-ui-expansionpanel-nested-action-9pkk5. I'm all in for adding a demo for the "action inside panel summary" case. Looking at the comment history, it seems that people also ask for an alternative where the |
So all that's missing is a reasonable use case for that (not just dummy text). If someone can work on a real example I'd be happy to review PR that adds a demo that incorporates some key aspects from https://codesandbox.io/s/material-ui-expansionpanel-nested-action-u2bm6:
|
Giving this one a hacktoberfest shot here: #17969 :P |
This comment has been minimized.
This comment has been minimized.
I used the method mentioned by @Loktor and it worked perfectly for me as my expansion panels are in separate components. My only qualm is the fact that I'm getting this warning/error: I've tested my app out in Firefox and it's working as expected, maybe misses the initial click at times but works after that. This'll be a mobile web app so it'll only be running on Chrome and Safari anyhow. Is there anyway I can get rid of this error? And is it fine for me to proceed with the method I'm using? Below is the snippet of code I'm using; an attribute inside ExpansionPanelSummary: |
The ExpansionPanelSummary handles click to expand/collapse details panel. But I want to put some actions buttons to it. But it's not possible to disable click on the whole summary panel and handle only expandIcon click.
The text was updated successfully, but these errors were encountered: