2

I have an input and I would like to change the border of the parent div when I focus on the input.
https://codesandbox.io/s/jolly-fermat-e2tyo?file=/src/App.js

import React from "react";
import ReactDOM from "react-dom";
import { withStyles } from "@material-ui/core/styles";

const InputComponent = ({ value, classes }) => (
  <div className={classes.inputContainer}>
    <input value={value} className={classes.input} />
  </div>
);

const styles = {
  input: {
    fontSize: 14,
    padding: 15,
    "&:focus": {
      backgroundColor: "#F8F8F8",
      $inputContainer: {
        //I know this won't work
        border: "1px solid #006CFF"
      }
    }
  },
  inputContainer: {
    border: "1px solid black",
    backgroundColor: "white"
  }
};

const InputWithStyles = withStyles(styles)(InputComponent);

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <InputWithStyles />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);

Currently using withStyles HOC from material-ui, and using the classes props on the component

Version used: "@material-ui/core": "^3.9.2"

jaycee
  • 301
  • 2
  • 13
  • It would be easier to help you if you provided a [code sandbox](https://codesandbox.io/s/new) showing the exact element you are trying to style and how you are currently trying to apply those styles to the element. – Ryan Cogswell May 19 '20 at 15:08
  • I have added a codepen @RyanCogswell as requested – jaycee May 20 '20 at 11:35

1 Answers1

1

The short answer is that this isn't possible in CSS (see Is there a CSS parent selector?).

The way to achieve the desired result is to change the parent (e.g. add/remove a "focused" class) via JavaScript in response to focus/blur events. This is the approach Material-UI uses internally to change the styles of input containers (see https://github.com/mui-org/material-ui/blob/v4.9.14/packages/material-ui/src/InputBase/InputBase.js#L414).

Here is a modified version of your sandbox using this approach:

import React from "react";
import ReactDOM from "react-dom";
import { withStyles } from "@material-ui/core/styles";
import classnames from "classnames";

const InputComponent = ({ value, classes }) => {
  const [focused, setFocused] = React.useState(false);
  return (
    <div
      className={classnames(classes.inputContainer, {
        [classes.focused]: focused
      })}
    >
      <input
        onFocus={() => setFocused(true)}
        onBlur={() => setFocused(false)}
        value={value}
        className={classes.input}
      />
    </div>
  );
};

const styles = {
  input: {
    fontSize: 14,
    padding: 15,
    "&:focus": {
      backgroundColor: "#F8F8F8"
    }
  },
  inputContainer: {
    border: "1px solid black",
    backgroundColor: "white",
    "&$focused": {
      border: "1px solid #006CFF"
    }
  },
  focused: {}
};

const InputWithStyles = withStyles(styles)(InputComponent);

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <InputWithStyles />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit Change input container based on input focused state

I was expecting to see your example using one of the Material-UI input components. If you are actually using one of those and removed it for the sake of simplicity in your example, then let me know. The way to handle this for Material-UI inputs would be a bit different -- Material-UI is already managing knowledge of the focused state, so it generally wouldn't be necessary to repeat that work. Instead, you would just leverage the class that Material-UI is already adding to the input container.

Ryan Cogswell
  • 43,837
  • 6
  • 114
  • 117
  • 1
    Thanks for the answer, yes I am using a custom input component, And that is the conclusion that I came through as well :D – jaycee May 20 '20 at 16:00