Search code examples
cssreactjsresponsive-designmaterial-uiemotion

How to make noWrap work with Breadcrumbs?


I'm trying to make the MUI component Breadcrumbs responsive:

When the Breadcrumbs component takes all of its space, its items shrink using ellipsis like any Typography component with noWrap prop set.

I know it has itemsBeforeCollapse, itemsAfterCollapse and maxItems props but these props are about item number compared to viewport size, not about each item width.

I tried to set the noWrap property to Typography and Link components (as it extends Typography props), but the ellipsis does not show up and the Link or Typography component does not shrink.

<Breadcrumbs>
  {links.map((link, i) =>
    i !== links.length - 1 ? (
      <Link
        key={i}
        underline={'hover'}
        noWrap
      >
        {link}
      </Link>
    ) : (
      <Typography noWrap key={i}>
        {link}
      </Typography>
    ),
  )}
</Breadcrumbs>

You can reproduce the issue on this codeSandbox:

Edit BasicBreadcrumbs Material Demo (forked)


Solution

  • If I understand you correctly, the problem is that the noWrap style is not affecting the right element.

    Why?

    noWrap affect elements that its width limited either explicit (e.g. width: 100px) or implicit (by parent's width).

    In your case, the Link and the Typography's width is not limited.

    What can you do?

    Breadcrumbs renders ol with display: flex. In order to force the children (li) to stand a line (and take a third in your case) you should give it flex: 1. From this point, you can give the li the ellipsis styles.

    The last part, how to give the li these styles? There are some ways as described at the css section.

    I would take the styled approach and this is how it looks

    import * as React from "react";
    import Typography from "@mui/material/Typography";
    import Breadcrumbs from "@mui/material/Breadcrumbs";
    import Link from "@mui/material/Link";
    import { styled } from "@mui/material/styles";
    
    const StyledBreadcrumbs = styled(Breadcrumbs)`
      .MuiBreadcrumbs-li {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        flex: 1;
      }
    `;
    
    export default function BasicBreadcrumbs() {
      const links = [
        "this is a waaaaaaaaaaaaay too long link",
        "and another link that can be long too",
        "this is the last link and guess what? It's waaaaaaaaaaaaaaaaaaayyy more longer"
      ];
      return (
        <StyledBreadcrumbs>
          {links.map((link, i) =>
            i !== links.length - 1 ? (
              <Link key={i} underline={"hover"}>
                {link}
              </Link>
            ) : (
              <Typography key={i}>
                {link}
              </Typography>
            )
          )}
        </StyledBreadcrumbs>
      );
    }
    

    https://codesandbox.io/s/basicbreadcrumbs-material-demo-forked-y1bbo?file=/demo.js