PUI
PUI is a Phoenix LiveView UI toolkit with styled components and bundled JavaScript hooks. Hook-managed families also expose zero-style primitive parts for application-owned markup.
Installation
Add pui to mix.exs:
defp deps do
[
{:pui, "~> 1.0"}
]
end
Then fetch dependencies:
mix deps.get
Agent Skills
Install the bundled PUI skills with the Skills CLI:
npx skills add suciptoid/pui
To install one skill, pass its name:
npx skills add suciptoid/pui --skill pui-components
Setup in Your Phoenix App
Import PUI CSS in your app stylesheet:
@import "tailwindcss" source(none);
@source "../css";
@source "../js";
@source "../../lib/your_app_web";
@source "../../deps/pui";
@import "../../deps/pui/assets/css/pui.css";
Register PUI hooks in your LiveSocket:
import { Socket } from "phoenix";
import { LiveSocket } from "phoenix_live_view";
import { Hooks as PUIHooks } from "pui";
const csrfToken = document
.querySelector("meta[name='csrf-token']")
.getAttribute("content");
const liveSocket = new LiveSocket("/live", Socket, {
params: { _csrf_token: csrfToken },
hooks: { ...PUIHooks },
});
liveSocket.connect();
Use PUI in LiveView modules:
defmodule MyAppWeb.DemoLive do
use MyAppWeb, :live_view
use PUI
def render(assigns) do
~H"""
<div class="space-y-4">
<.button>Click me</.button>
<.input type="text" placeholder="Name" />
</div>
"""
end
end
Components Included by use PUI
PUI.AccordionPUI.AvatarPUI.AlertPUI.BadgePUI.BreadcrumbPUI.ButtonPUI.ButtonGroupPUI.CardPUI.ChartPUI.ContainerPUI.DatePickerPUI.DialogPUI.DropdownPUI.EmptyPUI.InputPUI.LayoutPUI.PaginationPUI.PopoverPUI.ProgressPUI.SelectPUI.SeparatorPUI.SkeletonPUI.TablePUI.TabsPUI.Components(shared form and rendering helpers)
Additional modules available directly:
PUI.Flash(flash/toast rendering and helpers)PUI.IconandPUI.IconProvider(provider-agnostic semantic icons)PUI.Loading(loading indicators)PUI.MenuButton
Component Usage
PUI is styled by default:
<.menu_button variant="secondary">
Open
<:item>Profile</:item>
</.menu_button>
For custom markup around a hook-managed interaction, import its explicit
primitive module. There is no variant="unstyled"; each hook-managed family
exposes a .Primitive module instead:
<PUI.Select.Primitive.root id="assignee">
<PUI.Select.Primitive.trigger id="assignee-trigger" listbox_id="assignee-listbox">
Choose an assignee
</PUI.Select.Primitive.trigger>
</PUI.Select.Primitive.root>
Guides
- Usage Guide
- Icons Guide
- Breadcrumb Guide
- Pagination Guide
- Empty Guide
- Separator Guide
- Skeleton Guide
- Avatar Guide
- Headless Usage Guide
- Layouts Guide
- Migrate to PUI
Project model:
Development Commands
Build and setup:
mix setupmix assets.buildmix devmix buildmix publish
Testing and quality:
mix testmix test test/my_test.exsmix test test/my_test.exs:42mix test --failedmix compilemix formatmix docs