简体   繁体   中英

How can I override ExpansionPanelSummary deep elements with styled-components?

Using the docs/examples for overriding Material UI styling with styled-components, I've managed to style the root and "deeper elements" within an ExpansionPanel and ExpansionPanelDetails .

However, when I use the same technique to return an overridden ExpansionPanelSummary from a function passed to styled() , the ExpansionPanelSummary moves in the DOM and the whole ExpansionPanel no longer renders correctly.

The technique in question, as applied to ExpansionPanel (this works as expected, on the container ExpansionPanel ):

import MUIExpansionPanel from '@material-ui/core/ExpansionPanel';

export const ExpansionPanel = styled(props => (
  <MUIExpansionPanel
    classes={{expanded: 'expanded'}}
    {...props}
  />
))`
  && {
    ...root style overrides
  }
  &&.expanded {
    ...expanded style overrides
  }
`;

The typical DOM (with class names abbreviated) for ExpansionPanel and friends:

<div class="MuiExpansionPanel...">
  <div class="MuiExpansionPanelSummary..." />
  <div class="MuiCollapse-container...>
    <div class="MuiCollapse-wrapper...>
      <div class="MuiCollapse-wrapperInner...>
        <div class="MuiExpansionPanelDetails..." />
      </div>
    </div>
  </div>
</div>

The DOM when I apply the above technique to ExpansionPanelSummary :

<div class="MuiExpansionPanel...">
  <div class="MuiCollapse-container...>
    <div class="MuiCollapse-wrapper...>
      <div class="MuiCollapse-wrapperInner...>
        <div class="MuiExpansionPanelSummary..." />
        <div class="MuiExpansionPanelDetails..." />
      </div>
    </div>
  </div>
</div>

For completeness, here's a minimal repro of what I'm doing to ExpansionPanelSummary , that triggers the DOM switch:

export const ExpansionPanelSummary = styled(props => (
  <MUIExpansionPanelSummary
    {...props}
  />
))``;

And my JSX is standard ExpansionPanel setup:

<ExpansionPanel>
  <ExpansionPanelSummary>
    Summary Label
  </ExpansionPanelSummary>
  <ExpansionPanelDetails>
    <div>Some Content</div>
  </ExpansionPanelDetails>
</ExpansionPanel>

This difficulty is independent of using styled-components and just has to do with wrapping ExpansionPanelSummary in another component.

You can similarly reproduce this with the following wrapping of ExpansionPanelSummary :

const MyCustomSummary = props => {
  return (
    <ExpansionPanelSummary {...props} expandIcon={<ExpandMoreIcon />}>
      <Typography>{props.text}</Typography>
    </ExpansionPanelSummary>
  );
};

There are several component groups like this where a Material-UI parent component looks for a particular type of child component and treats that child specially. For instance, you can find the following block in ExpansionPanel

      if (isMuiElement(child, ['ExpansionPanelSummary'])) {
        summary = React.cloneElement(child, {
          disabled,
          expanded,
          onChange: this.handleChange,
        });
        return null;
      }

Fortunately, Material-UI has a straightforward way to tell it that your custom component should be treated the same as a particular Material-UI component via the muiName property:

MyCustomSummary.muiName = "ExpansionPanelSummary";

or in your case it would look like:

export const ExpansionPanelSummary = styled(props => (
  <MUIExpansionPanelSummary
    {...props}
  />
))``;

ExpansionPanelSummary.muiName = "ExpansionPanelSummary";

编辑自定义扩展面板摘要

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM