AshPanel
A flexible, composable resource management UI library for Ash Framework applications.
Features
- Auto-discovery: Automatically introspects Ash resources to generate complete admin interfaces
- Reactive State: Powered by AshComputer for clean, declarative reactive state management
- Fully Customizable: Swap out any component while maintaining the core logic
- Authorization Aware: Respects Ash policies and authorization rules
- Composable: Mix and match components, layouts, and views
- Zero Config Start: Get a full CRUD interface with minimal code
Philosophy
"Configuration by introspection, customization by composition"
Start with zero configuration and progressively customize as needed.
Quick Start
Installation
Add ash_panel to your dependencies:
def deps do
[
{:ash_panel, "~> 0.1.0"}
]
endBasic Usage
Option 1: Using ResourceLive (Recommended)
# Create a LiveView module
defmodule MyAppWeb.Admin.UsersLive do
use AshPanel.ResourceLive,
resource: MyApp.Accounts.User,
domain: MyApp.Accounts
end
# Mount in your router
defmodule MyAppWeb.Router do
use MyAppWeb, :router
use AshPanel.Router
scope "/admin" do
pipe_through [:browser, :require_authenticated_user]
ash_panel_resource "/users", MyAppWeb.Admin.UsersLive
end
endThis generates standard RESTful routes:
GET /admin/users- List all usersGET /admin/users/new- Create new userGET /admin/users/:id- View user detailsGET /admin/users/:id/edit- Edit user
Option 2: Using Individual Views
defmodule MyAppWeb.Admin.UsersLive do
use AshPanel.LiveView,
resource: MyApp.Accounts.User,
domain: MyApp.Accounts
endBoth options give you a full CRUD interface with:
- Pagination
- Filtering (auto-generated from resource attributes)
- Sorting
- Search
- Detail view
- Forms (create/edit)
See ROUTER_EXAMPLE.md for a complete multi-resource example.
Customization
Level 1: Configuration
defmodule MyAppWeb.Admin.UsersLive do
use AshPanel.LiveView,
resource: MyApp.Accounts.User,
domain: MyApp.Accounts,
per_page: 25,
searchable_fields: [:email, :name],
default_sort: [inserted_at: :desc]
# Override attribute display
attribute :email do
label "Email Address"
sortable true
filterable true
end
# Add custom actions
action :send_welcome_email do
label "Send Welcome"
icon "mail"
confirmation "Send welcome email?"
end
endLevel 2: Custom Components
# Implement the behavior
defmodule MyApp.Components.CustomTable do
@behaviour AshPanel.Components.TableBehavior
use Phoenix.Component
@impl true
def render(assigns) do
~H"""
<!-- Your custom table implementation -->
"""
end
end
# Use it
defmodule MyAppWeb.Admin.UsersLive do
use AshPanel.LiveView,
resource: MyApp.Accounts.User,
domain: MyApp.Accounts,
components: [
table: MyApp.Components.CustomTable
]
endLevel 3: Custom Computers
defmodule MyAppWeb.Admin.UsersLive do
use AshPanel.LiveView,
resource: MyApp.Accounts.User,
domain: MyApp.Accounts
# Extend the generated computer
extend_computer :list_view do
input :custom_filter do
initial nil
end
val :custom_data do
compute fn %{query_result: results} ->
# Custom computation
end
end
end
endLevel 4: Completely Custom
defmodule MyAppWeb.Admin.CustomUsersLive do
use Phoenix.LiveView
use AshPanel.Computers
# Use just the computers, provide your own render
def render(assigns) do
~H"""
<!-- Completely custom layout -->
"""
end
endViews and Layouts
AshPanel provides ready-to-use container components for common scenarios:
Views
AshPanel.Views.ListView- Complete list view with table, filters, and paginationAshPanel.Views.DetailView- Single record detail view with relationshipsAshPanel.Views.FormView- Create/update form with validation
Layouts
AshPanel.Layouts.SidebarLayout- Admin interface with sidebar navigationAshPanel.Layouts.TopbarLayout- Simple top navigation barAshPanel.Layouts.MinimalLayout- Minimal layout for embedding
Example
def render(assigns) do
~H"""
<AshPanel.Layouts.MinimalLayout.render
title="User Management"
actions={[%{label: "New User", on_click: "show_create_form", primary: true}]}
>
<AshPanel.Views.ListView.render
rows={@list_view_rows}
columns={@list_view_columns}
current_page={@list_view_current_page}
total_pages={@list_view_total_pages}
on_row_click={&handle_row_click/1}
/>
</AshPanel.Layouts.MinimalLayout.render>
"""
endSee ZERO_CONFIG_EXAMPLE.md for a complete working example.
Component Behaviors
AshPanel defines behaviors for all swappable components:
AshPanel.Components.TableBehavior- Table/list renderingAshPanel.Components.FilterBarBehavior- Filter controlsAshPanel.Components.PaginationBehavior- Pagination controls
Each behavior documents the expected assigns and contracts.
Architecture
AshPanel separates concerns into four layers:
- Introspection Layer - Auto-discovers resource metadata
- Computation Layer - AshComputer-based reactive logic
- Configuration Layer - DSL for customization
- Presentation Layer - Pluggable UI components
This separation allows you to customize at any level without breaking the others.
Comparison
| Feature | AshPanel | AshAdmin | Backpex |
|---|---|---|---|
| Auto-discovery | ✅ Full | ✅ Full | ⚠️ Manual |
| Customization | ✅ Excellent | ❌ Limited | ✅ Good |
| Reactive State | ✅ AshComputer | ❌ Manual | ❌ Manual |
| Component Swapping | ✅ Full | ❌ No | ✅ Yes |
| Dependencies | Phoenix LV | Phoenix LV | LV + DaisyUI + Alpine |
Documentation
See the full documentation for:
- Detailed guides
- Component reference
- Customization examples
- Migration guides
License
MIT License - see LICENSE file for details.
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.