SPB Git

spb/autoscholar

Public
1.4 KB · 51 lines tsx
1"use client";2import { type ReactNode, useId, useState } from "react";34export function Tabs({5  tabs,6  initial = 0,7}: {8  tabs: Array<{ label: string; content: ReactNode }>;9  initial?: number;10}) {11  const [i, setI] = useState(initial);12  const id = useId();13  return (14    <div>15      <div role="tablist" className="flex gap-1 border-b hairline">16        {tabs.map((tab, k) => (17          <button18            key={tab.label}19            type="button"20            role="tab"21            id={`${id}-tab-${k}`}22            aria-selected={i === k}23            aria-controls={`${id}-panel-${k}`}24            tabIndex={i === k ? 0 : -1}25            onClick={() => setI(k)}26            onKeyDown={(e) => {27              if (e.key === "ArrowRight") setI((i + 1) % tabs.length);28              if (e.key === "ArrowLeft") setI((i - 1 + tabs.length) % tabs.length);29            }}30            className={`-mb-px border-b-2 px-3 py-2 text-sm ${i === k ? "border-[var(--accent)] font-medium" : "border-transparent muted"}`}31          >32            {tab.label}33          </button>34        ))}35      </div>36      {tabs.map((tab, k) => (37        <div38          key={tab.label}39          role="tabpanel"40          id={`${id}-panel-${k}`}41          aria-labelledby={`${id}-tab-${k}`}42          hidden={i !== k}43          className="pt-4"44        >45          {tab.content}46        </div>47      ))}48    </div>49  );50}51
Files · 87b4e55c3b9fbcc2cd191a1e469b33de0a24ccc8
Menu

Theme