CCCC
CCCC

Reputation: 6461

React - how to trigger focus on parent element when the child element is focusing

This is my current SearchBar
enter image description here

What I want to do is, when I focus the <InputBase>, it will help to trigger the focus on
<div className={classes.search} ref={refSearchBar}></div>, and make the box-shadow changes like below:

enter image description here

I tried to use UseRef, but it seems not working.

SearchBar.js

import React, { useRef } from "react";
import { makeStyles } from "@material-ui/core/styles";
import InputBase from "@material-ui/core/InputBase";
import SearchIcon from "@material-ui/icons/Search";

const useStyles = makeStyles((theme) => ({
  search: {
    position: "relative",
    borderRadius: theme.shape.borderRadius,
    padding: "0 0.5rem",
    width: "50%",
    border: "1px solid grey",
    "&:focus": {
      boxShadow: "0 0 0 1px blue, 0 0 0 4px blue"
    }
  },
}));

export default function PrimarySearchAppBar(props) {
  const classes = useStyles();
  const refSearchBar = useRef(null);

  return (
    <div className={classes.search} ref={refSearchBar}>
      <div className={classes.searchIcon}>
        <SearchIcon />
      </div>
      <InputBase
        placeholder="Search…"
        classes={{
          root: classes.inputRoot,
          input: classes.inputInput
        }}
        inputProps={{ "aria-label": "search" }}
        style={{ width: "100%" }}
        onClick={() => {
          refSearchBar.current.focus();
        }}
      />
    </div>
  );
}

CodeSandbox
https://codesandbox.io/s/bold-monad-w4cxi?file=/src/SearchBar.jsx

Upvotes: 4

Views: 3641

Answers (2)

Ryan Le
Ryan Le

Reputation: 8412

You could add input icon by using startAdornment props from InputBase instead

Because focus pseudo-class is only available on input so you would need to apply it to input.

Something like this:

<InputBase
  startAdornment={<SearchIcon />}
  placeholder="Search…"
  classes={{
    adornedStart: classes.searchIcon,
    root: classes.inputRoot,
    input: classes.inputInput,
  }}
  inputProps={{ "aria-label": "search" }}
  style={{ width: "100%" }}
/>;

Working Example:

Edit cranky-morning-5jpbc

Upvotes: 0

Quentin
Quentin

Reputation: 943142

The :focus-within CSS pseudo-class matches an element if the element or any of its descendants are focused. In other words, it represents an element that is itself matched by the :focus pseudo-class or has a descendant that is matched by :focus. (This includes descendants in shadow trees.)

MDN

Thus:

div {
  margin: 1em;
  padding: 1em;
  border: solid blue 3px;
  border-radius: 5px;
}

div:focus-within {
  box-shadow: 5px 5px 15px 5px #000000;
}
<div><input></div>
<div><input></div>

Upvotes: 3

Related Questions