はじめに
Phoenix LiveView は Elixir の Web フレームワークです
JavaScript をほぼ書くことなく、 Elixir でフロントエンドもバックエンドも実装できます
MishkaChelekom は UI コンポーネントのジェネレーターです
UI コンポーネントを直接定義しているわけではなく、必要な UI コンポーネントを生成して Phoenix プロジェクト内に追加します
実装したアプリケーションはこちら
実行環境(前提条件)
Erlang と Elixir 、 Node.js をインストールしているものとします
各言語のバージョン
- Erlang 27.2
- Elixir 1.17.3
- Node.js 22.12.0
macOS であれば mise や asdf を使ってインストールするのがおすすめです
mise の場合
mise use -g erlang@27.2
mise use -g elixir@1.17.3
mise use -g node@22.12.0
asdf の場合
asdf plugin add erlang
asdf install erlang 27.2
asdf global erlang 27.2
asdf plugin add elixir
asdf install elixir 1.17.3
asdf global elixir 1.17.3
asdf plugin add nodejs
asdf install nodejs 22.12.0
asdf global nodejs 22.12.0
elixir のパッケージマネージャー Hex をインストールします
mix local.hex
Phoenix プロジェクトを生成するための phx_new をインストールします
mix archive.install hex phx_new
Phoenix プロジェクトの作成
Phoenix プロジェクトを作成します
今回は UI だけ見たいので DB 操作をしないため --no-ecto
のオプションを付けています
mix phx.new phoenix_mishka_chelekom_sample --no-ecto
Fetch and install dependencies? [Yn]
と質問されるので、そのまま Enter を押下(デフォルトの yes で回答)します
phoenix_mishka_chelekom_sample ディレクトリーが作成されるので、中に移動します
cd phoenix_mishka_chelekom_sample
Phoenix アプリケーションを起動します
mix phx.server
http://localhost:4000 にアクセスすると、以下のような画面が表示されます
一旦、 Ctrl + C でアプリケーションを停止します
MishkaChelekom の導入
mix.exs
を以下のように編集します
defmodule PhoenixBloomSample.MixProject do
...
defp deps do
[
...
- {:bandit, "~> 1.5"}
- {:bandit, "~> 1.5"},
+ {:mishka_chelekom, "~> 0.0.1", only: :dev}
]
end
...
end
MishkaChelekom 自体はコードを生成するだけで実行環境には不要なため、 only: :dev
を指定しています
これにより、リリースされるバイナリは必要最小限のものになります
MishkaChelekom をインストールします
mix deps.get
コンポーネントの導入
MishkaChelekom では以下のようなコマンドでコードを生成します
mix mishka.ui.gen.component <コンポーネント名>
公式ドキュメントからコンポーネントの種類、表示、動作、プロパティ、使用例などが確認できます
まだバージョン 0.0.1 であることもあるのか、コンポーネントのプロパティについてはドキュメントと実装が一致していません
1.0.0 リリースまでにはきっと整備されると思います
Rating コンポーネントを追加してみましょう
mix mishka.ui.gen.component rating
コマンドにより、 lib/phoenix_mishka_chelekom_sample_web/components/rating.ex
が生成されます
コンポーネントを関数名だけで呼び出したいので、 lib/phoenix_mishka_chelekom_sample_web.ex
を以下のように編集します
defmodule PhoenixMishkaChelekomSampleWeb do
...
defp html_helpers do
quote do
# Translation
use Gettext, backend: PhoenixMishkaChelekomSampleWeb.Gettext
# HTML escaping functionality
import Phoenix.HTML
# Core UI components
import PhoenixMishkaChelekomSampleWeb.CoreComponents
+ import PhoenixMishkaChelekomSampleWeb.Components.Rating
# Shortcut for generating JS commands
alias Phoenix.LiveView.JS
# Routes generation with the ~p sigil
unquote(verified_routes())
end
end
...
end
lib/phoenix_mishka_chelekom_sample_web/controllers/page_html/home.html.heex
に Rating を追加します
...
<h1 class="text-brand mt-10 flex items-center text-sm font-semibold leading-6">
Phoenix Framework
<small class="bg-brand/5 text-[0.8125rem] ml-3 rounded-full px-2 font-medium leading-6">
v{Application.spec(:phoenix, :vsn)}
</small>
</h1>
<.rating />
<.rating select={3} />
<.rating select={5} />
<.rating interactive />
<p class="text-[2rem] mt-4 font-semibold leading-10 tracking-tighter text-zinc-900 text-balance">
Peace of mind from prototype to production.
</p>
...
アプリケーションを起動します
mix phx.server
ブラウザで表示すると、以下のように Rating が表示されます
interactive
を指定した場合はマウスオーバーで評価が変わっています
続けて Alert を追加してみます
極力コードを少なくするため、利用する予定のある色とスタイルのみを指定します
mix mishka.ui.gen.component alert --color info,error --variant default
lib/phoenix_mishka_chelekom_sample_web/components/alert.ex
が生成されました
内容を確認すると、例えば色の指定は以下のように :error
、 :danger
、 :info
だけが指定されています
( :error
と :danger
は同じ色を使っているので、片方しか指定しなくても両方ついてくるようです)
defp color_variant("default", type) when type in [:error, :danger] do
"bg-[#FFE6E6] text-[#E73B3B] border border-[#E73B3B] hover:[&>button]:text-[#F0756A]"
end
defp color_variant("default", :info) do
"bg-[#E5F0FF] text-[#004FC4] border border-[#004FC4] hover:[&>button]:text-[#3680DB]"
end
これにより、最終的に TailwindCSS が生成する CSS ファイルも小さくなり、その分フロントエンドが軽くなります
lib/phoenix_mishka_chelekom_sample_web/controllers/page_html/home.html.heex
に Alert を追加します
defmodule PhoenixMishkaChelekomSampleWeb do
...
defp html_helpers do
quote do
# Translation
use Gettext, backend: PhoenixMishkaChelekomSampleWeb.Gettext
# HTML escaping functionality
import Phoenix.HTML
# Core UI components
- import PhoenixMishkaChelekomSampleWeb.CoreComponents
+ import PhoenixMishkaChelekomSampleWeb.CoreComponents, except: [flash_group: 1]
+ import PhoenixMishkaChelekomSampleWeb.Components.Alert
import PhoenixMishkaChelekomSampleWeb.Components.Rating
# Shortcut for generating JS commands
alias Phoenix.LiveView.JS
# Routes generation with the ~p sigil
unquote(verified_routes())
end
end
...
end
Alert 内で flash_group
を定義しているため、 CoreComponents からはインポートしないように指定しています
lib/phoenix_mishka_chelekom_sample_web/controllers/page_html/home.html.heex
に Alert を追加します
...
<h1 class="text-brand mt-10 flex items-center text-sm font-semibold leading-6">
Phoenix Framework
<small class="bg-brand/5 text-[0.8125rem] ml-3 rounded-full px-2 font-medium leading-6">
v{Application.spec(:phoenix, :vsn)}
</small>
</h1>
<.alert kind={:info}>Info</.alert>
<.alert kind={:error}>Error</.alert>
<.rating />
...
アプリケーションを起動すると、 Alert の表示が確認できます
まとめてコンポーネントを作成する
以下のように実行すると、 Alert と Rating をまとめて読み込むためのモジュール MishkaComponents が生成されます
mix mishka.ui.gen.components alert,rating --import
mishka.ui.gen.components
<- 最後に s
がついています
生成されたファイル lib/phoenix_mishka_chelekom_sample_web/components/mishka_components.ex
の中身は以下のようになっています
defmodule PhoenixMishkaChelekomSampleWeb.Components.MishkaComponents do
defmacro __using__(_) do
quote do
import PhoenixMishkaChelekomSampleWeb.Components.Alert,
only: [flash: 1, flash_group: 1, alert: 1]
import PhoenixMishkaChelekomSampleWeb.Components.Rating, only: [rating: 1]
end
end
end
MishkaComponents を使う場合、 lib/phoenix_mishka_chelekom_sample_web/controllers/page_html/home.html.heex
は以下のように編集します
defmodule PhoenixMishkaChelekomSampleWeb do
...
defp html_helpers do
quote do
# Translation
use Gettext, backend: PhoenixMishkaChelekomSampleWeb.Gettext
# HTML escaping functionality
import Phoenix.HTML
# Core UI components
- import PhoenixMishkaChelekomSampleWeb.CoreComponents
+ import PhoenixMishkaChelekomSampleWeb.CoreComponents, except: [flash_group: 1]
+ use PhoenixMishkaChelekomSampleWeb.Components.MishkaComponents
# Shortcut for generating JS commands
alias Phoenix.LiveView.JS
# Routes generation with the ~p sigil
unquote(verified_routes())
end
end
...
end
use PhoenixMishkaChelekomSampleWeb.Components.MishkaComponents
により、 MishkaComponents の中に記述されている各種コンポーネントの import を実施しています
ただし、 mix mishka.ui.gen.components
を実行した場合、 Alert や Rating など個別のコンポーネントにオプションを指定できないため、コンポーネントの色やスタイルは全て生成されます
また、以下のコマンドを実行することで MishkaComponents で生成できる全てのコンポーネントを一括生成します
mix mishka.ui.gen.components --import --yes
まとめ
MishkaComponents はコンポーネントのジェネレーターという、他の UI ライブラリーとは毛色が違うものでした
コンポーネント自体の種類もオプションも豊富なので、 1.0.0 が出るのが楽しみですね