【Material-UI】TextField 컴퍼넌트의 disabled 스타일을 커스터마이즈 하는 방법

14443 단어 CSSReactmaterial-ui

소개



프레임워크나 라이브러리를 이용해 개발을 하면, 역시 적지 않고, 커스터마이즈 할 필요가 나올 수 있습니다.
이번은, 「React」 × 「UI 프레임워크의 Material-UI」를 사용해 개발할 때에 조금 손질한 포인트가 있었으므로 소개입니다.

대상의 컴퍼넌트 【TextField】



입력 필드 및 선택 상자와 같은 HTML 태그의 <input>로 사용할 수 있습니다.

Material-UI 정보



Material-UI는 원래 모든 API가 준비되어 있어, 커스터마이즈성도 상당히 담보되어 있어 사용하기 쉬운 인상입니다.
그러나 이번에 소개하는 TextField 컴포넌트로 입력하고 싶지 않은 disabled UI를 변경하고 싶을 때 문제가 나왔습니다.

기본 사용자 정의



기본적으로 준비되어 있는 커스터마이즈 방법으로서, 공식 문서를 베이스로 Button 컴퍼넌트의 커스터마이즈를 실시했을 때의 소스 코드가 이하입니다.
import React from "react";
import Button from "@material-ui/core/Button";
import FormLabel from "@material-ui/core/FormLabel";
import { makeStyles } from "@material-ui/core/styles";
import "./styles.css";

const styles = makeStyles(theme => ({
  rootBtn: { // Buttonクラスのrootクラス
    marginRight: "1em",
    backgroundColor: "#ff8800",
    "&:disabled": {
      color: "#bababa",
      backgroundColor: "#dadada"
    }
  }
}));

export default function App() {
  const classes = styles();

  return (
    <div className="App">
      <h1>ボタンの例</h1>
      <div>
        <Button className={classes.rootBtn}>Button</Button>
        <FormLabel>通常デザイン</FormLabel>
      </div>
      <div>
        <Button className={classes.rootBtn} disabled>
          Button
        </Button>
        <FormLabel>disabledデザイン</FormLabel>
      </div>
    </div>
  );
}



위가 작동하는 디자인으로 아래가 disabled로 설정된 경우입니다.
공식 문서에서 볼 수 있듯이 disabled API가 true이면 루트에 의사 클래스를 선언하도록 지시됩니다.

Pseudo-class applied to the root element if disabled={true}.
참조 : 공식 문서에서

이번에는 루트 클래스에 rootBtn를 지정하고 해당 의사 클래스에 disabled 스타일을 정의합니다.
활성화되는 트리거는 disabled API가 true인 경우이므로, 아래의 버튼일 때만 이 스타일이 유효하게 되어 있습니다.

이런 식으로 API는 CSS 클래스에 준비되어있어 스타일을 환경에 맞게 쉽게 사용자 정의 할 수있는 것이 큰 매력입니다.

TextField에서 사용자 정의



위의 Button 구성 요소의 느낌으로 만들면 실패했습니다.
전혀 스타일이 효과가 없다. 어쩔 수 없이 문서를 바라보고 있어도 한결같이 해결 방법은 보이지 않았습니다.

그래서 구조를 살펴보면, TextField 컴퍼넌트는, 몇개의 컴퍼넌트가 합쳐서 구성되고 있는 것 같았습니다.
<!-- inputタグラップされて形成されている -->
<div class="TextField">
  <input class="input-base">
  ...
  </>
</>

disabled의 스타일은 <input> 로 정의되고 있는 것 같았으므로, 어떻게 든 여기를 덮어쓰는 방법이 필요했습니다.

로컬 규칙을 참조하는 $ruleName



이런 쓰는 방법이 있었다니 몰랐다.

const styles = {
  root: {
    '&$disabled': {
      color: 'white',
    },
  },
  disabled: {},
};

이것을 참고로 스타일하면 잘 스타일이 효과가 있었습니다.
소스는 다음과 같습니다.
import React from "react";
import TextField from "@material-ui/core/TextField";
import FormLabel from "@material-ui/core/FormLabel";
import { makeStyles } from "@material-ui/core/styles";
import "./styles.css";

const styles = makeStyles(theme => ({
  rootTxt: {
    marginRight: "1em",
    "&$disabled": {
      color: "#bababa",
      backgroundColor: "#dadada"
    }
  },
  disabled: {}
}));

export default function App() {
  const classes = styles();

  return (
    <div className="App">
      <h1>テキストフィールドの例</h1>
      <div>
        <TextField
          InputProps={{
            classes: {
              root: classes.rootTxt,
              disabled: classes.disabled
            }
          }}
          defaultValue="TextField"
        />
        <FormLabel>通常デザイン</FormLabel>
      </div>
      <br />
      <div>
        <TextField
          InputProps={{
            classes: {
              root: classes.rootTxt,
              disabled: classes.disabled
            }
          }}
          defaultValue="TextField"
          disabled
        />
        <FormLabel>disabledデザイン</FormLabel>
      </div>
    </div>
  );
}



사이고에게



이번에 다룬 것은 TextField 컴퍼넌트입니다만, 그 밖에도 컴퍼넌트를 곱한 형태로 표현되고 있는 컴퍼넌트는 많이 있습니다.
그러한 컴퍼넌트도 아마 이 쓰는 방법이 필요하게 될 것 같네요.

전제로 알고 있다고 모르기 때문에, 사용법이나 설계가 크게 바뀔 것 같다고 느끼면서 이번은 어떻게든 해결할 수 있었습니다!

소개한 내용의 Sandbox



P.S 깨달았을 무렵에는 이런 일을 썼다! The TextField is a convenience wrapper for the most common cases (80%). It cannot be all things to all people, otherwise the API would grow out of control.

좋은 웹페이지 즐겨찾기