Enterprise-ready Phoenix LiveView component library — 119 components, inspired by shadcn/ui.

Ejectable components with zero heavy JS dependencies, full WAI-ARIA accessibility, TailwindCSS v4 semantic tokens, and built-in analytics widgets, enterprise data components, full Calendar & Scheduling Suite, and AI-ready chat UI for financial terminals, BI dashboards, booking platforms, and KPI monitors.

Hex.pm Elixir License: MIT


Why PhiaUI?

FeaturePhiaUIDaisyUISalad UIShadCN/uiDoggoMishka ChelekomPrimer Live
PlatformPhoenix LiveViewCSS / AnyPhoenix LiveViewReactPhoenix LiveViewPhoenix LiveViewPhoenix LiveView
Components11940+~3050+40+~90~40
Copy-paste ownership
LiveView-native (phx-*, streams)
Zero npm runtime depsPartialPartial
Full WAI-ARIA on all interactivePartialPartialPartialPartial
Tailwind CSS v4PartialPartial
Dark mode
CSS-first theming & color presets✓ (8)✓ (20+)PartialPartial
Ecto / FormField integration
Enterprise dashboard shell
KPI / analytics widgets
AI / chat components
Kanban + filter builder
Ctrl+K command palette

DaisyUI — CSS-only Tailwind plugin, framework-agnostic, ideal for rapid prototyping. Salad UI — shadcn/ui patterns for Phoenix LiveView, copy-paste via mix salad.install. ShadCN/ui — React/Next.js, Radix UI primitives, the inspiration behind PhiaUI's copy-paste model. Doggo — headless, unstyled, strict WAI-ARIA; bring your own CSS. Mishka Chelekom — feature-rich Phoenix LiveView kit, CLI-generated components, Tailwind v4. Primer Live — GitHub Primer design system for Phoenix LiveView, library dependency model.


Component Library — 119 Components

Buttons — 7 components

Action triggers for all interaction patterns: primary actions, toolbars, floating actions, and toggles.

ComponentFunctionDescription
Buttonbutton/16 variants (default, destructive, outline, secondary, ghost, link) × 4 sizes, icon size, disabled state
ButtonGroupbutton_group/1Unified button toolbar with horizontal/vertical orientation, shared border radius
BackTopback_top/1Fixed scroll-to-top button — appears after scroll threshold, smooth scroll, fade — PhiaBackTop hook
CopyButtoncopy_button/1Clipboard copy with check-icon feedback and aria-live announcement — PhiaCopyButton hook
FloatButtonfloat_button/1Fixed circular FAB; speed-dial variant with expandable item buttons
Toggletoggle/1aria-pressed stateful button, 2 variants (default, outline), 3 sizes
ToggleGrouptoggle_group/1Single or multiple selection group, :let context for active state

Full documentation

Calendar — 33 components

The most comprehensive calendar and scheduling suite for Phoenix LiveView, covering every date/time interaction pattern from simple pickers to full booking platforms.

ComponentFunctionDescription
BadgeCalendarbadge_calendar/1Calendar with numeric badge overlay per day (counts, notifications)
BigCalendarbig_calendar/1Full-page month view, view switcher (month/week/day), MON-first, event pills
BookingCalendarbooking_calendar/1Appointment booking calendar with availability slots per day and confirm flow
Calendarcalendar/1Server-rendered monthly grid, single/range mode, keyboard navigation
CalendarTimePickercalendar_time_picker/1Full month calendar + inline time picker combined in one component
CalendarWeekViewcalendar_week_view/1Week grid with time axis (00:00–23:00), events positioned by pixel offset
CountdownTimercountdown_timer/1Live server-side countdown to target datetime, displays DD:HH:MM:SS
DailyAgendadaily_agenda/1Single-day timeline with hour rows and overlapping event layout
DateCarddate_card/1Day card with 4 states: default / today / selected / disabled
DateFielddate_field/1, form_date_field/1Segmented date input (DD / MM / YYYY) with independent slot navigation, FormField
DatePickerdate_picker/1Calendar + Popover compose, configurable date format
DateRangePickerdate_range_picker/1Dual calendar range selection, range highlight, min/max bounds — PhiaDateRangePicker hook
DateRangePresetsdate_range_presets/1DateRangePicker extended with preset buttons (Today, This Week, Last 30 Days, custom)
DateStripdate_strip/1Horizontal scrollable row of DateCards, auto-scrolls to selected day
DateTimePickerdate_time_picker/1, form_date_time_picker/1Combined date calendar + time picker in popover, ISO 8601 output, FormField
EventCalendarevent_calendar/1Monthly grid with event pills; day click expands event list
HeatmapCalendarheatmap_calendar/1Contribution-style grid, intensity buckets, role="grid" WAI-ARIA
MonthPickermonth_picker/1, form_month_picker/1Grid of 12 months, year navigation arrows, FormField
MultiMonthCalendarmulti_month_calendar/1Side-by-side N months (2–4), synchronized navigation
MultiSelectCalendarmulti_select_calendar/1Calendar with toggle-per-day multi-day selection
RangeCalendarrange_calendar/1SUN-first month grid, range band: start/end blue circles + half-band + full-band
ScheduleEventCardschedule_event_card/1Rich event card: title, time, location, attendees, status badge
ScheduleViewschedule_view/1Agenda-style list grouped by date, upcoming events sorted chronologically
StreakCalendarstreak_calendar/1Habit tracker / streak heatmap: current streak, longest streak, intensity levels
TimePickertime_picker/1, form_time_picker/1Clock-face or scroll-wheel time selector, 12h/24h, minute step, FormField
TimeSliderPickertime_slider_picker/1Slider-based start/end time range picker
TimeSlotGridtime_slot_grid/1Grid of bookable time slots: available / booked / selected states
TimeSlotListtime_slot_list/1Vertical list of time slots with availability indicator and book button
WeekCalendarweek_calendar/1Compact week navigator: month title + prev/next arrows, 7-day strip, selected-day pill
WeekDayPickerweek_day_picker/1Mon–Sun pill toggles for recurrence rules, multi-select
WeekPickerweek_picker/1, form_week_picker/1ISO week selector (Wxx/YYYY), week highlight in calendar grid, FormField
WheelPickerwheel_picker/1iOS-style scroll-snap wheel picker, configurable columns and items
YearPickeryear_picker/1, form_year_picker/1Scrollable year grid, min/max bounds, FormField

Full documentation


Cards — 5 components

Structured surface components for metrics, selection, and e-commerce receipts.

ComponentFunctionDescription
Cardcard/1Composable card with header, content, and footer slots
MetricGridmetric_grid/1Responsive grid wrapper for multiple StatCards, configurable column count
ReceiptCardreceipt_card/1Transaction/purchase receipt: line items, totals, merchant info, QR slot
SelectableCardselectable_card/1Card with checkbox/radio selection state, border highlight when selected
StatCardstat_card/1KPI card with value, trend indicator (up/down/neutral), and trend value

Full documentation


Data — 13 components

Enterprise data management: tables, grids, charts, Gantt, Kanban, and advanced filters.

ComponentFunctionDescription
BulkActionBarbulk_action_bar/1Contextual toolbar activated by table row selection; action slots
ChartShellchart_shell/1Consistent card chrome wrapper for any chart library
Chartphia_chart/1ECharts integration hook — area, bar, line, pie, scatter — PhiaChart hook
DataGriddata_grid/1Sortable columns with phx-click sort events, next_dir/1 helper
FilterBarfilter_bar/1Horizontal filter toolbar with search, select, toggle, and reset slots
FilterBuilderfilter_builder/1Dynamic query builder: field / operator / value rule rows, add/remove
GanttChartgantt_chart/1Horizontal SVG project timeline: row labels, date-range bars, today indicator
GaugeChartgauge_chart/1SVG semicircle gauge, value needle, min/max labels, configurable color zones
KanbanBoardkanban_board/1Drag-ready column + card layout with priority indicators and avatar slots
SparklineCardsparkline_card/1Inline SVG sparkline polyline + metric value + trend badge
Tabletable/18 sub-components, phx-update="stream" compatible, sortable headers
Treetree/1, tree_item/1Hierarchical tree view via native <details>/<summary> (zero JS), role="tree"
UptimeBaruptime_bar/1Segmented uptime visualization (green/red/yellow segments), percentage badge

Full documentation


Display — 11 components

Visual identity, status indicators, avatars, chat bubbles, and theme control.

ComponentFunctionDescription
ActivityFeedactivity_feed/1Chronological event log with 6 activity types, group labels, and avatar slot
Avataravatar/1Circular profile image with initials fallback, 5 sizes
AvatarGroupavatar_group/1Stacked overlapping avatars, +N overflow badge, configurable max
Badgebadge/14 variants (default, secondary, outline, destructive) for status labels
ChatMessagechat_message/1Full AI/human chat UI: container, bubbles, suggestions, chat input
DarkModeToggledark_mode_toggle/1localStorage + prefers-color-scheme dark mode toggle — PhiaDarkMode hook
Directiondirection/1LTR/RTL wrapper for multilingual (Arabic, Hebrew) content
Iconicon/1Lucide SVG sprite, 4 sizes (xs, sm, md, lg)
Kbdkbd/1Semantic <kbd> keyboard shortcut display
ThemeProvidertheme_provider/1Scoped CSS theme wrapper via data-phia-theme attribute
Timelinetimeline/1Vertical activity timeline with status states, CSS-only connector

Full documentation


Feedback — 11 components

Loading states, alerts, notifications, and progress indicators.

ComponentFunctionDescription
Alertalert/12 variants (default, destructive) with title and description sub-components
AlertDialogalert_dialog/1role="alertdialog", destructive variant, shared PhiaDialog hook
CircularProgresscircular_progress/1Radial SVG progress ring, customizable size/stroke/color, role="progressbar"
EmptyStateempty_state/1Centered placeholder with icon, title, description, and action slots
Progressprogress/1Horizontal role="progressbar", aria-valuenow, indeterminate mode
Skeletonskeleton/1animate-pulse block placeholders for loading states
Snackbarsnackbar/1Temporary bottom-of-screen notification banner, auto-dismiss, action slot
Sonnersonner/1Rich toast stack: icon variants, action button, promise integration — PhiaSonner hook
Spinnerspinner/1CSS SVG animated loading indicator, 5 sizes, role="status" + aria-live
StepTrackerstep_tracker/1Multi-step wizard progress indicator, horizontal and vertical orientation
Toasttoast/1push_event-driven auto-dismiss toast, stacking, 5 variants — PhiaToast hook

Full documentation


Forms — 4 components

Form layout primitives that integrate with Phoenix.HTML.Form and Ecto changesets.

ComponentFunctionDescription
Fieldfield/1Standalone form field layout without Phoenix.HTML.FormField
Formform/1phx-change / phx-submit form wrapper
FormFieldform_field/1, form_label/1, form_message/1Composable label + input + error message primitives
Labellabel/1Accessible <label> with for attribute, required indicator

Full documentation


Inputs — 24 components

Every input primitive with full Ecto / Phoenix.HTML.FormField integration.

ComponentFunctionDescription
Checkboxcheckbox/1, form_checkbox/1Native checkbox, indeterminate state, FormField
Chipchip/1, chip_group/1Interactive pill: toggle (aria-pressed), dismissible (×), 3 variants
ColorPickercolor_picker/1Native <input type="color"> + swatches + hex display — PhiaColorPicker hook
Comboboxcombobox/1Server-side search filter dropdown, FormField integration
Editableeditable/1Click-to-edit inline field: preview/edit toggle, Enter/Escape/click-outside — PhiaEditable hook
FileUploadfile_upload/1, file_upload_entry/1Drag-and-drop zone, phx-drop-target, per-entry progress bar, cancel
ImageUploadimage_upload/1Drop zone + preview grid, native Phoenix live_file_input uploads
Inputinput/1Base <input> element, multiple types, class customization
InputAddoninput_addon/1Prefix/suffix addon wrapper for inputs (icons, labels, currency symbols)
InputOTPinput_otp/1N-slot OTP/PIN input with auto-advance focus, paste distribution, inputmode="numeric"
MentionInputmention_input/1@mention textarea with server-side autocomplete — PhiaMentionInput hook
MultiSelectmulti_select/1, form_multi_select/1<select multiple> with selected-chip row, FormField integration
NumberInputnumber_input/1, form_number_input/1<input type="number"> with ± stepper buttons, prefix/suffix slots, FormField
PasswordInputpassword_input/1, form_password_input/1Password field with show/hide toggle via JS.toggle_attribute, FormField
PhiaInputphia_input/1Unified label + input + description + error message wrapper, all input types
RadioGroupradio_group/1, form_radio_group/1Native radio inputs, :let context, FormField
Ratingrating/1, form_rating/1CSS-only star rating, role="radiogroup", FormField
RichTextEditorrich_text_editor/1WYSIWYG editor, 14 toolbar commands, zero npm — PhiaRichTextEditor hook
SegmentedControlsegmented_control/1Radio-based segment selector, CSS active-sliding state, 3 sizes
Selectselect/1Native <select> with FormField integration
Sliderslider/1, form_slider/1CSS input[type=range], WAI-ARIA aria-valuemin/max/now, FormField
Switchswitch/1, form_switch/1Toggle switch with CSS animation, role="switch", FormField
TagsInputtags_input/1Multi-tag input, deduplication, CSV hidden sync — PhiaTagsInput hook
Textareatextarea/1Multi-line textarea with FormField integration

Full documentation


Layout — 7 components

Structural composition components for panels, scroll areas, and collapsible regions.

ComponentFunctionDescription
Accordionaccordion/1Single or multiple expand mode via Phoenix.LiveView.JS, zero hooks
AspectRatioaspect_ratio/1CSS padding-top ratio trick, any ratio (16:9, 4:3, 1:1, etc.)
Collapsiblecollapsible/1Single-panel expand/collapse, server-controlled open state via Phoenix.LiveView.JS
Resizableresizable/1Drag-to-resize split panels — PhiaResizable hook
ScrollAreascroll_area/1Custom scrollbar overlay, horizontal / vertical / both orientations
Separatorseparator/1Horizontal or vertical divider, role="separator"
Shellshell/1CSS Grid desktop layout: fixed sidebar 240px + fluid main 1fr

Full documentation


Media — 3 components

Audio playback, image carousels, and QR code generation.

ComponentFunctionDescription
AudioPlayeraudio_player/1Full media player: play/pause, scrubber, volume, duration display — PhiaAudioPlayer hook
Carouselcarousel/1Touch-swipe, keyboard navigation, loop, dot indicators — PhiaCarousel hook
QrCodeqr_code/1Inline SVG QR code via eqrcode, configurable size and error correction level

Full documentation


Application chrome: sidebar, topbar, breadcrumbs, tabs, pagination, and mobile navigation.

ComponentFunctionDescription
BottomNavigationbottom_navigation/1, bottom_navigation_item/1Mobile bottom tab bar, aria-current on active tab, icon + label layout
Breadcrumbbreadcrumb/17 sub-components, aria-label="Breadcrumb", aria-current="page" on last item
Menubarmenubar/1Desktop app-style menu bar, role="menubar" + keyboard navigation
MobileSidebarTogglemobile_sidebar_toggle/1Hamburger button that opens sidebar drawer on small viewports
NavigationMenunavigation_menu/1Horizontal nav with links and mega-menu dropdown content panels
Paginationpagination/1Server-side pagination with phx-click page events
Sidebarsidebar/1, sidebar_item/1Fixed sidebar, brand / nav / footer slots, active item highlight
Tabstabs/1tab / list / trigger / content composition, server-rendered, :let context
TabsNavtabs_nav/1Navigation tabs: underline, solid, and pill variants
Toolbartoolbar/1, toolbar_button/1, toolbar_separator/1role="toolbar", icon buttons, keyboard-navigable separator
Topbartopbar/1Full-width application header with left/center/right action slots

Full documentation


Overlay — 9 components

Modal dialogs, drawers, popovers, tooltips, and context menus — all with focus management.

ComponentFunctionDescription
Commandcommand/1Ctrl+K global command palette, arrow-key navigation, server-side filter — PhiaCommand hook
ContextMenucontext_menu/1Right-click context menu, smart positioning, role="menu" WAI-ARIA — PhiaContextMenu hook
Dialogdialog/1Modal dialog with focus trap, Escape to close, scroll lock — PhiaDialog hook
Drawerdrawer/14-direction side panel / bottom sheet, focus trap, backdrop click — PhiaDrawer hook
DropdownMenudropdown_menu/1Trigger + menu: smart flip, click-outside, arrow-key navigation — PhiaDropdownMenu hook
HoverCardhover_card/1role="tooltip" hover preview card, delay show/hide
Popoverpopover/1Click-open floating panel, focus trap, click-outside to close — PhiaPopover hook
Sheetsheet/14 sides (top/right/bottom/left), 5 sizes, modal side panel — PhiaDialog hook
Tooltiptooltip/1Hover + focus tooltip, 4 positions, smart flip — PhiaTooltip hook

Full documentation


Live Sample

See PhiaUI in action with a full enterprise dashboard, booking platform, and CMS built entirely from library components:

github.com/charlenopires/PhiaUI-samples


Quick Start

Step 1 — Install

Add PhiaUI to mix.exs:

def deps do
  [
    {:phia_ui, "~> 0.1.5"}
  ]
end

Fetch dependencies and run the installer:

mix deps.get
mix phia.install

The installer copies all 24 JS hook files to assets/js/phia_hooks/ and injects the base theme import into app.css.

Step 2 — Configure CSS

In assets/css/app.css:

@import "tailwindcss";
@import "../../../deps/phia_ui/priv/static/theme.css";

For runtime color theme switching (optional), generate the multi-theme CSS:

mix phia.theme install

This writes assets/css/phia-themes.css with all 8 [data-phia-theme] selectors and auto-imports it in app.css. Activate a preset by setting data-phia-theme="blue" on any ancestor element or on <html>.

Step 3 — Eject components

Copy specific component source files into your project:

mix phia.add button card dialog

Components are ejected to lib/your_app_web/components/ui/. After ejection you own the code — read it, customize it, delete what you do not need.

lib/your_app_web/components/ui/button.ex       yours to edit
assets/js/phia_hooks/dialog.js                 yours to edit

Step 4 — Import in your LiveView

defmodule MyAppWeb.PageLive do
  use MyAppWeb, :live_view

  import MyAppWeb.Components.UI.Button
  import MyAppWeb.Components.UI.Card
  import MyAppWeb.Components.UI.Dialog

  def render(assigns) do
    ~H"""
    <.button variant="default">Hello PhiaUI</.button>
    """
  end
end

Or import globally in my_app_web.ex:

defp html_helpers do
  quote do
    import MyAppWeb.Components.UI.Button
    import MyAppWeb.Components.UI.Card
    # add more as you eject them
  end
end

Step 5 — Register JS hooks

Add all 24 hooks to assets/js/app.js:

import PhiaDialog          from "./phia_hooks/dialog"
import PhiaDropdownMenu    from "./phia_hooks/dropdown_menu"
import PhiaTagsInput       from "./phia_hooks/tags_input"
import PhiaRichTextEditor  from "./phia_hooks/rich_text_editor"
import PhiaTooltip         from "./phia_hooks/tooltip"
import PhiaPopover         from "./phia_hooks/popover"
import PhiaToast           from "./phia_hooks/toast"
import PhiaDarkMode        from "./phia_hooks/dark_mode"
import PhiaCommand         from "./phia_hooks/command"
import PhiaDateRangePicker from "./phia_hooks/date_range_picker"
import PhiaChart           from "./phia_hooks/chart"
import PhiaCalendar        from "./phia_hooks/calendar"
import PhiaCarousel        from "./phia_hooks/carousel"
import PhiaContextMenu     from "./phia_hooks/context_menu"
import PhiaDrawer          from "./phia_hooks/drawer"
import PhiaTheme           from "./phia_hooks/theme"
import PhiaResizable       from "./phia_hooks/resizable"
import PhiaMentionInput    from "./phia_hooks/mention_input"
import PhiaCopyButton      from "./phia_hooks/copy_button"
import PhiaEditable        from "./phia_hooks/editable"
import PhiaColorPicker     from "./phia_hooks/color_picker"
import PhiaBackTop         from "./phia_hooks/back_top"
import PhiaAudioPlayer     from "./phia_hooks/audio_player"
import PhiaSonner          from "./phia_hooks/sonner"

let liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: csrfToken },
  hooks: {
    PhiaDialog, PhiaDropdownMenu, PhiaTagsInput, PhiaRichTextEditor,
    PhiaTooltip, PhiaPopover, PhiaToast, PhiaDarkMode,
    PhiaCommand, PhiaDateRangePicker, PhiaChart, PhiaCalendar,
    PhiaCarousel, PhiaContextMenu, PhiaDrawer, PhiaTheme,
    PhiaResizable, PhiaMentionInput, PhiaCopyButton, PhiaEditable,
    PhiaColorPicker, PhiaBackTop, PhiaAudioPlayer, PhiaSonner
  }
})

Only import hooks for components you actually use. All hook files are vanilla JS — zero npm runtime dependencies.


Usage Patterns

Buttons & Actions

<%!-- Variants --%>
<.button>Default</.button>
<.button variant="destructive">Delete</.button>
<.button variant="outline" size="sm">
  <.icon name="download" size={:sm} /> Export
</.button>
<.button variant="ghost" size="icon"><.icon name="more-horizontal" size={:sm} /></.button>

<%!-- Button Group toolbar --%>
<.button_group>
  <.button variant="outline" size="icon"><.icon name="bold" size={:sm} /></.button>
  <.button variant="outline" size="icon"><.icon name="italic" size={:sm} /></.button>
  <.button variant="outline" size="icon"><.icon name="underline" size={:sm} /></.button>
</.button_group>

<%!-- Floating action button with speed dial --%>
<.float_button position={:bottom_right}>
  <:main icon="plus" aria_label="Actions" />
  <:item icon="edit"  on_click="edit"   label="Edit" />
  <:item icon="share" on_click="share"  label="Share" />
  <:item icon="trash" on_click="delete" label="Delete" />
</.float_button>

Layout Shell

<.shell>
  <:sidebar>
    <.sidebar>
      <:brand>
        <span class="font-bold text-lg">MyApp</span>
      </:brand>
      <:nav>
        <.sidebar_item href="/dashboard" active={@path == "/dashboard"} icon="layout-dashboard">
          Dashboard
        </.sidebar_item>
        <.sidebar_item href="/users" active={@path =~ "/users"} icon="users">
          Users
        </.sidebar_item>
        <.sidebar_item href="/settings" active={@path =~ "/settings"} icon="settings">
          Settings
        </.sidebar_item>
      </:nav>
    </.sidebar>
  </:sidebar>
  <:topbar>
    <.topbar>
      <:left><h1 class="text-lg font-semibold">{@page_title}</h1></:left>
      <:right>
        <.dark_mode_toggle />
        <.avatar><.avatar_fallback name={@current_user.name} /></.avatar>
      </:right>
    </.topbar>
  </:topbar>
  <:main>
    {@inner_content}
  </:main>
</.shell>

Forms & Inputs

<.form for={@form} phx-change="validate" phx-submit="save">
  <.phia_input field={@form[:email]} type="email" label="Email address" phx-debounce="blur" />
  <.phia_input field={@form[:name]} label="Full name" />
  <.form_number_input field={@form[:age]} label="Age" min={18} max={120} step={1} />
  <.form_password_input field={@form[:password]} label="Password" />

  <.field>
    <div class="flex items-center gap-2">
      <.checkbox id="terms" name="terms" checked={@terms_checked} phx-click="toggle-terms" />
      <.label for="terms">I agree to the Terms of Service</.label>
    </div>
  </.field>

  <.button type="submit" class="w-full">Create account</.button>
</.form>

<%!-- Tags input --%>
<.tags_input id="skill-tags" name="skills" value={@skills} placeholder="Add skill…" />

<%!-- Inline editable field --%>
<.editable id="project-name" value={@project.name} on_submit="rename_project">
  <:preview><h1 class="text-2xl font-bold">{@project.name}</h1></:preview>
  <:input><.phia_input id="project-name-input" name="name" value={@project.name} /></:input>
</.editable>

Overlay Components

<%!-- Dialog --%>
<.dialog id="confirm-dialog" open={@show_dialog}>
  <.dialog_header>
    <.dialog_title>Confirm action</.dialog_title>
    <.dialog_description>This cannot be undone.</.dialog_description>
  </.dialog_header>
  <.dialog_footer>
    <.button variant="outline" phx-click="cancel">Cancel</.button>
    <.button variant="destructive" phx-click="confirm">Confirm</.button>
  </.dialog_footer>
</.dialog>

<%!-- Drawer --%>
<.drawer id="filters-drawer" open={@filters_open} direction="right">
  <.drawer_header><h2 class="font-semibold">Filters</h2></.drawer_header>
  <.drawer_close />
  <div class="px-6 pb-6">
    <.filter_builder fields={@fields} rules={@rules}
      on_add="add_rule" on_remove="remove_rule" on_change="update_rule" />
  </div>
  <.drawer_footer>
    <.button phx-click="apply_filters">Apply filters</.button>
  </.drawer_footer>
</.drawer>

<%!-- Tooltip --%>
<.tooltip content="Copy to clipboard">
  <.copy_button value={@api_key} />
</.tooltip>

<%!-- Command palette (Ctrl+K) --%>
<.command id="command-palette" open={@command_open} on_search="search_commands">
  <.command_input placeholder="Search commands…" />
  <.command_list>
    <.command_item :for={cmd <- @commands} value={cmd.id} on_select="run_command">
      <.icon name={cmd.icon} size={:sm} /> {cmd.label}
    </.command_item>
  </.command_list>
</.command>

Data & Analytics

<%!-- KPI metric grid --%>
<.metric_grid cols={4}>
  <.stat_card title="MRR"   value="$48,290" trend="up"      trend_value="+12.5%" />
  <.stat_card title="Users" value="2,840"   trend="up"      trend_value="+8.2%" />
  <.stat_card title="Churn" value="3.1%"    trend="down"    trend_value="-0.4%" />
  <.stat_card title="NPS"   value="67"      trend="neutral" trend_value="0" />
</.metric_grid>

<%!-- ECharts integration --%>
<.phia_chart
  id="revenue-chart"
  type={:area}
  title="Monthly Revenue"
  series={[%{name: "MRR", data: @mrr_data}]}
  labels={@month_labels}
  height="320px"
/>

<%!-- Streamable data table --%>
<.table id="users-table" rows={@streams.users}>
  <:col :let={user} label="Name">{user.name}</:col>
  <:col :let={user} label="Email">{user.email}</:col>
  <:col :let={user} label="Role"><.badge>{user.role}</.badge></:col>
  <:action :let={user}>
    <.button variant="ghost" size="sm" phx-click="edit" phx-value-id={user.id}>Edit</.button>
  </:action>
</.table>

<%!-- Sparkline widget --%>
<.sparkline_card
  title="Weekly signups"
  value="284"
  trend="up"
  trend_value="+18%"
  data={@weekly_signups}
/>

<%!-- Gauge --%>
<.gauge_chart value={72} min={0} max={100} label="CPU Usage" unit="%" />

Calendar Suite

<%!-- Simple date picker --%>
<.date_picker field={@form[:start_date]} label="Start date" />

<%!-- Booking calendar with time slots --%>
<.booking_calendar
  id="appointment-calendar"
  available_dates={@available_dates}
  selected_date={@selected_date}
  on_date_select="select_date"
/>

<.time_slot_grid
  id="time-slots"
  slots={@time_slots}
  selected={@selected_slot}
  on_select="select_slot"
/>

<%!-- Full-page calendar --%>
<.big_calendar
  id="main-calendar"
  events={@events}
  view={@calendar_view}
  current_date={@current_date}
  on_view_change="change_view"
  on_date_click="open_day"
  on_event_click="open_event"
/>

<%!-- Week view with positioned events --%>
<.calendar_week_view
  id="week-view"
  week_start={@week_start}
  events={@week_events}
  on_slot_click="new_event"
/>

<%!-- Streak/habit tracker --%>
<.streak_calendar
  data={@habit_data}
  current_streak={@current_streak}
  longest_streak={@longest_streak}
/>

Notifications

<%!-- Toast — mount once in root.html.heex --%>
<.toast id="toast-viewport" />
# Trigger from any LiveView event handler
{:noreply,
 socket
 |> push_event("phia-toast", %{
   title: "File saved",
   description: "document.pdf saved successfully.",
   variant: "success"
 })}
<%!-- Sonner (rich toast stack) — mount once in root.html.heex --%>
<.sonner id="sonner-viewport" position="bottom-right" />
# Push a Sonner toast
{:noreply, push_event(socket, "phia-sonner", %{
  message: "Changes published",
  type: "success",
  action: %{label: "Undo", event: "undo_publish"}
})}
<%!-- Snackbar — inline temporary notification --%>
<.snackbar id="save-snackbar" open={@snackbar_open} auto_dismiss={3000}>
  Draft saved automatically
  <:action phx-click="dismiss_snackbar">Dismiss</:action>
</.snackbar>

Feedback

<%!-- Spinner --%>
<.spinner size={:md} label="Loading data…" />

<%!-- Skeleton placeholders --%>
<div class="space-y-3">
  <.skeleton class="h-4 w-3/4" />
  <.skeleton class="h-4 w-1/2" />
  <.skeleton class="h-32 w-full" />
</div>

<%!-- Progress bar --%>
<.progress value={@upload_progress} max={100} aria-label="Upload progress" />

<%!-- Circular progress --%>
<.circular_progress value={68} size={80} stroke_width={8} label="68%" />

<%!-- Empty state --%>
<.empty_state>
  <:icon><.icon name="inbox" class="h-12 w-12 text-muted-foreground" /></:icon>
  <:title>No results found</:title>
  <:description>Try adjusting your filters or search terms.</:description>
  <:action>
    <.button phx-click="reset_filters">Clear filters</.button>
  </:action>
</.empty_state>

<%!-- Step tracker --%>
<.step_tracker>
  <.step status="complete" label="Account"  step={1} />
  <.step status="active"   label="Profile"  step={2} description="Fill in your details" />
  <.step status="upcoming" label="Confirm"  step={3} />
</.step_tracker>

Tutorials

Three end-to-end step-by-step guides that take you from a blank Phoenix LiveView project to a production-ready application.

1. Analytics Dashboard

docs/guides/tutorial-dashboard.md

Build a full enterprise analytics dashboard with a Shell layout (sidebar + topbar), KPI metric cards (StatCard, MetricGrid), live ECharts area and bar charts (PhiaChart), a streamable sortable data table (DataGrid), a Ctrl+K command palette, dark mode toggle, and real-time push_event updates. Covers phx-update="stream", server-side sorting, and hook registration.

2. Booking Platform

docs/guides/tutorial-booking.md

Build a complete appointment booking flow: BookingCalendar for date selection, TimeSlotGrid for slot availability, StepTracker wizard (date → slot → details → confirm), form validation with Ecto changesets, PhiaInput with live error feedback, AlertDialog for cancellation confirmation, and Sonner toast notifications on booking success or failure.

3. Content Management System

docs/guides/tutorial-cms.md

Build a CMS with a RichTextEditor for content authoring, DataGrid with sortable columns and BulkActionBar for bulk publish/archive/delete, KanbanBoard for editorial pipeline management, ActivityFeed for audit log, FilterBuilder for advanced content search, Tree for taxonomy/category management, and Drawer side panel for record editing.


Documentation

FileDescription
docs/components/buttons.mdButton, ButtonGroup, BackTop, CopyButton, FloatButton, Toggle, ToggleGroup
docs/components/calendar.mdAll 33 calendar and scheduling components
docs/components/cards.mdCard, MetricGrid, ReceiptCard, SelectableCard, StatCard
docs/components/data.mdBulkActionBar, Chart, ChartShell, DataGrid, FilterBar, FilterBuilder, GanttChart, GaugeChart, KanbanBoard, SparklineCard, Table, Tree, UptimeBar
docs/components/display.mdActivityFeed, Avatar, AvatarGroup, Badge, ChatMessage, DarkModeToggle, Direction, Icon, Kbd, ThemeProvider, Timeline
docs/components/feedback.mdAlert, AlertDialog, CircularProgress, EmptyState, Progress, Skeleton, Snackbar, Sonner, Spinner, StepTracker, Toast
docs/components/forms.mdField, Form, FormField, Label
docs/components/inputs.mdAll 24 input components
docs/components/layout.mdAccordion, AspectRatio, Collapsible, Resizable, ScrollArea, Separator, Shell
docs/components/media.mdAudioPlayer, Carousel, QrCode
docs/components/navigation.mdBottomNavigation, Breadcrumb, Menubar, MobileSidebarToggle, NavigationMenu, Pagination, Sidebar, Tabs, TabsNav, Toolbar, Topbar
docs/components/overlay.mdCommand, ContextMenu, Dialog, Drawer, DropdownMenu, HoverCard, Popover, Sheet, Tooltip
docs/guides/theme-system.mdCSS-first theming, 8 OKLCH color presets, dark mode, runtime switching, ThemeProvider, anti-FOUC
docs/guides/tutorial-dashboard.mdStep-by-step analytics dashboard tutorial
docs/guides/tutorial-booking.mdStep-by-step booking platform tutorial
docs/guides/tutorial-cms.mdStep-by-step CMS tutorial

Generate ExDoc API reference locally:

mix docs

Theming

PhiaUI ships 8 OKLCH color presets: zinc, slate, blue, rose, orange, green, violet, neutral.

Generate the multi-theme CSS:

mix phia.theme install
# Writes assets/css/phia-themes.css with all 8 [data-phia-theme] selectors
# Auto-imports it in app.css

Activate a preset at the HTML level:

<html class="dark" data-phia-theme="blue">

Scope a theme to a specific section:

<.theme_provider theme={:rose}>
  <.button>Rose button</.button>
</.theme_provider>

Enable runtime theme switching with the PhiaTheme hook:

<select phx-hook="PhiaTheme" id="theme-select">
  <option value="zinc">Zinc</option>
  <option value="blue">Blue</option>
  <option value="rose">Rose</option>
  <option value="green">Green</option>
</select>

Dark mode is toggled by adding/removing the .dark class on <html> via the PhiaDarkMode hook. To prevent flash of unstyled content, add this script to <head> before any stylesheet:

<script>
  (function() {
    var mode = localStorage.getItem('phia-mode');
    if (mode === 'dark' || (!mode && matchMedia('(prefers-color-scheme: dark)').matches)) {
      document.documentElement.classList.add('dark');
    }
    var ct = localStorage.getItem('phia-color-theme');
    if (ct) document.documentElement.setAttribute('data-phia-theme', ct);
  })();
</script>

Full theme guide


License

MIT — see LICENSE.