React에서 div를 사용하여 버튼을 만드는 방법(그리고 하지 말아야 하는 이유)

15233 단어 reacta11yhtmlwebdev
웹 개발자로서 우리는 종종 웹 응용 프로그램에서 다양한 대화형 구성 요소를 만드는 작업을 수행합니다. 경우에 따라 기존 div 에 클릭 핸들러를 추가하거나 비의미적 요소에서 사용자 지정 <Button/> 구성 요소를 만드는 것이 매력적인 솔루션처럼 보일 수 있습니다.

액체 오류: 내부

이 기사에서는 button을 버튼으로 사용하지 않음으로써 발생하는 "숨겨진"버그와 이러한 결함을 극복하는 데 필요한 코드의 양을 설명하고자 합니다.

1. onClick 핸들러



이것은 div 에 상호 작용을 추가하는 명백한 첫 번째 단계입니다. 그러나 이름에서 알 수 있듯이 onClickdiv 핸들러는 마우스 클릭 이벤트만 지원합니다(onClick이 있는 button은 훨씬 더 많은 작업을 수행함). 불행하게도 마우스 이벤트만 지원하면 키보드와 화면 판독기 사용자는 알 수 없습니다. 이것이 실행 가능한 요소가 되었다는 정보를 받지 못하고 키보드와의 상호 작용을 트리거할 수도 없습니다.

//DO NOT USE: non-accessible implementation
const Button = () => {
  const onClick = () => console.log('clicked');

  return <div onClick={onClick}>My Button</div>
}



2. 역할 추가, tabindex



tabindex 과 역할을 div 에 추가하여 접근 가능한 솔루션을 향해 나아갈 수 있습니다. button role은 스크린 리더에게 이 요소를 버튼으로 알리고 실행 가능함을 암시합니다. tabindex="0"(React에서는 tabIndex={0})을 설정하면 이 요소가 키보드로 초점을 맞출 수 있습니다. 그럼에도 불구하고 사용자 지정 div은 여전히 ​​키보드로 트리거할 수 없습니다.






스콧 오엠지










ARIA Practices의 첫 번째 원칙은 "역할은 약속입니다"라고 말합니다. 그 문제에 대해 ARIA 또는 HTML을 사용할 때 인터페이스를 사용하거나 문서를 소비하는 사람들에게 무엇을 약속하는지 생각해 보십시오. 약속을 이행하고 있습니까? ?


오후 14:05 - 2019년 10월 12일











//DO NOT USE: non-accessible implementation
const Button = () => {
  const onClick = () => console.log('clicked');

  return <div role="button" tabIndex={0} onClick={onClick}>My Button</div>
}


3. 키보드 이벤트


button에 초점이 맞춰지면 SPACE 또는 ENTER 키로 트리거할 수 있습니다. 이 기능을 div 버튼에 가져오려면 onKeyPress을 구현하고 해당 특정 이벤트를 감시해야 합니다. 그런 다음 일치하는 이벤트를 onClick 핸들러에 수동으로 전달할 수 있습니다.

이 처음 세 단계를 구현하면 이제 div 버튼에 거의 액세스할 수 있습니다.

const Button = () => {
  const onClick = () => console.log("clicked");

  const onKeyPress = e => {
    const enterOrSpace =
      e.key === "Enter" ||
      e.key === " " ||
      e.key === "Spacebar" ||
      e.which === 13 ||
      e.which === 32;
    if (enterOrSpace) {
      e.preventDefault();
      onClick(e);
    }
  };
  return (
    <div
      role="button"
      onClick={onClick}
      tabIndex={0}
      onKeyPress={onKeyPress}
    >
      My Button
    </div>
  );
};


4. 비활성화 상태



종종 disabled 속성은 button 과의 사용자 상호 작용을 방지하는 데 사용됩니다. divtabindex으로 설정하고(키보드 포커스에서 제거) 버튼이 비활성화된 동안 -1 핸들러에서 클릭을 무시함으로써 동일한 기능을 onClick 버튼에 추가할 수 있습니다.

const Button = ({ disabled }) => {
  const onClick = () => {
    if (disabled) {
      return;
    }
    console.log("clicked");
  };

  const onKeyPress = e => {
    const enterOrSpace =
      e.key === "Enter" ||
      e.key === " " ||
      e.key === "Spacebar" ||
      e.which === 13 ||
      e.which === 32;
    if (enterOrSpace) {
      e.preventDefault();
      onClick(e);
    }
  };
  return (
    <div
      className={disabled ? "btn disabled" : "btn"}
      role="button"
      tabIndex={disabled ? -1 : 0}
      onClick={onClick}
      onKeyPress={onKeyPress}
    >
      My div Button
    </div>
  );
};


5. 버튼 스타일



또한 div의 스타일을 button처럼 보이게 하려면 Chrome에서 기본 스타일을 훔칠 수 있습니다(권장하지 않음).

//DO NOT USE: browser-specific styles
.btn {
  display: inline-block;
  -webkit-appearance: button;
  padding: 1px 7px 2px;
  cursor: default;
  font: 400 11px system-ui;
  color: buttontext;
  background-color: buttonface;
}
.btn.disabled {
  color: rgb(170, 170, 170);
}


결론


div에서 버튼을 만드는 것과 실제 button을 사용하는 것의 차이점을 설명하는 가장 쉬운 방법은 다음 button 스니펫을 사용하여 위의 모든 것(및 그 이상)을 구현하는 데 필요한 코드의 양을 보여주는 것이라고 생각합니다.

// PLEASE USE: most accessible solution
const Button = props => {
  const onClick = () => {
    console.log("clicked");
  };

  return (
    <button
      onClick={onClick}
      {...props}
    >
      My button Button
    </button>
  );
};

좋은 웹페이지 즐겨찾기