Search code examples
reactjsmaterial-uijsx

How can I pass both the theme and the props in the styled() of Material UI-5?


import {
  AppBar,
  Avatar,
  Badge,
  InputBase,
  Toolbar,
  Typography,
} from "@mui/material";

import React, { useState } from "react";
import { styled, alpha } from "@mui/material/styles";
import { Mail, Notifications, Search } from "@mui/icons-material";

const LogoLg = styled(Typography)(({ theme }) => ({
  display: "none",
  [theme.breakpoints.up("sm")]: {
    display: "block",
  },
}));

const LogoSm = styled(Typography)(({ theme }) => ({
  display: "none",
  [theme.breakpoints.down("sm")]: {
    display: "block",
  },
}));

const SearchDiv = styled("div")(({ theme, props }) => ({
  display: "flex",
  alignItems: "center",
  backgroundColor: alpha(theme.palette.common.white, 0.15),
  borderRadius: theme.shape.borderRadius,
  width: "50%",
  "&:hover": {
    backgroundColor: alpha(theme.palette.common.white, 0.15),
  },
  [theme.breakpoints.down("sm")]: {
    display: props.open ? "flex" : "none",
  },
}));

const IconsDiv = styled("div")((theme) => ({
  display: "flex",
  alignItems: "center",
}));

const BadgeItem = styled(Badge)(({ theme }) => ({
  marginRight: theme.spacing(2),
}));

const SearchButton = styled(Search)(({ theme }) => ({
  marginRight: theme.spacing(2),
}));

const Navbar = () => {
  const [open, setOpen] = useState(false);
  return (
    <AppBar>
      <Toolbar sx={{ display: "flex", justifyContent: "space-between" }}>
        <LogoLg variant="h6">Milan Poudel</LogoLg>
        <LogoSm variant="h6">MILAN</LogoSm>
        <SearchDiv open={open}>
          <Search />
          <InputBase
            placeholder="Search..."
            sx={{ color: "white", marginLeft: "10px" }}
          />
        </SearchDiv>
        <IconsDiv>
          <SearchButton onClick={() => setOpen(true)} />
          <BadgeItem badgeContent={4} color="error">
            <Mail />
          </BadgeItem>
          <BadgeItem badgeContent={2} color="error">
            <Notifications />
          </BadgeItem>
          <Avatar
            alt="milan-poudel"
            src="https://i.ytimg.com/vi/CmSc_EIqyQI/maxresdefault.jpg"
          />
        </IconsDiv>
      </Toolbar>
    </AppBar>
  );
};

export default Navbar;

In the searchDiv, I want to use both theme and the props that I have used in SearchDiv below (i.e. "open" prop). I want to use it in the styled and according to it's state, want to customize the display property? How can I pass both the theme and props to the styled in the new MUI5? Previously I could use props directly while in the MUIv4 but I don't think in MUI5 it is allowed


Solution

  • Signature from the styled API Documentation:
    styled(Component, [options])(styles) => Component

    The props are passed into the styles parameter (from where you're also destructuring and retrieving theme), so you can add your open property to that and use it directly -- for example:

    // 1. Added `open` to `styles` param
    const SearchDiv = styled("div")(({ theme, open }) => ({
    
      ...
    
      // 2. Changed `props.open` to `open` below 
      [theme.breakpoints.down("sm")]: {
        display: open ? "flex" : "none",
      },
    }));
    
    // Unchanged
    <SearchDiv open={open}>
      ...
    </SearchDiv>
    

    Simple working example to demonstrate usage: https://codesandbox.io/s/simple-mui5-props-example-1uclg?file=/src/Demo.js