Extend the border of MUI Select around another element

Viewed 150

I have a dropdown menu using MUI Select to sort (A-Z, newest-oldest), and I have a button next to it to reverse direction (Z-A, oldest-newest). Is it possible to extend the border of the Select (which darkens on hover) around the IconButton?

Here's a gif of what currently happens: border highlights on hover but goes back to normal when cursor moves to button.

If I just change the Paper both elements are in to variant="outlined", the outline cuts right through the label of the Select, whereas the Select's outline leave a gap for the label:

Outline cuts right through the label of the Select If both Paper and Select are outlined, the border doubles around the Select AND cuts through its label The Select's outline leave a gap for the label

If it's not possible to extend the Select's outline around the button, then can I make a new border around the whole element that has the same behavior on hover -- but without doubling the width of the border around the Select? Or can I make a border just around three sides of the little nubbin that's sticking out with the IconButton in it? How might I do that?

Here's the relevant part of my code for that component:

return (
    <FormControl sx={{ minWidth: "152px", mt: 1, }} >
        <Paper sx={{ bgcolor: "#fefcf9", }}>
        <InputLabel id="arrange-by-label">Arrange By</InputLabel>
        <Select
            labelId="arrange-by-label"
            id="arrange-by"
            value={litTextsOrder}
            label="Arrange By"
            onChange={handleLitTextsOrder}
            sx={{ bgcolor: "#fefcf9", minWidth: "132px" }}
        >
            {valuesArr.map((valueArr, index) => {
                return (
                    <MenuItem 
                        key={index} 
                        value={valueArr[0]}
                    >
                        {valueArr[1]} 
                    </MenuItem>
                )
            })}
        </Select>
        <Box component="span">
        <IconButton>
            <CompareArrowsIcon sx={{ transform: "rotate(90deg)"}}/>
        </IconButton>
        </Box>
        </Paper>
    </FormControl>
)

Thanks for your help, y'all!

1 Answers

You can do that by target the next element using & + span selector, remove the border right border of the Select and add a border except the left side in the button next to the Select. The hover color is not in a theme, it's hardcoded at this line, so you also have to copy it.

const theme = useTheme();
const hoverColor =
  theme.palette.mode === "light"
    ? "rgba(0, 0, 0, 0.23)"
    : "rgba(255, 255, 255, 0.23)";
const activeColor = theme.palette.primary.main;
<Select
  label="Arrange By"
  sx={{
    bgcolor: "#fefcf9",
    minWidth: "132px",
    "& fieldset": {
      borderTopRightRadius: 0,
      borderBottomRightRadius: 0
    },
    "&&:hover fieldset": {
      borderRight: "none",
      borderLeft: `solid 1px ${hoverColor}`,
      borderTop: `solid 1px ${hoverColor}`,
      borderBottom: `solid 1px ${hoverColor}`
    },
    "&&.Mui-focused fieldset": {
      borderRight: "none",
      borderLeft: `solid 1px ${activeColor}`,
      borderTop: `solid 1px ${activeColor}`,
      borderBottom: `solid 1px ${activeColor}`
    },
    "& + span": {
      display: "flex",
      borderRadius: theme.shape.borderRadius + "px",
      borderTopLeftRadius: 0,
      borderBottomLeftRadius: 0,

      "& button": {
        height: "100%"
      }
    },
    "&:hover + span": {
      borderColor: hoverColor,
      border: `solid 1px ${hoverColor}`,
      borderLeft: "none"
    },
    "&.Mui-focused + span": {
      borderColor: activeColor,
      border: `solid 1px ${activeColor}`,
      borderLeft: "none"
    }
  }}
>

Codesandbox Demo

Related