Tabs

같은 맥락의 내용을 여러 패널로 나누어 전환합니다.

Live preview
컴포넌트를 조작하면 여기에 결과가 표시됩니다.
코드 보기
HTML
<sy-tab-group
  active="0"
  type="line"
  position="top"
  size="medium"
  align="left"
  padding="none"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">개요</sy-tab>
  <sy-tab tabkey="tab-1">활동</sy-tab>
  <sy-tab tabkey="tab-2">설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>

사용 가이드

#

같은 맥락에 있는 관련 내용을 나누어 전환합니다. 앱 전체의 이동에는 Navigation, 순차 작업에는 Steps가 알맞습니다.

  1. 탭과 본문 짝짓기

    sy-tab의 tabkey와 sy-tab-content의 name을 일치시키세요.

  2. 활성 탭 정하기

    active는 0부터 시작합니다. 코드에서는 setActiveTab()으로 전환합니다.

  3. 많거나 닫을 수 있는 탭

    많은 탭은 오버플로 메뉴로 탐색할 수 있습니다. 닫기 기능이 필요한 탭만 closable로 설정하세요.

예제

#

기본 탭

tabkey와 콘텐츠의 name을 연결해 패널을 전환합니다.

코드 보기
HTML
<sy-tab-group
  active="0"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">개요</sy-tab>
  <sy-tab tabkey="tab-1">활동</sy-tab>
  <sy-tab tabkey="tab-2">설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>

카드 스타일

경계가 필요한 작업 영역에 카드 스타일을 적용합니다.

코드 보기
HTML
<sy-tab-group
  active="0"
  type="card"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">개요</sy-tab>
  <sy-tab tabkey="tab-1">활동</sy-tab>
  <sy-tab tabkey="tab-2">설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>

세로 탭

position을 left 또는 right로 설정해 콘텐츠 옆에 배치합니다.

코드 보기
HTML
<sy-tab-group
  active="0"
  position="left"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">개요</sy-tab>
  <sy-tab tabkey="tab-1">활동</sy-tab>
  <sy-tab tabkey="tab-2">설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>

탭 닫기

닫기 아이콘으로 탭과 연결된 콘텐츠를 함께 제거합니다.

코드 보기
HTML
<sy-tab-group
  active="0"
  type="card"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0" closable>개요</sy-tab>
  <sy-tab tabkey="tab-1" closable>활동</sy-tab>
  <sy-tab tabkey="tab-2" closable>설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>

닫기 전 확인

닫기 요청을 받은 뒤 확인 버튼으로 제거합니다. 취소하면 탭을 유지합니다.

코드 보기
HTML
<sy-tab-group
  active="0"
  id="sample"
  style="height:190px"
>
  <sy-tab
    tabkey="draft"
    closable
    manual-close
  >작성 중</sy-tab>
  <sy-tab-content name="draft">
    <p>저장하지 않은 초안입니다.</p>
  </sy-tab-content>
</sy-tab-group>
<div id="close-prompt" hidden>
  <p>작성 중인 탭을 닫을까요?</p>
  <sy-button id="confirm-close" variant="primary">닫기 확인</sy-button>
  <sy-button id="cancel-close">계속 작성</sy-button>
</div>

<script type="module">
  await (root => {
    const group = root.querySelector('#sample');
    const prompt = root.querySelector('#close-prompt');
    let pending;
    group.addEventListener('closed', event => {
      if (!event.detail.isManualClose) return;
      pending = event.detail.tabkey;
      prompt.hidden = false;
    });
    root.querySelector('#confirm-close').addEventListener('click', async () => {
      await group.closeTab(pending);
      prompt.hidden = true;
    });
    root.querySelector('#cancel-close').addEventListener('click', () => {
      pending = undefined;
      prompt.hidden = true;
    });
  })(document);
</script>

일부 탭 비활성화

설정 탭만 비활성화한 상태입니다. 나머지 탭은 전환할 수 있습니다.

코드 보기
HTML
<sy-tab-group
  active="0"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">개요</sy-tab>
  <sy-tab tabkey="tab-1">활동</sy-tab>
  <sy-tab tabkey="tab-2" disabled>설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>

코드에서 탭 제어

탭 인덱스로 전환하고 선택된 인덱스를 조회하거나 키로 닫을 수 있습니다.

코드 보기
HTML
<sy-tab-group
  active="0"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0" closable>개요</sy-tab>
  <sy-tab tabkey="tab-1" closable>활동</sy-tab>
  <sy-tab tabkey="tab-2" closable>설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">활동 탭으로 이동</sy-button>
  <sy-button id="action-1" size="small">현재 탭 조회</sy-button>
  <sy-button id="action-2" size="small">설정 탭 닫기</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setActiveTab(1);
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget1 = document.querySelector("#sample");
  document.querySelector('#action-1').addEventListener('click', async () => {
    const result = await actionTarget1.getActiveTab();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget2 = document.querySelector("#sample");
  document.querySelector('#action-2').addEventListener('click', async () => {
    const result = await actionTarget2.closeTab("tab-2");
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

많은 탭

폭이 부족하면 더보기 메뉴로 숨겨진 탭을 선택합니다.

코드 보기
HTML
<sy-tab-group active="0" style="width:100%;height:240px">
  <sy-tab tabkey="report-0">보고서 1</sy-tab>
  <sy-tab-content name="report-0">
    <p>보고서 1 내용입니다.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-1">보고서 2</sy-tab>
  <sy-tab-content name="report-1">
    <p>보고서 2 내용입니다.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-2">보고서 3</sy-tab>
  <sy-tab-content name="report-2">
    <p>보고서 3 내용입니다.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-3">보고서 4</sy-tab>
  <sy-tab-content name="report-3">
    <p>보고서 4 내용입니다.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-4">보고서 5</sy-tab>
  <sy-tab-content name="report-4">
    <p>보고서 5 내용입니다.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-5">보고서 6</sy-tab>
  <sy-tab-content name="report-5">
    <p>보고서 6 내용입니다.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-6">보고서 7</sy-tab>
  <sy-tab-content name="report-6">
    <p>보고서 7 내용입니다.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-7">보고서 8</sy-tab>
  <sy-tab-content name="report-7">
    <p>보고서 8 내용입니다.</p>
  </sy-tab-content>
</sy-tab-group>

이벤트와 전달 값

컴포넌트를 조작하고 최근 이벤트의 이름과 detail 값을 확인하세요. 코드에는 이 컴포넌트와 하위 구성 요소가 보내는 이벤트의 구독 방법이 모두 포함되어 있습니다.

코드 보기
HTML
<sy-tab-group
  active="0"
  type="line"
  position="top"
  size="medium"
  align="left"
  padding="none"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">개요</sy-tab>
  <sy-tab tabkey="tab-1">활동</sy-tab>
  <sy-tab tabkey="tab-2">설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>
<output id="demo-events" aria-live="polite">컴포넌트를 조작하면 최근 이벤트와 전달 값이 표시됩니다.
</output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  for (const name of ["selected", "closed", "ordered", "tabSelected", "tabClosed", "tabAdded"]) {
    document.addEventListener(name, event => {
      document.querySelector('#demo-events').textContent =
        `${event.target.localName} · ${name}: ${describeResult(event.detail)}`;
    });
  }
</script>

탭 추가 요청 받기

추가 버튼은 tabAdded 이벤트로 앱에 새 탭 생성을 요청합니다. 이 예제는 요청 내용을 결과에 표시합니다. 실제 앱에서는 새 sy-tab과 sy-tab-content를 함께 추가하세요.

코드 보기
HTML
<sy-tab-group
  active="0"
  type="line"
  position="top"
  size="medium"
  align="left"
  padding="none"
  add-new-tab
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">개요</sy-tab>
  <sy-tab tabkey="tab-1">활동</sy-tab>
  <sy-tab tabkey="tab-2">설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>
<output id="demo-events" aria-live="polite">컴포넌트를 조작하면 최근 이벤트와 전달 값이 표시됩니다.
</output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? '완료';
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "addNewTab": true
  });
  for (const name of ["tabAdded"]) {
    document.addEventListener(name, event => {
      document.querySelector('#demo-events').textContent =
        `${event.target.localName} · ${name}: ${describeResult(event.detail)}`;
    });
  }
</script>

탭·본문·보조 동작 슬롯

tabs에는 탭, contents에는 연결된 본문을 배치합니다. extra에는 탭 목록 옆에 표시할 보조 내용을 넣습니다.

코드 보기
HTML
<sy-tab-group active="0" style="height:220px">
  <sy-tab tabkey="overview" slot="tabs">개요</sy-tab>
  <sy-tab tabkey="activity" slot="tabs">활동</sy-tab>
  <sy-tab-content name="overview" slot="contents">프로젝트 개요</sy-tab-content>
  <sy-tab-content name="activity" slot="contents">최근 활동</sy-tab-content><span
    slot="extra"
  >팀 프로젝트</span>
</sy-tab-group>

하단 탭 탐색

콘텐츠 패널 아래에 탭을 가운데 정렬하여 배치합니다.

코드 보기
HTML
<sy-tab-group
  active="0"
  type="line"
  position="bottom"
  size="medium"
  align="center"
  padding="none"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">개요</sy-tab>
  <sy-tab tabkey="tab-1">활동</sy-tab>
  <sy-tab tabkey="tab-2">설정</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">프로젝트 현황을 한눈에 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">최근 변경 사항과 팀의 활동을 확인합니다.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">프로젝트의 기본 설정을 관리합니다.</p>
  </sy-tab-content>
</sy-tab-group>

<script type="module">
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "position": "bottom",
    "align": "center"
  });
</script>

API reference

#

이름에 마우스를 올리거나 키보드로 선택하면 적용 코드를 확인할 수 있습니다. 터치 화면에서는 이름을 누르세요.

<sy-tab-group>

Properties

Attribute / PropertyTypeDefaultDescription
numberundefined현재 탭의 인덱스입니다. 0부터 시작합니다.
'center' | 'left''left'탭 줄의 왼쪽 또는 가운데 정렬입니다.
booleanfalse사용자 조작과 키보드 포커스를 차단합니다.
booleanfalse탭을 드래그하여 순서를 변경할 수 있게 합니다.
"top" | "bottom" | "left" | "right""top"항목 배치 방향입니다.
"card" | "line""line"line 또는 card 스타일입니다.
"small" | "medium" | "large""medium"컴포넌트의 크기입니다.
"small" | "medium" | "large" | 'none'"none"탭 영역의 안쪽 여백입니다.
booleanfalse추가 버튼과 tabAdded 이벤트를 제공합니다. 새 탭의 생성은 앱에서 처리합니다.

Events

EventDetailDescription
CustomEvent<any>사용자가 항목을 선택했을 때 발생합니다.
CustomEvent<any>이벤트의 detail에서 결과를 확인하세요.
CustomEvent<HTMLSyTabElement[]>이벤트의 detail에서 결과를 확인하세요.
CustomEvent<{ index: number; value: string }>이벤트의 detail에서 결과를 확인하세요.
CustomEvent<{ index: number; value: string }>이벤트의 detail에서 결과를 확인하세요.
CustomEvent<void>이벤트의 detail에서 결과를 확인하세요.

Methods

MethodReturnsDescription
Promise<void>인덱스 또는 tabkey로 탭과 연결된 콘텐츠를 제거합니다.
Promise<void>0부터 시작하는 인덱스로 탭을 선택합니다.
Promise<number | undefined>현재 탭의 인덱스를 반환합니다. 선택된 탭이 없으면 undefined입니다.

Slots

SlotDescription
tabs 영역에 표시할 내용입니다.
extra 영역에 표시할 내용입니다.
컴포넌트의 본문 또는 자식 항목입니다.
contents 영역에 표시할 내용입니다.

<sy-tab>

Properties

Attribute / PropertyTypeDefaultDescription
booleanfalse닫기 버튼을 표시합니다.
booleanfalse사용자 조작과 키보드 포커스를 차단합니다.
stringundefined콘텐츠 name과 연결할 고유한 탭 키입니다.
booleanfalse닫기 요청 이벤트만 전달합니다. 확인 후 부모의 closeTab을 호출하세요.
booleanfalse현재 선택된 탭입니다. 부모가 관리합니다.
booleanfalse부모가 전달한 비활성화 상태입니다.
booleanfalse부모와 개별 설정을 합친 최종 비활성화 상태입니다.
numberundefined부모가 계산한 항목 인덱스입니다.
"card" | "line""line"line 또는 card 스타일입니다. 부모가 전달합니다.
"small" | "medium" | "large""medium"컴포넌트의 크기입니다.
"top" | "bottom" | "left" | "right""top"항목 배치 방향입니다.
booleanfalseGlobal Header 안의 탭 스타일입니다. 헤더가 설정합니다.

Events

EventDetailDescription
CustomEvent<any>사용자가 항목을 선택했을 때 발생합니다.
CustomEvent<any>이벤트의 detail에서 결과를 확인하세요.

Methods

MethodReturnsDescription
Promise<void>항목을 닫습니다.

Slots

SlotDescription
컴포넌트의 본문 또는 자식 항목입니다.

<sy-tab-content>

Properties

Attribute / PropertyTypeDefaultDescription
booleanfalse현재 탭과 연결되어 콘텐츠를 표시하는 상태입니다. 부모가 관리합니다.
booleanfalse사용자 조작과 키보드 포커스를 차단합니다.
stringundefined표시할 sy-tab의 tabkey와 같은 값을 지정합니다.

Slots

SlotDescription
컴포넌트의 본문 또는 자식 항목입니다.