本文へ

開発記録

bejamas/ui の導入:まずは Button 一つから、サイト全体を任せない

ネイティブ Astro の Button 一つから始め、必要な UI コンポーネントだけを追加するときに CLI、スタイル、依存関係、HTML の意味をどう確認し、既存のデザインと変更範囲を守ったかを記録します。

林予晴
公開
  • Astro
  • bejamas/ui
  • Tailwind CSS
  • コンポーネント設計

この記録は、2026年10月1日の初期導入段階を扱っています。以下の色と Font Awesome は当時の構成であり、現在のサイトの配色やアイコンシステムを示すものではありません。

このポートフォリオサイトは、ネイティブ Astro に移行したばかりでした。ページにはすでにグレーブルーと鮮やかなブルーの配色や、独自のボタンスタイルがありました。今後のページで同じ UI コードを繰り返し書かずに済むよう、共通コンポーネントを追加したいと考えていましたが、導入と同時にサイト全体のデザインを変えるつもりはありませんでした。

今回は導入範囲を Button 一つに絞りました。コンポーネントがプロジェクトにどう追加されるのか、既存の色を使えるのか、出力される HTML が用途に合っているのかを確認してから、次の追加を判断することにしました。

まず知りたかったのは、一つのコンポーネントがどこまで変更を広げるかです。サイト全体の背景や文字色、既存の操作要素まで一緒に変わると、どの手順が原因だったのかを切り分けにくくなります。

コンポーネントの追加方法を先に確認する

選んだ bejamas/ui は、Astro と Tailwind CSS v4 向けのコンポーネントシステムです。公式では、CLI を使って必要なコンポーネントだけを追加する手順が用意されています。[4]

Button のソースコードは自分たちのプロジェクトに配置され、後から直接編集できます。この方式は copy-and-own と呼ばれます。その分、コードを理解し、保守する責任も自分たちにあります。ソースコードが手元にあるからといって、更新時の確認が不要になるわけではありません。

最初に、コンポーネントの保存先、必要な補助関数やパッケージ、サイト全体の CSS への影響を確認しました。デモサイトにある Dialog や Tabs などは、ページで実際に必要になってから追加します。

ネイティブのボタン一つを確認しても、すべてのインタラクティブなコンポーネントを検証したことにはなりません。後から dialog や drawer が必要になった場合は、キーボード操作、フォーカス、追加されるブラウザスクリプトを別途確認する必要があります。

サイト全体の設定を変える前に dry-run を行う

当時の CLI(コマンドラインツール)の説明を確認し、bejamas 0.4.1 にバージョンを固定したうえで、package.json に追加用の入口を設けました。以下はこのコマンドに関係する設定だけの抜粋であり、インストール用ファイル全体ではありません。

{
  "scripts": {
    "ui:add": "bejamas add"
  }
}

この設定とインストール済みの CLI があって初めて、このプロジェクトで次のプレビューコマンドを実行できます。

npm run ui:add -- button --dry-run

--dry-run は、書き込み予定の内容を確認するためのオプションです。[5] ui:add は自分たちで定義した script 名であり、npm や Astro の組み込みコマンドではありません。別のプロジェクトでは、まずそのプロジェクト用の設定が必要です。インストール方法は末尾の公式ドキュメントを参照できます。

実際に追加した後も、変更内容を一つずつ確認します。今回は Button 以外に、class を結合する補助関数、スタイルの import、依存関係も追加されました。一つのコンポーネントだけを指定しても、複数のファイルが変わることがあります。

CLI のバージョンを固定していても、確認を省略してよいわけではありません。追加するたびに実際の生成内容を見ること、init や apply を一括で無条件に実行しないこと、すでにカスタマイズしたコンポーネントを上書きしないことをルールにしました。

色は元の定義に残す

今回の Button 導入では、当時のグレーブルーと鮮やかなブルーの配色を維持しました。後から配色を変えるなら、コンポーネント導入とは分けて取り組めます。

コンポーネントは、背景、文字、境界線、フォーカス表示を表す background、foreground、border、ring などの名前を使います。これらの意味に基づく色を、既存のパレットにつなぎました。以下は当時の実際のスタイルからの短い抜粋です。

@theme {
  --color-siteBg: #e0e6ec;
  --color-black: #1c1e19;
  --color-primary: #273cf7;
}

@theme inline {
  --color-background: var(--color-siteBg);
  --color-foreground: var(--color-black);
  --color-ring: var(--color-primary);
}

@theme に元のサイトの色を残し、@theme inline でコンポーネントが必要とする名前をその色に対応させています。この共通設定がデザイントークンです。一か所で管理すれば、各ページで別々にカラーコードを書く必要がなくなります。

この段階では、既存の Font Awesome によるアイコンシステムも維持しました。コンポーネントのサンプルが別のアイコンを使っているからといって、サイト全体を置き換えることはしませんでした。

スタイルの確認では、CLI が追加したグローバルな base ルールも調べました。この種の CSS はボタン以外の要素にも影響するため、すべてを残したわけではありません。特に Tab キーで移動するとき、元のサイトの focus-visible によるフォーカス表示が引き続き見える必要があります。

ここでの判断は実務的です。まずコンポーネントをサイトに合わせ、本当にリニューアルするときにデザイントークンをまとめて調整します。

ボタンに見えても、用途に合う要素を出力する

見た目が同じでも、用途は区別する必要があります。別のページへの移動はリンクなので、実際の href を持つ <a> を出力します。操作を実行するときは <button> を使います。以下はスタイルと操作用スクリプトを省いた最小の例です。元の繁体字中国語のラベルとルート例をそのまま残しています。ラベルは順に「このサイトについて」「メニューを開く」「フォームを送信する」という意味です。

<a href="/about">關於這個網站</a>
<button type="button">開啟選單</button>
<button type="submit">送出表單</button>

今回追加した Button は as="a" に対応しており、最初の用途でも実際のリンクを出力できます。読者はブラウザの通常の操作で新しいタブを開けます。すべてのナビゲーションを JavaScript のクリックイベントに変える必要はありません。

操作用ボタンの既定値も type="button" にし、フォームを送信するときだけ type="submit" を明示して渡すようにしました。これはこのプロジェクトで行ったローカルな変更であり、コンポーネントライブラリのすべてのバージョンに共通する既定値として説明するものではありません。

こうした違いは、見た目だけでは分からないことがあります。「ボタンの色が表示された」だけで検証を終えることはできません。実際の HTML を読み、tag、属性、class の結合結果も確認する必要があります。

まだ使われていないコンポーネントは別途テストする

基礎的な導入の時点では、既存のページの操作要素を Button に置き換えていませんでした。そのため、サイトのビルドが成功しても、新しいコンポーネントが実際にレンダリングされた証拠にはなりません。

そこで、同じ Button と CSS を読み込むテスト専用ページを作り、サイズ、スタイル、リンクとしての用途を実際にレンダリングしました。その後、生成された HTML を確認しました。リンクに href があるか、操作用ボタンの type は正しいか、無効状態や class の結合が想定どおりか、追加のブラウザスクリプトがあるかを調べました。

この記録が示すのは、そのテスト範囲で Button が使えたということです。すべてのインタラクティブなコンポーネント、モバイルのレイアウト、新しいサイト全体の確認が済んだという意味ではありません。

導入中には、Windows のネイティブモジュールのファイルがロックされる問題もありました。当時は npm ci が成功せず、後から npm install で依存関係を復旧して、確認を完了しました。これはそのときの対処の記録です。npm install をあらゆるインストールエラーの解決策と考えることも、lockfile からの再インストールを検証済みだと主張することもできません。

「すべて成功した」とだけ残すと、次に別の環境で作業する人は、何が未確認なのか分かりません。

次のコンポーネントも必要性から考える

最初に Button だけを導入したことで、コンポーネントの出所、token の接続、CLI の書き込み範囲、ローカルな変更を確認できました。

後から Card や Badge を追加するときも、同じ確認方法を使えます。より複雑な操作要素を追加するときは、対応する動作検証を増やします。コンポーネントライブラリを使うために、すべての HTML 要素をコンポーネント化する必要はありません。

共通コンポーネントで減らしたいのは重複した実装であって、出力や動作への理解ではありません。サイトの情報設計、内容、見た目の判断は、引き続き実際の要件に基づいて決める必要があります。

記録の範囲

この記事は、基本的な Button だけを追加した段階を記録しています。当時、既存のページはまだ全面的に新しいコンポーネントへ移行していませんでした。コマンド設定と CSS の抜粋は、その実装から取ったものです。HTML のブロックは用途を説明するための最小の例です。ほかのインタラクティブなコンポーネントや、その後のサイト全体のリニューアルは、今回の検証範囲に含みません。

出典

[4] https://ui.bejamas.com/docs/installation [5] https://ui.bejamas.com/docs/cli