はじめに
Phoenix LiveView は Elixir の Web フレームワークです
JavaScript をほぼ書くことなく、 Elixir でフロントエンドもバックエンドも実装できます
Bloom は Tailwind CSS を使った UI コンポーネントのライブラリです
shadcn にインスパイアされたという点では SaladUI と同じですね
Bloom は面白いコンポーネントを簡単に導入できるので、「これは使えそう!」と思ったコンポーネントがあれば、ぜひ使ってみましょう
実装したアプリケーションはこちら
実行環境(前提条件)
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_bloom_sample --no-ecto
Fetch and install dependencies? [Yn]
と質問されるので、そのまま Enter を押下(デフォルトの yes で回答)します
phoenix_bloom_sample ディレクトリーが作成されるので、中に移動します
cd phoenix_bloom_sample
Phoenix アプリケーションを起動します
mix phx.server
http://localhost:4000 にアクセスすると、以下のような画面が表示されます
一旦、 Ctrl + C でアプリケーションを停止します
Bloom の導入
mix.exs
を以下のように編集します
defmodule PhoenixBloomSample.MixProject do
...
defp deps do
[
{:phoenix, "~> 1.7.18"},
{:phoenix_html, "~> 4.1"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
- {:phoenix_live_view, "~> 1.0.0"},
+ {:phoenix_live_view, "~> 1.0.0", override: true},
...
- {:bandit, "~> 1.5"}
- {:bandit, "~> 1.5"},
+ {:bloom, "~> 0.0.8"}
]
end
...
end
まだ Bloom の依存関係が更新されていないため、 phoenix_live_view のバージョン指定に , override: true
を加えています
Bloom をインストールします
mix deps.get
assets/tailwind.config.js
に safelist の指定を加えます
safelist を指定しない場合、変数の組み合わせで作られるクラスは TailwindCSS のスタイルが生成されないため、色が表示されません
...
module.exports = {
...
safelist: [
{
pattern: /bg-+/,
variants: ["focus", "hover", "group-hover", "active"],
},
{
pattern: /text-+/,
variants: ["focus", "hover", "group-hover", "active"],
},
{
pattern: /from-+/,
variants: ["focus", "hover", "group-hover", "active"],
},
{
pattern: /to-+/,
variants: ["focus", "hover", "group-hover", "active"],
},
{
pattern: /inset-+/,
variants: ["focus", "hover", "group-hover", "active"],
},
{
pattern: /opacity-+/,
variants: ["focus", "hover", "group-hover", "active"],
},
{
pattern: /transition-+/,
variants: ["focus", "hover", "group-hover", "active"],
},
],
...
}
コンポーネントの導入
以下のコマンドでインストール可能なコンポーネントが確認できます
mix bloom.install help
実行結果
Usage: mix bloom.install [component_name]
Available components: avatar | glow_button | code_snippet | hero | gradient_text | bento_grid | card | marquee
具体的なコンポーネントのデザインや挙動はストーリーブックで確認できます
今回は Avatar など、4種類をインストールしてみます
以下のコマンドを実行してください
mix bloom.install avatar
すると、 lib/phoenix_bloom_sample_web/components/avatar.ex
が作成されます
コマンドの実行結果として以下のメッセージが表示されます
Don't forget to import the component to your phoenix_bloom_sample_web.ex` file.
その通りに、 lib/phoenix_bloom_sample_web.ex
を編集します
defmodule PhoenixBloomSampleWeb do
...
defp html_helpers do
quote do
# Translation
use Gettext, backend: PhoenixBloomSampleWeb.Gettext
# HTML escaping functionality
import Phoenix.HTML
# Core UI components
import PhoenixBloomSampleWeb.CoreComponents
+ import PhoenixBloomSampleWeb.Components.Avatar
# Shortcut for generating JS commands
alias Phoenix.LiveView.JS
# Routes generation with the ~p sigil
unquote(verified_routes())
end
end
...
end
同様の手順で code_snippet 、 glow_button 、gradient_text もインストールしましょう
最終的に、以下のファイルが追加されます
lib/phoenix_bloom_sample_web/components/avatar.ex
lib/phoenix_bloom_sample_web/components/code_snippet.ex
lib/phoenix_bloom_sample_web/components/glow_button.ex
lib/phoenix_bloom_sample_web/components/gradient_text.ex
また、 lib/phoenix_bloom_sample_web.ex
は以下のように編集します
defmodule PhoenixBloomSampleWeb do
...
defp html_helpers do
quote do
# Translation
use Gettext, backend: PhoenixBloomSampleWeb.Gettext
# HTML escaping functionality
import Phoenix.HTML
# Core UI components
import PhoenixBloomSampleWeb.CoreComponents
+ import PhoenixBloomSampleWeb.Components.Avatar
+ import PhoenixBloomSampleWeb.Components.CodeSnippet
+ import PhoenixBloomSampleWeb.Components.GradientText
+ import PhoenixBloomSampleWeb.Components.GlowButton
# Shortcut for generating JS commands
alias Phoenix.LiveView.JS
# Routes generation with the ~p sigil
unquote(verified_routes())
end
end
...
end
lib/phoenix_bloom_sample_web/controllers/page_html/home.html.heex
に各種コンポーネントを追加します
<.flash_group flash={@flash} />
<div class="left-[40rem] fixed inset-y-0 right-0 z-0 hidden lg:block xl:left-[50rem]">
...
<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>
<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>
<div class="flex items-center gap-4 mt-4">
<.avatar name="Jessica&rotate=30" style="adventurer" />
<.avatar
name="Me"
img_src="https://api.dicebear.com/9.x/adventurer/svg?seed=Oliver&rotate=20&eyebrows=variant02&eyes=variant01&hairColor=85c2c6&mouth=variant24"
/>
</div>
<.code_snippet
class="mt-4"
delimiter=">"
text_color="emerald-800"
background_color="green-200"
>
mix bloom.install code_snippet
</.code_snippet>
<.gradient_text
class="text-[2rem] mt-4 font-semibold leading-10 tracking-tighter text-balance"
from_color="pink-500"
to_color="cyan-500"
>
Peace of mind from prototype to production.
</.gradient_text>
<.glow_button class="mt-4" from_color="emerald-600" to_color="indigo-600">
Hello, Bloom!
</.glow_button>
<p class="mt-4 text-base leading-7 text-zinc-600">
Build rich, interactive web applications quickly, with less code and fewer moving parts. Join our growing community of developers using Phoenix to craft APIs, HTML5 apps and more, for fun or at scale.
</p>
...
</div>
アプリケーションを起動してみます
mix phx.server
確かにコンポーネントが表示されました
まとめ
コンポーネント単位で必要なものだけインストールできるのは良いですね
ちなみに、アバターは DiceBear というアバター作成サービスを利用していて、顔のパーツや角度などを調節して、自分のアバターを作成できます
他にも面白いコンポーネントが充実していくと良いですね