7
votes

I am trying to port the styling of the Drawer component below, into Styled Components.

    <Drawer
      variant="permanent"
      classes={{
        paper: classes.drawerPaper
      }}
    >

,where paper is styled as follows:

const styles = theme => ({
  drawerPaper: {
    position: "relative",
    width: 240px
  }
});

I have no idea of how can I customize paper prop through Styled Components. The following styled component syntax does not work:

export const StyledDrawer = styled(Drawer)`
    position: "relative";
    width: 240px;
`;

The source-code for this component indicates that this is passed as props as PaperProps but I can still not find a way to override it.

3

3 Answers

5
votes

I would have given my answer in a comment but since I don't have enough reputation I can not comment. Anyway,look at the styled component documentation. It says that :

if you attempt to style a Drawer with variant permanent, you will likely need to affect the Drawer's underlying paper style. However, this is not the root element of Drawer and therefore styled-components customization as above will not work. You can workaround this by using stable JSS class names, but the most reliable approach is to use the classes property to introduce an override style, and then style it with higher specificity via &.

Please also look at the example given of button as well. If you still can't figure out comment here and I will try to help further.

5
votes

I have recently given an example in https://codesandbox.io/s/material-demo-k9l9h

I hope it helps:

import React, { useState } from "react";
import Drawer from "@material-ui/core/Drawer";
import styled from "styled-components";

const drawerWidth = 240;

const styles = theme => ({
  drawer: {
    position: "absolute",
    overflowX: "hidden",
    zIndex: theme.zIndex.drawer + 2,
    [theme.breakpoints.up("sm")]: {
      position: "relative",
      width: drawerWidth,
      flexShrink: 0,
      zIndex: theme.zIndex.drawer
    },
    whiteSpace: "nowrap"
  },
  drawerOpen: {
    width: drawerWidth,
    transition: theme.transitions.create("width", {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen
    })
  },
  drawerClose: {
    transition: theme.transitions.create("width", {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen
    }),
    overflowX: "hidden",
    width: 0,
    [theme.breakpoints.up("sm")]: {
      width: theme.spacing.unit * 9 + 1
    }
  }
});

const StyledDrawer = styled(Drawer)`
  ${({ theme, open }) => {
    const classes = styles(theme);
    return {
      ...classes.drawer,
      ...(open ? classes.drawerOpen : classes.drawerClose)
    };
  }}

  .MuiDrawer-paper {
    ${({ theme, open }) => {
      const classes = styles(theme);
      return open ? classes.drawerOpen : classes.drawerClose;
    }}

    &::-webkit-scrollbar {
      width: 2px;
    }
    &:hover {
      &::-webkit-scrollbar-thumb {
        display: none;
      }
    }
    &::-webkit-scrollbar-thumb {
      display: none;
    }
    &::-webkit-scrollbar-track {
      display: none;
    }
  }
`;

const PersistentDrawerLeft = () => {
  const [isOpen, setIsOpen] = useState(false);

  const handleDrawerOpen = () => {
    setIsOpen(true);
  };

  const handleDrawerClose = () => {
    setIsOpen(false);
  };

  return (
    <div>
      <StyledDrawer variant="permanent" open={isOpen}>
        <span>sidebar</span>
        <button onClick={handleDrawerClose}>close</button>
      </StyledDrawer>
      <span>Content</span>
      <button onClick={handleDrawerOpen}>open</button>
    </div>
  );
};

export default PersistentDrawerLeft;
2
votes

This is actually fairly easy. You can pass your own Component that the paper object will use allowing you to easily impart your own styling.

import styled from "styled-components";
const StyledPaper = styled.div`
   // my styles
`;

function MyComponent() {
  return (
    <Drawer
       // normal props
       PaperProps={{ component : StyledPaper }}
    >
      // drawer content
    </Drawer>
  )
}

Another option is to also have the first child of the drawer impart the styling. Since the paper has display: flex you can just put flex: 1 on your child and it will grow to the full size of the paper.

function MyComponent() {
  return (
    <Drawer
       // normal props
    >
      <StyledDiv>
        My Content
      </StyledDiv>
    </Drawer>
  )
}