탭 전환 - Tabpanel

TAB/Panel ui

Resources

5 STEPS

  • STEP 1. 사용자에게 각 element의 역할이 무엇인지 설명해야 한다: ROLE (eg.<input type="checkbox">)
  • STEP 2. 사용자에게 element의 속성과 중요 연관성을 알려야 한다: PROPERTY (eg. <input type=... disabled required readonly>)
  • STEP 3. 사용자에게 element의 상태를 알려야 한다: STATE ( eg. ... checked="true" disabled="false">)
  • STEP 4. 상태변화가 있을 시 사용자에게 알려야 한다: STATE CHANGE
  • STEP 5. 키보드 접근성 제공 (TAB키로 이동)

STEP1: ROLE 정의하기

<!-- tablist 영역 -->
<ul role="tablist">
    <li id="tabBtn1" role="tab">TAB 1</li>
    <li id="tabBtn2" role="tab">TAB 2</li>
</ul>
<!-- panel1 -->
<div id="panel1" role="tabpanel">
    <h3>PANEL 1</h3>
</div>
<!-- panel2 -->
<div id="panel2" role="tabpanel">
    <h3>PANEL 2</h3>
</div>
  • 탭 리스트를 만들 때 <ul>Unordered List(순번이 없는 리스트)로 설명되기때문에 정확한 역할 설명이 아니다.
  • 그냥 리스트가 아닌 이것은 탭 리스트다! role="tablist" 라고 역할 부여해 정확한 역할 설명을 해준다.
  • <li>도 마찬가지로, 리스트가 아니라 role="tab" 탭 역할을 하는 Element 라고 역할을 변경해준다.
  • <div>는 아무 역할이 없는 Element 이며, role="tabpnel" 로 역할을 부여한다.
  • role attribute의 값은 지정되어있고, 하위 구조 역시 역할에 따라 제한이 있다. 임의로 쓰게 되면 밸리데이션 에러가 난다.

STEP2: 중요 Element간의 관계와 속성

<!-- tablist -->
<ul class="tablist" role="tablist">
    <li id="tab1" role="tab" aria-controls="panel1">TAB 1</li>
    <li id="tab2" role="tab" aria-controls="panel2">TAB 2</li>
</ul>
<!-- panel1 -->
<div id="panel1" role="tabpanel" aria-labelledby="tab1" >
    <h3>PANEL 1</h3>
</div>
<!-- panel2 -->
<div id="panel2" role="tabpanel" aria-labelledby="tab2" >
    <h3>PANEL 2</h3>
</div>

aria-controls (property)

  • 이 element로 제어하는 element(대상)를 식별
  • ID 값으로 참조

aria-labelledby (property)

  • 이 element를 레이블링(참조?) 하고있는 element(대상)를 식별하는 속성

Element간의 연관성

  • id="tab1"Element에 이벤트 발생시 id="panel1"Element의 가시성을 변경한다.
  • id="tab1"Element는 id="panel1"을 컨트롤하는 element이다.
  • id="tab1"aria-controls="panel1"라고 연관 지어 줄수있다.
  • id="panel1"Element는, id="tab1"이 참조 하고있다.
  • id="pannel1"aria-labelledby="tab1"라고 연관 지어 줄수있다.

STEP3: STATE 초기화

<!-- tablist -->
<ul role="tablist">
    <li id="tab1" role="tab" class="active" aria-controls="panel1" aria-selected="true">TAB 1</li>
    <li id="tab2" role="tab" aria-controls="panel2" aria-selected="false">TAB 2</li>
</ul>
<!-- panel1 -->
<div id="panel1" role="tabpanel" class="active" aria-labelledby="tab1" aria-hidden="false">
    <h3>PANEL 1</h3>
</div>
<!-- panel2 -->
<div id="panel2" role="tabpanel" aria-labelledby="tab2" aria-hidden="true">
    <h3>PANEL 2</h3>
</div>
  • UI 초기 상태를 지정한다
  • 첫 탭은 선택되어 있고, 첫번째 탭에 연결된 패널을 보여준다.
  • 각 탭에 aria-selected 라는 속성을 추가하고, 선택되어 있는 탭이면, true, 아닌 탭이면 false로 지정한다. (javascript에서 속성값을 가져오면 string 이다 boolean 노노)
  • [role="tabpanel"] 은 모두 숨기고, 보여줄 [role="tabpanel"]만 보여주면 된다.
  • [role="tabpanel"]aria-hidden 이라는 속성을 추가해, 숨길 시 true, 아닐 시 false로 지정한다.
  • [aria-hidden="true"], [aria-hidden="false"] 이 셀렉터들은 IE9 이하 버전 브라우저 들에서 안 먹힌다.
  • .active 클래스를 추가해서, CSS로 .active 클래스가 붙었을 때만 보여지게 해준다.
  • aria-* 속성도 IE7 에서 안 먹으니, 탭도 .active 클래스로 스타일을 추가해준다
/* tab */
[role='tab'] {
    background: #fff;
    color: black;
}
[role='tab'].active {
    /* 활성화 스타일 */
    background: gray;
    color: #fff;
}

/* panel */
[role='panel'] {
    display: none;
}
[role='panel'].active {
    /* 활성화 스타일 */
    display: block;
}

이제 스크립트로 상태변경을 해주면 된다.

STEP 4: STATE 변경

TODOS
Tab

  • 탭을 선택하면,
  • 해당 탭의aria-selectedSTATEtrue로 변경하여 선택 표시를 하고,
  • 구 버전 IE... 선택된 탭에 active클래스를 붙여, 활성화된 스타일로 변경해주고,
  • 나머지 탭의 STATEfalse로 변경하여, 선택해제를 함,
  • 구 버전 IE... 선택된 탭의 형제 탭들의 active클래스를 제거해서, 스타일 초기화를 해준다.

Panel -

  • 탭을 선택하면, 해당 탭이 컨트롤하고있는 panel 을 찾고
  • 해당 패널의 aria-hiddenSTATEfalse 로 변경하여 보여지게 하고,
  • 구 버전 IE... 해당 패널에 active클래스를 붙여, 활성화된 스타일로 변경해주고,
  • 나머지 패널의 aria-hiddenSTATEtrue 로 변경하여 숨김.
  • 구 버전 IE... 해당 패널의 형제 패널의 active클래스를 제거해 , 스타일 초기화를 해준다,

// 이벤트 핸들러 - 이벤트 발생시 동작할 함수
function eventHandler(e) {
  var $eTarget = $(e.currentTarget);
  var $targetPanel = $('[aria-labelledby="' + $eTarget.attr('id') + '"]');
    $eTarget
        .attr('aria-selected', true)
        .addClass('active') // 구버전 IE
        .siblings('[role="tab"]')
        .attr('aria-selected', false)
        .removeClass('active'); // 구버전 IE

    $targetPanel
        .attr('aria-hidden', false)
        .addClass('active') // 구버전 IE
        .siblings('[role="tabpanel"]')
        .attr('aria-hidden', true)
        .removeClass('active'); // 구버전 IE
}

// 이벤트 바인딩 - 이벤트와, 실행될 함수를 연결해줌
$('[role="tab"]').on('click', eventHandler);

STEP 5: 키보드 접근성

<!-- tablist -->
<ul role="tablist">
    <li id="tab1" role="tab" class="active" aria-controls="panel1" aria-selected="true" tabindex="0">TAB 1</li>
    <li id="tab2" role="tab" aria-controls="panel2" aria-selected="false" tabindex="0">TAB 2</li>
</ul>
<!-- panel1 -->
<div id="panel1" role="tabpanel" class="active" aria-labelledby="tab1" aria-hidden="false">
    <h3>PANEL 1</h3>
</div>
<!-- panel2 -->
<div id="panel2" role="tabpanel" aria-labelledby="tab2" aria-hidden="true">
    <h3>PANEL 2</h3>
</div>

<li ... role="tab">탭 Element에 tabindex="0" 추가. 탭 포커스가 가능하게 해주는 속성이다.

function eventHandler(e) {
  var $eTarget = $(e.currentTarget);
  var $targetPanel = $('[aria-labelledby="' + $eTarget.attr('id') + '"]');

  // 조건문으로 이벤트 구분
  if (e.type === 'click') { // 클릭 시 동작
    $eTarget
      .attr('aria-selected', true)
      .addClass('active')
      .siblings('[role="tab"]')
      .attr('aria-selected', false)
      .removeClass('active');

    $targetPanel
      .attr('aria-hidden', false)
      .addClass('active')
      .siblings('[role="tabpanel"]')
      .attr('aria-hidden', true)
      .removeClass('active');
  } else if (e.type === 'keydown' && e.which === 13) { // 키가 눌렸을 때 && 키가 엔터일 때
    // e.which 는 keycode 값을 판별하는데 13 이 엔터 키에 해당되는 keycode
    $(this).click(); // 현재 Element에 클릭이벤트 발생시킴
  }
}

// 바인딩에 keydown 이벤트 추가 - 쉼표 없음
$('[role="tab"]').on('click keydown', eventHandler);

Notes

  • 이게 불편한점이 아이디 값인데, 아이디 중복때문에 귀찮아 질 수가 있음
  • 아이디를 제거할 수 있는 방법이 있으면 좋을 것 같다

results for ""

    No results matching ""