# 2021년 4월, Monthly I Learned
# 4/10
# UI 컴포넌트별로 신경써야할 것
https://uiplaybook.dev/
- 툴팁
- Focus되었을때도 보여야하고, Esc누르거나 다른곳 네비게이팅하면 사라진다.
- 툴팁 자체는 포커스되면 안됨.
- 기본 위치를 지정할 수 있게 해주되 공간이 없으면 다른 곳에 보이도록.
- 필수적인 정보를 넣지 말것
- 간결한 텍스트
- 툴팁 안에 인터렉티브한 요소(버튼, 링크 등)을 넣지 말것. 이걸 원하면 Popover를 쓸것.
- 개발팁
- 툴팁 넘 빨리 보여주면 UX에 안좋음. 100ms하삼.
- 부모가 짤라버릴수도 있으니 DOM hierarchy에서 부모 밖에 위치시킨다.
- disabled된 element(e.g.
<button>
)은 마우스이벤트 안먹으니까 Pointer events를 대신 써라. 아니면 위에<span>
등으로 감싸던가.
- 접근성
- exc누르면 사라짐.
- 툴팁 컨테이너 element에
role="tooltip"
- 툴팁 대상 되는 element에
aria-describedby="툴팁엘리먼트id"
로 엮어줘라- aria-describedby는 툴팁뿐 아니라 보충정보를 전달해줘야하는 곳에 다 사용가능. (e.g. input에 힌트 '비밀번호는 10자 이상이어야 합니다')
- Focus되었을때도 보여야하고, Esc누르거나 다른곳 네비게이팅하면 사라진다.
- 버튼
- Active와 Focus의 차이: Active는 눌려진 상태, Focus는 포커스.
- 포커스 스타일 꼭 넣어줘야한다! 그 전까진
outline: 0
넣지마
- 포커스 스타일 꼭 넣어줘야한다! 그 전까진
- 접근성
- W3 Success Criterion for Target Size에 따라 44px이상이어야 함.
- 텍스트가 없는 아이콘버튼 등은
area-label
넣어줘 - button태그의 기본 접근성지원이 많아서 무조건 태그 쓰는걸로. div등으로 하지 말구.
- Active와 Focus의 차이: Active는 눌려진 상태, Focus는 포커스.
- 셀렉트
- 접근성 1부터 대응하는게 큰일일테니 native
<select>
엘리먼트 쓰는걸 추천 - typeahead로 검색 가능해야한다
- 여유공간에 따라 다이나믹하게 보여야 한다
- onclick대신 mousedown이벤트를 쓰면 사용자가 한번에 셀렉하게 할 수 있다(onclick은 마우스를 떼야 발발됨)
- 셀렉트 열면 드롭다운으로 포커스 가야함 (Focus trap)
- 접근성 1부터 대응하는게 큰일일테니 native
- 노티피케이션 (스낵바/토스트... 근데 좀더 행동을 self describe하기 위해선 노티피케이션이란 이름이 좋겠다~)
- 액션에 대한 피드백 보여줄 때 씀(네트워크 에러, 저장되었습니다). 좀 더 끼어들면서 추가액션을 유도하는 노티피케이션은 AlertDialog를 대신 써라.
- 보통 4초 뒤에 사라짐. 액셔너블한 노티피케이션(e.g. 지웠습니다 - undo)은 10초도 무방.
- hover하면 타이머를 멈춤. 나가면 타이머 restart
- 접근성: role 어트리뷰트를 꼭 써야한다.
- role="alert" : 스크린리더가 다른거 읽다가도 즉각으로 읽어줌. e.g. 네트워크 에러 보여주는등의 상황
- role="status": 다 읽기까지를 기다림 e.g. 저장되었습니다 보여주는 등의 상황
- https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_status_role
# 4/15
# Compound패턴과 리액트 훅
https://kentcdodds.com/blog/compound-components-with-react-hooks
- 특정 목표를 해결하기 위해 붙어다녀야 하는 컴포넌트(e.g. Select / Option)들이 있을때 유연하게 API설계하는 방법
- React.cloneElement나 React context로 서로간의 관계를 만들어준다.
<Toggle onToggle={(on) => console.log(on)}>
<Toggle.On>The button is on</Toggle.On>
<Toggle.Off>The button is off</Toggle.Off>
<Toggle.Button />
</Toggle>
(kent 블로그에서 코드 복사해옴)
const ToggleContext = React.createContext();
function Toggle(props) {
const [on, setOn] = React.useState(false);
const toggle = React.useCallback(() => setOn((oldOn) => !oldOn), []);
useEffectAfterMount(() => {
props.onToggle(on);
}, [on]);
const value = React.useMemo(() => ({ on, toggle }), [on]);
// context안에 on, toggle을 전달
return (
<ToggleContext.Provider value={value}>
{props.children}
</ToggleContext.Provider>
);
}
function useToggleContext() {
const context = React.useContext(ToggleContext);
if (!context) {
throw new Error(
`Toggle compound components cannot be rendered outside the Toggle component`
);
}
return context;
}
function On({ children }) {
const { on } = useToggleContext();
return on ? children : null;
}
function Off({ children }) {
const { on } = useToggleContext();
return on ? null : children;
}
function Button(props) {
const { on, toggle } = useToggleContext();
return <Switch on={on} onClick={toggle} {...props} />;
}
// Toggle컴포넌트 안에 On, Off, Button 컴포넌트를 static 프로퍼티로 넣음 (optional)
Toggle.On = On;
Toggle.Off = Off;
Toggle.Button = Button;
# 자바스크립트의 메모리관리
https://developer.mozilla.org/ko/docs/Web/JavaScript/Memory_Management
- C와같은 저수준 언어는 메모리관리 위해 malloc() / free()를 사용하는데 js는 객체 생성시 자동으로 메모리 할당하고 쓸모없어졌을때 자동으로 해제함(가비지 컬렉션)