Tabs

Tabsは、関連するコンテンツをグループ化し、タブを切り替えることで表示内容を変更できるコンポーネントです。

プロパティ

Tabsは、以下のプロパティをサポートしています。

名前 デフォルト値 説明
tabs TabsItem[] タブ項目の配列を渡します。
currentTabId number | string 現在選択されているタブのIDを指します。

TabsItem

TabsItemは、タブ内の情報を表すオブジェクトです。

名前 デフォルト値 説明
id number | string タブ項目のidです。
label string タブの項目名です。
disabled boolean false タブを無効化します。操作できません。

インストールの手順

以下のコンポーネントのコードを、使いたいプロジェクトにコピー&ペーストします。
パスは実際のプロジェクトの構成にあわせて更新してください。

atoms/Tabs.svelte
        <!--
@component
## 概要
- タブ形式のナビゲーションUIを提供するコンポーネントです

## 機能
- tabsに指定した配列からタブを動的に生成します

## Props
- tabs: タブ項目の配列
- currentTabId: 現在選択されているタブのID

## Usage
```svelte
<Tabs {tabs} />
```
-->

<script module lang="ts">
  import type { ClassValue } from 'svelte/elements';
  import { cva, type VariantProps } from 'class-variance-authority';

  export const tabsVariants = cva('relative px-3 py-1.5 leading-normal text-sm font-medium outline-primary transition-colors cursor-pointer hover:bg-base-container-accent/90 focus-visible:outline-[0.125rem] focus-visible:outline-offset-[0.125rem]', {
    variants: {
      /** 現在のタブかどうか */
      current: {
        true: ['text-base-foreground-default'],
        false: ['text-base-foreground-muted'],
      },
      /** 操作できるかどうか */
      disabled: {
        true: ['opacity-50 pointer-events-none'],
        false: [],
      },
    },
  });

  export type TabsVariants = VariantProps<typeof tabsVariants>;

  export interface TabsProps extends TabsVariants {
    /** クラス */
    class?: ClassValue;
    /** タブ項目の配列 */
    tabs: TabsItem[];
    /** タブが選択されたときのハンドラ */
    onChange?: (tab: TabsItem) => void;
    /** 現在選択されているタブのID */
    currentTabId?: number | string;
  }

  export interface TabsItem {
    /** タブ項目のID */
    id: number | string;
    /** タブの項目名 */
    label: string;
    /** 操作できるかどうか */
    disabled?: boolean;
  }
</script>

<script lang="ts">
  import { quintOut } from 'svelte/easing';
  import { crossfade } from 'svelte/transition';

  let { class: className, tabs, onChange, currentTabId = tabs[0].id }: TabsProps = $props();

  const [send, receive] = crossfade({
    duration: 300,
    easing: quintOut,
  });

  function onChangeTab(tab: TabsItem) {
    if (tab.disabled) return;
    currentTabId = tab.id;
    onChange?.(tab);
  }
</script>

<div class={[className, 'flex items-center']}>
  {#each tabs as tab}
    <button class={tabsVariants({ current: currentTabId === tab.id, disabled: tab.disabled })} disabled={tab.disabled} onclick={() => onChangeTab(tab)}>
      {tab.label}
      {#if currentTabId === tab.id}
        <span class="absolute bottom-0 left-0 w-full h-0.5 bg-primary" in:receive={{ key: 'floating' }} out:send={{ key: 'floating' }}></span>
      {/if}
    </button>
  {/each}
</div>

      

使い方


サンプル

Default

特に操作が行われていない、デフォルトの状態です。

Current

currentTabIdを指定することで、任意のタブを選択状態にすることも可能です。

Disabled

利用不可の状態です。