녕후킴
  • 📎 Tab 컴포넌트 목적

    서로 관련이 있고, 동일한 계층에 존재하는 컨텐츠의 navigation을 돕는 요소

    mui

    📎 Tab 컴포넌트 설계하기

    선택한 탭에 대해서 패널들 중에 탭에 대응하는 패널만 보여지는데, 그렇다면 패널들에 대해 ul과 li를 써는게 맞나? 고민했다. 패널들 중 하나만 보여지기 때문에 굳이 쓰진 않아도 될것 같다.

    How to create an accessible Tabs component in React?의 문서에서 hidden을 쓰는데, 옳바른 쓰임세가 아닌 것 같다.

    How to create an accessible Tabs component in React?

    Creating an accessible tab component with React

    📎 section 태그와 article 태그

    section 태그의 특징은 다음과 같다.

    1. 각각의 section은 heading 태그가 존재한다.
    2. 주제별 컨텐츠를 그룹핑한다. 대표적인 예로 챕터가 있다.
    3. 페이지 내에 section이 하나인 경우, section을 사용하지 않는다.

    article 태그의 특징은 다음과 같다.

    1. 뉴스 기사, 블로그 게시글 등 "독립적으로 공유되는" 콘텐츠를 표현한다.

    section 태그와 article 특징은 전혀 관련이 없다. 다른 주제를 가진 article들을 그루핑할 때 사용할 수도 있고, 하나의 article이 서로 다른 section 태그를 가질 수 있다. 혹은 동시에 사용되지 않을 수도 있다.

    <article> <section id="introduction"> </section> <section id="content"> </section> <section id="summary"> </section> </article> // or... <section id="main"> <article> <!-- first blog post --> </article> <article> <!-- second blog post --> </article> <article> <!-- third blog post --> </article> </section>

    How to correctly use "section" tag in HTML5?

    📎 Compound 컴포넌트 패턴 소감

    Component 컴포넌트 패턴 특징은 다음과 같다.

    1. 부모의 상태를 공유하기 위해 Context API가 사용된다.
    2. Compound 컴포넌트 패턴은 JSX가 컴포넌트 바깥으로 드러나는 특징이 있다.

    좋았던 점은 Compound 컴포넌트를 구성하는 컴포넌트들이 자신에게 필요한 prop을 가져가기 때문에 알맞은 관심사 및 책임 분리가 가능하다.

    안좋았던 점은 다음과 같다.

    1. Compound 컴포넌트 내부에 들어가는 컴포넌트 명을 전부 알아야한다.
    2. JSX가 길어진다.
    3. ContextAPI가 딸려온다.

    종합적으로보면, IconButtonGroup 컴포넌트처럼 UI가 간단한 경우에는 불리한 것 같다. 페이지 전반에 걸쳐서 복잡한 UI 규칙을 갖는 Header 컴포넌트 혹은 Tab 컴포넌트와 같은 경우에 유리한 것 같다.

    📎 Linkable Tab 컴포넌트 설계하기

    How to Create Linkable NextJS Tabs using HeadlessUI and TailwindCSS

    📎 wai-aria에 관한 이해

    WAI ARIA는 Web Accessiblity Initiate Accessible Rich Internect Application의 약자로, role과 attribute로 구성되어 스크린 리더를 도와 웹 접근성을 향상시킨다. ARIA에 대해서는 "No ARIA is better than bad ARIA."란 말이 있다

    accessible name이란 U요소가 갖는 이름인데, 이 이름은 OS와 같은 플랫폼이 갖는 accessibility API를 통해서 Assistive Technologies에 전달된다.

    accessible name은 보여지는 경우도 있고 보여지지 않는 경우도 있다. 보여지는 경우는 다시 accessible name이 요소 내부에 존재하는 경우와 요소 외부에 존재하는 경우로 나뉜다. 요소 내부에 존재하는 경우는 <button/>, <a/>, <td/> 등의 태그들이 갖는 내부 텍스트들이 그 예이며, 요소 외부에 존재하는 경우는 <textarea/>, <fieldset/>, <table/> 등의 태그들이 각각 <label/>, <legend/>, <caption/> 태그들과 연결되는 경우이다. 반대로 보여지지 않는 경우는 <img/> 태그가 alt 태그를 갖는 경우다.

    모든 UI요소는 accessible name을 가져야하는데, accessble name이 존재하지 않는 경우 aria-label과 aria-labelledby를 이용해서 만들어 줄수 있다. aria-labelledby는 id를 이용하여 다른 DOM 요소를 참조하여 accessible name을 결정할 때 사용되고, 참조할 DOM 요소가 없는 경우 aria-label을 이용한다.

    aria-describedby도 aria-labelledby와 동일하게 동작하는데 labelledby는 describedby에 비해서 훨씬 짧은 정보를 제공한다는 차이점이 존재한다. aria-labelledby는 복잡한 규칙이 존재하니 사용에 유의하자.

    ARIA: presentation role in Mozilla

    Aria in Mozilla

    Accessiblity API in W3C

    Accessible name in W3C

    ARIA Authoring Practices Guide (APG)

    📎 hidden attribute의 의미

    요소를 숨긴다. 이를 통해 react에서 요소를 숨기는 방법을 하나 더 알게됐다.

    1. conditional rendering
    2. display: none
    3. visibility: hidden
    4. hidden

    display: none과 hidden은 거의 동일하다. (react에서의 동작도 동일하다) 단, 사용해야 하는 때는 다음과 같이 구분할 수 있다. hidden은 숨기려는 요소가 현재 페이지 컨텐츠의 일부가 아닐 때 사용(semantic한 관점)하고, display:none은 숨기려는 요소가 현재 페이지 컨텐츠의 일부일 때 사용한다.

    예를들면 폼을 작성하는 와중에 유저가 잘못 기입했을 때 보여져야하는 에러 메세지나 혹은 폼을 작성하고나서 보여져야하는 성공 메세지는 hidden이 적합하다. 에러 메세지든 성공 메세지든 실제 조건이 충족되지 않는다면 보여지지 않기 때문에 페이지 컨텐츠의 일부로 보기 어렵기 때문이다

    반면에 뷰포트 등의 제약으로 특정 문단을 숨겨놨다가 토글 버튼을 눌러서 보여주거나 혹은 유저가 어떤 요소를 Hover하거나 클릭했을 때 특정 요소를 보여주어야 하는 경우에는 display: none이 적합하다.

    hidden은 스크린 리더가 읽어주지 않지만, display: none의 경우 스크린 리더마다 읽어주는 경우도 있고, 읽어주지 않는 경우도 존재한다고 한다.

    tab panel을 설계한다면 display: none을하고 여기에 aria-hidden=true를 이용하여 스크린 리더에게 적절하게 알려주도록 하자.

    What is the difference between the hidden attribute (HTML5) and the display:none rule (CSS)?

    hidden-attribute-ignored

    Using the hidden attribute vs conditionally rendering a component

    📎 presentation role의 의미

  • 📎 Tailwind의 동작

    tailwind는 빌드할 때 애플리케이션을 스캔하면서 사용되는 class들만 남기고 나머지는 전부 purge한다. 그렇기 때문에 애플리케이션 사이즈가 아무리 커도 CSS 파일이 10kb를 넘지 못한다.

    완벽하지 않은 dynamic class name을 사용하는 방법은 safelist를 사용하는 방법 외에는 존재하지 않는다. safelist는 purge에서 제외하기 때문이다. 완벽한 dynamic class name은 여전히 사용 가능하다.

    // 완벽하지 않은 dynamic class name <div class="text-{{ error ? 'red' : 'green' }}-600"></div> // 완벽한 dynamic class name <div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>

    Dynamically build classnames in TailwindCss

    Optimizing for Production