[UX Engineering] [Design System] Input

tmaxos.ux.sinri·2022년 8월 21일
1
post-thumbnail

React를 포함하여 컴포넌트 단위 개발이 가능한 환경에서는
코드 재사용성을 충분히 고려한 설계가 필요합니다.

의존도가 낮고 재사용성이 뛰어난 컴포넌트는
자연스럽게 디자인 시스템을 프로젝트에 구축해 나간다고 생각하는데요

사실 이 컴포넌트는 완전 새롭게 들어가지는 않았는데요.
초기에 설계한 컴포넌트가 재사용하기에 좋지 않았기 때문에
이번 주말동안 찬찬히 다시 고쳐봤습니다.

화면 설계

처음 input 태그를 스타일링 할때 제가 실수했던 부분은
인터렉션을 충분히 고려하지 못하고
input태그와 :focus, ::placeholder 와 같은 가상 선택자로만 구현하려고 했다는 점입니다.

위와 같은 가이드에서는 input의 부모 태그를 container로 설정하여서
container의 focus 상태를 관리하는 편이 수월했습니다.
Input.jsx

<div className="container">
	<label>이름<span>*</span></label>
    <input type="text" />
   	<span>invalid message</span>
</div>

Custom한 컴포넌트를 적용한 다이얼로그 컴포넌트는 아래와 같이 구성해보겠습니다.
Dialog.jsx

<div>
  <form>
      <Input />
      <Input />
      <Input />
      <button></button>
  </form>
</div>

인터렉션 이해하기

요즘 css가 어렵습니다...

focus 상태

이때 사용한 이벤트 trigger는 onFocusonBlur였습니다.
이 이벤트를 통해 부모 태그인 container의 focus 상태를 관리하는 함수를 작성했습니다.

  ...
  const focused = (event) => {
    event.target.parentElement.classList.remove("invalid")
    event.target.parentElement.classList.add("focused")
  };
  ...
  return <input
      onFocus={focused}
      onBlur={focusedout}
      ...
    />

label 위치 css

처음 위의 동작을 label 태그 하나만 올렸다 내렸다 했습니다.
그런데, click 이벤트를 관리하려고 하니 label이 계속 선택되는 답답한 상황이 생겼습니다.
그래서 label::placeholder를 적절히 섞었습니다.

  return
  	<label>
      {label}
      {required && <span className="required">&#42;</span>}
    </label>
  	<input
      onFocus={focused}
      onBlur={focusedout}
      placeholder={label}
      ...
     />

유효성 스타일 초기화 하기


브라우저에서 제공하는 기본 유효성 메세지 입니다.
저희가 원하는 게 아니니 초기화 하겠습니다.
onInvalid={invalid} 에서 event.preventDefault()로 제어할 수 있습니다.
초기화 후에는 submit 동작을 해도 default 메세지가 뜨지 않습니다.

유효성 검사 기능 넣기 - 정규식

자바스크립트에서 유효성 검사를 하려면 정규식부터 떠오르죠!
유효성 검사를 제외하고도 사이트 내에 text를 관리할 때도 정규식을 이용하면
너무너무 편하답니다.
기획 문서를 보고 여러 가지 케이스들을 설정해 보았습니다.
짱짱 유용한 링크 공유 >> 😉정규식 테스트 사이트

제 목표는 3번이 선택되는 것입니다.


정규식 만드는 건 사실 저도 처음이고 이미 잘만들어진게 있을 거 같긴하지만,
한번 만들어봣습니다...


이정도면 괜찮을 거 같네욤

완성 후

props를 통해서 이쁘게 넘겨주는 게 필요할거 같았습니다.
이를 위해 몇가지 default 값 설정, refactoring, capsule 작업을 통해 완성된 최종 컴포넌트입니다.
Input.jsx

...
return <div className={`textfield --t1 ${typed()}`}>
    <label>
      {inf.label}
      {inf.required && <span className="required">&#42;</span>}
    </label>
    {inf.required && <span className="placeholder-required">&#42;</span>}
    <input
      onFocus={focused}
      onBlur={focusedout}
      placeholder={inf.label}
      className={'value' + inf.className}

      value={inputVal}
      onChange={(event) => onChange(event)}
      required={inf.required}

      type={inf.type}
      onInvalid={invalid}
      pattern={pattern(inf.type)}
    />
    <span className="invalid-message">{invalidMessage(inf.label)}</span>
  </div>

Dialog.jsx

...
<Form props={{
	onSubmit: handleSubmit
 }}>
 	<FormInput props={{
    	label: '이름',
        required: true,
        type: 'text',
	}} />
    <FormInput props={{
    	label: '소속회사 또는 학교',
        required: true,
        type: 'text'
	}} />
    <FormInput props={{
    	label: '이메일 (예: tmaxos@tmax.co.kr)',
        required: true,
        type: 'email'
	}} />
    <ButtonRound props={{
    	type: 'submit',
	}}>
	    {"String"}
    </ButtonRound>
</Form>
...

아직 완벽한 실력은 아니지만,,,

변수명과 함수명 등.. 아쉬운 점이 많은 컴포넌트지만,
그래도 이전에 설계한 Input 컴포넌트에 비해서 많이 개선된거 같습니다.
앞으로도 독립성이 강하고 재사용성이 뛰어난 컴포넌트를 설계하는 연습을 하여서
디자인 시스템이 잘 정착할 수 있도록 노력하겠습니당 😊

//
작성 - 정수진C
🦘햇병아리sinri0809였습니다.
피드백은 환영입니다.

profile
티맥스오에스 UX팀 sinri

0개의 댓글