tailwindcss を使って Tabボタン(react x typescript)

#  はじめに
みなさん、こんにちは **torihazi**です！
最近 実務でTailwindcss を使うことになり、その勉強も兼ねて
現在いろいろ触ってます！

使い方としてはbootstrapに近いもの、という感じです

今回やる見た目ももしかしたら元々別で用意されているものかもしれませんが

ぱっと見なかったので作ってみました。

React x Typescript x tailwindcss です

# どういうものか
こんな感じのやつです。
ChakraUIとかには多分似たようなもの見たことある気がするんですが。

![2024-08-119.17.19-ezgif.com-video-to-gif-converter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2567812/e8fd246a-75b1-e0b8-dbac-b8f790192ac2.gif)

# コード
根本は input type="radio"です。
それを 見えなくする(hiddenを設定)することで実現するよくあるパターンです。
そこから今回は何を選択しているかというのをReact側でState管理して
「切り替わる」見た目を表現しました。

本当はmapを使った方がDRYにかけると思うのですが、
今回は3つで事足りたのでしていません。あとすぐ思いつきませんでした。

jsxだとしたらこの途中で書いてある型定義とか省けば使えるはずです。

ちなみに showForの型定義は
```ts:showForの型
~~~
export const TARGET = {
  ALL: "all",
  STUDENT: "student",
  MENTOR: "mentor",
} as const;

export type TargetValue = (typeof TARGET)[keyof typeof TARGET];
~~~
```

```tsx:RadioBtnGroup.tsx
~~~
type RadioBtnGroupProps = {
  showFor: TargetValue;
  setShowFor: React.Dispatch<React.SetStateAction<TargetValue>>;
};

export const RadioBtnGroup = ({ showFor, setShowFor }: RadioBtnGroupProps) => {
  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    setShowFor(e.target.value as TargetValue);
  };

  return (
    <>
      <div className="flex mb-3">
        <input
          type="radio"
          value="all"
          className="hidden"
          id="all"
          onChange={handleChange}
          checked={showFor === "all"}
        />
        <label
          htmlFor="all"
          className={`${
            showFor === "all"
              ? "bg-blue-400 text-white font-bold"
              : "text-slate-400 hover:bg-blue-100 transition"
          } border border-slate-100 border-r-0 text-blue rounded-l-lg p-2 `}
        >
          all
        </label>
        <input
          type="radio"
          value="student"
          className="hidden"
          id="student"
          onChange={handleChange}
          checked={showFor === "student"}
        />
        <label
          htmlFor="student"
          className={`${
            showFor === "student"
              ? "bg-blue-400 text-white font-bold"
              : "text-slate-400 hover:bg-blue-100 transition"
          } border border-slate-100 border-x-0 text-blue  p-2 `}
        >
          student
        </label>
        <input
          type="radio"
          value="mentor"
          className="hidden"
          id="mentor"
          onChange={handleChange}
          checked={showFor === "mentor"}
        />
        <label
          htmlFor="mentor"
          className={`${
            showFor === "mentor"
              ? "bg-blue-400 text-white font-bold"
              : "text-slate-400 hover:bg-blue-100 transition"
          } border border-slate-100 border-l-0 text-blue rounded-r-lg p-2 `}
        >
          mentor
        </label>
      </div>
    </>
  );
};

```

# こだわり？ポイント
今回で言うと、角の丸とボタン間の線です。

ボタンの角については
- 一番左のボタンは左側上下頂点が丸く、右側上下頂点が角
- 真ん中のボタンは全頂点が角
- 一番右のボタンは右側上下頂点が角、左側上下頂点が丸

ボタン間の線については
- 一番左のボタンは右側の線のみない
- 真ん中のボタンは左右の線ない
- 一番右のボタンは左側の線のみない

幸い、tailwindcssにはborderの位置ごとに参照できるcssのクラスが揃っており
今回はそれを使用しました。

例えば
> 一番左のボタンは左側上下頂点が丸く、右側上下頂点が角

については`rounded-l-lg`という感じです。

それ以外にも調べてみるといろいろあるので調べてみてください。

# 終わりに
最近 Typescriptを学び始めたのですが、ジェネリックとか`React.Dispatch<React.SetStateAction<TargetValue>>;`とか
なんだかまだよくわかっていません。
vscodeが指定してきたからそうしただけで。。。

ただkeyof とか typeofはなんとなくわかるようになりました。

難しいです。ひたすらに。

まぁ頑張ります。