🍇

【初心者向け】TypeScript×Vue3×TailwindCSSでボタンコンポーネントを設計してみる

2024/04/11に公開

今回は、TypeScript×Vue3×TailwindCSSでボタンコンポーネントを設計する際に考えたことについて解説します。

コンポーネントの設計をやったことない方や、他のエンジニアのコンポーネント設計のやり方に興味があるという方の参考になれば嬉しいです。

propsやslotの設計

まず、コンポーネントを設計する上で最も重要なのは、propsやslotに何を渡すかです。
今回は以下のようなシンプルなボタンを作ることにします。(ただし色やサイズはいくつか選択肢があるようにする。)

そのため、propsとして考えられるものとしては以下のようなものが挙げられるでしょう。

  • ボタンの色
  • サイズ
  • テキスト

もしこの辺りがパッと思いつかないようであれば、他のUIライブラリを参考にしてみるのが良いと思います。例えばVueを使っているのであれば、Vuetifyとかが参考になるかと思います。

ただ、vuetifyなどのUIライブラリの多くはpropsが非常に多いので、その中でも「これはマストで使いたい」というものをピックアップしていくと良いでしょう。

それではここからは、上記で挙げたものをもう少し詳しく見ていきます。

ボタンの色

今回は、赤、青、黄の3種類があるとします。
この場合、イメージとしてはbackgroundColor="red"みたいな感じでpropsで渡したいので、TypeScriptを用いる場合にはbackgroundColorのデータ型をきちんと定義しておきたいですね。

コンポーネントファイルのscriptタグの中に以下のように、リテラルのユニオン型で書いていけば良いでしょう。

type Props = {
  backgroundColor: "red" | "blue" | "yellow"
}

これは、backgroundColorというpropsに、"red","blue", "yellow"のどれかしか渡せないという書き方になります。

もしnullも許容したいのであれば、

type Props = {
  backgroundColor?: "red" | "blue" | "yellow"
}

const props = withDefaults(defineProps<Props>(), {
  backgroundColor: 'blue'
})

のような感じで、?を使ってnull許容にした後に、withDefaults()を使ってデフォルト値を定義しておくと良いですね。
そうすれば、propsとしてbackgroundColorが渡されなかったとしてもデフォルト値が利用されます。

ちなみに、色のバリエーションが増えてきてファイルの行数が膨大になってきたら、src/constantsなどにtsファイルを作成して、そちらに定数化して切り出しても良いでしょう。

export const BACKGROUND_COLOR_OPTIONS = [
  'red',
  'blue',
  'yellow',
  ...
  ...
  ...
] as const

サイズ

サイズについては、今回は"small", "medium", "large"の3種類を選択できるようにします。

ここで、もしかしたらsizeではなくwidthとheightをpropsとして渡したくなった方もいるかもしれません。
この辺りは地味に結構難しいところだと思います。

ですが、widthやheightを自由に指定できるようしてしまうと、それはすなわちサイズを自由に設定できてしまうことを意味するので、コンポーネントの意味がなくなってしまいます。

コンポーネントはアプリ内の部品なので、基本的には縦横の長さの組み合わせのレパートリーが無限にあるのではなく、数種類に限定されているべきでしょう。
なので、props側でサイズを選択しさえすれば、横幅と高さが自動的に設定されるような設計にしてあげる方が親切です。

ボタンはその横幅が親要素の100%になるように指定したい時もあるかと思います。
そうなったら、TailwindCSSの場合はw-100とかを指定して親要素いっぱいまで広げてあげれば良いでしょう。

テキスト

テキストについては、propsかslotかちょっと迷いますね。
基本的な判断基準としては、HTMLを渡したい場合にはslotを使えば良いです。

なので、ボタンの例で言えば、もしアイコン等を渡す可能性があるのであればslotを使うことになります。
今回はテキストだけを想定しているので、propsでテキストを渡せば良いでしょう。

テキストは文字列であれば基本的に何でも良いので、string型とします。
また、テキストは必ず必要なのでnull許容にはしません。

ここまでのソースコード全体を書くと、以下のようになります。

type Props = {
  backgroundColor?: "red" | "blue" | "yellow"
    color?: "white"
  text: string
}

const props = withDefaults(defineProps<Props>(), {
  backgroundColor: 'blue'
    color: 'white'
  text: 'click'
})

scriptタグの記述

その他にemitなどscriptタグで書きたいことがあれば、書いていくのですが、今回は特になさそうなので無しでいきます。

templateの記述

scriptタグが書けたら、次はtemplateタグを書いていきます。
今回はボタンにテキストが渡って来るだけなので、HTMLの骨格は以下で良いでしょう。

<template>
  <button>
    {{ props.text }}
  </button>
</template>

TailwindCSSを当てる

あとは、TailwindCSSを使ってスタイルを当てていけばOKです。
通常のCSSのスタイルとTailwindCSSのクラスは基本的に1:1で紐づいています。

書き方は、チートシートを見ながらでOKです。

あとは、propsのsizeの値が"sm"ならこのクラス、"md"ならこのクラス...というように場合分けする書き方をしていけばOKです。
(sizeだけでなくbackgroundColorの時も同様です。)

Xについて

僕のXアカウントでは、主にweb開発、AI、会社経営のノウハウについて発信しています。もし興味があれば、フォローしていただけると嬉しいです。

プログラミング学習サポート&キャリア相談について

プログラミング学習サポート&キャリア相談も始めました。興味のある方はこちらから詳細をご覧ください。
https://shibayama-masaki.com/consulting/

Discussion