Registry for managing dashboard tabs across the application.
The Registry provides both compile-time configuration via application config and runtime registration for dynamic tabs. Tabs are stored in an ETS table for efficient access.
Configuration
Tabs can be configured in your application config:
config :phoenix_kit, :user_dashboard_tabs, [
%{
id: :orders,
label: "Orders",
icon: "hero-shopping-bag",
path: "orders",
priority: 100
},
%{
id: :settings,
label: "Settings",
icon: "hero-cog-6-tooth",
path: "settings",
priority: 900
}
]Tab paths are relative by convention —
Tab.resolve_path/2prepends the context prefix (/dashboard/,/admin/, or/admin/settings/) at load time. Both relative and absolute forms are accepted but relative is preferred.
Runtime Registration
Parent applications can register tabs at runtime:
PhoenixKit.Dashboard.Registry.register(:my_app, [
Tab.new!(id: :custom, label: "Custom", path: "custom", priority: 150)
])Groups
Tabs can be organized into groups:
config :phoenix_kit, :user_dashboard_tab_groups, [
%{id: :main, label: nil, priority: 100},
%{id: :farm, label: "Farm Management", priority: 200, icon: "hero-cube"},
%{id: :account, label: "Account", priority: 900}
]Then assign tabs to groups:
%{id: :printers, label: "Printers", path: "printers", group: :farm}PubSub Integration
The registry can broadcast tab updates:
PhoenixKit.Dashboard.Registry.update_tab_badge(:notifications, Badge.count(5))LiveViews subscribed to "phoenix_kit:dashboard:tabs" will receive updates.
Summary
Functions
Drops the tabs listed in :hidden_admin_tabs from tabs.
Broadcasts a full tab list refresh to all subscribers.
Broadcasts a tab update to all subscribers.
Returns a specification to start this module under a supervisor.
Clears attention animation from a tab.
Gets admin-level tabs, filtered by permission and module-enabled status.
Gets all registered groups, sorted by priority.
Gets all subtabs for a given parent tab ID.
Gets a specific tab by ID.
Gets all registered tabs, sorted by priority.
Gets all tabs in a specific group.
Gets all tabs with their active state for the given path.
Gets only top-level tabs (tabs without a parent).
Gets user-level tabs.
Checks if a tab has any subtabs.
Admin tab ids the host has hidden
Checks if the registry has been initialized.
Loads admin default tabs.
Loads the default PhoenixKit tabs (Dashboard, Settings).
Loads tabs from application configuration.
The admin path of the tab that declares view as its live_view, or
"/admin" when nothing claims it.
Gets the PubSub topic for tab updates.
Registers tabs for an application namespace.
Registers tabs from a map/keyword configuration.
Registers tab groups.
Sets an attention animation on a tab.
Starts the Registry GenServer.
Unregisters all tabs for a namespace.
Unregisters a specific tab by ID.
Updates an existing tab's attributes.
Updates a tab's badge.
Functions
@spec broadcast_refresh() :: :ok
Broadcasts a full tab list refresh to all subscribers.
@spec broadcast_update(PhoenixKit.Dashboard.Tab.t()) :: :ok
Broadcasts a tab update to all subscribers.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec clear_tab_attention(atom()) :: :ok
Clears attention animation from a tab.
@spec get_admin_tabs(keyword()) :: [PhoenixKit.Dashboard.Tab.t()]
Gets admin-level tabs, filtered by permission and module-enabled status.
Options
:scope- The current scope (for permission and visibility filtering):include_hidden- Include tabs that would be hidden (default: false)
@spec get_groups() :: [PhoenixKit.Dashboard.Group.t()]
Gets all registered groups, sorted by priority.
@spec get_subtabs( atom(), keyword() ) :: [PhoenixKit.Dashboard.Tab.t()]
Gets all subtabs for a given parent tab ID.
Examples
Registry.get_subtabs(:orders)
# => [%Tab{id: :pending_orders, parent: :orders, ...}, ...]
@spec get_tab(atom()) :: PhoenixKit.Dashboard.Tab.t() | nil
Gets a specific tab by ID.
@spec get_tabs(keyword()) :: [PhoenixKit.Dashboard.Tab.t()]
Gets all registered tabs, sorted by priority.
Options
:scope- The current scope (for visibility filtering):level- Filter by tab level::admin,:user, or nil for all:path- The current path (for active state detection):include_hidden- Include tabs that would be hidden (default: false)
Examples
Registry.get_tabs()
Registry.get_tabs(scope: scope, level: :user)
Registry.get_tabs(scope: scope, level: :admin)
@spec get_tabs_in_group( atom(), keyword() ) :: [PhoenixKit.Dashboard.Tab.t()]
Gets all tabs in a specific group.
Gets all tabs with their active state for the given path.
Returns tabs with an additional :active key set based on path matching.
@spec get_top_level_tabs(keyword()) :: [PhoenixKit.Dashboard.Tab.t()]
Gets only top-level tabs (tabs without a parent).
Options
Same as get_tabs/1.
Examples
Registry.get_top_level_tabs()
# => [%Tab{id: :orders, parent: nil, ...}, ...]
@spec get_user_tabs(keyword()) :: [PhoenixKit.Dashboard.Tab.t()]
Gets user-level tabs.
Options
:scope- The current scope (for visibility filtering):include_hidden- Include tabs that would be hidden (default: false)
Checks if a tab has any subtabs.
Examples
Registry.has_subtabs?(:orders)
# => true
@spec initialized?() :: boolean()
Checks if the registry has been initialized.
@spec load_admin_defaults() :: :ok
Loads admin default tabs.
Called during initialization.
@spec load_defaults() :: :ok
Loads the default PhoenixKit tabs (Dashboard, Settings).
Called during initialization and can be used to reset to defaults.
@spec load_from_config() :: :ok
Loads tabs from application configuration.
Reads from :phoenix_kit, :user_dashboard_tabs config key.
The admin path of the tab that declares view as its live_view, or
"/admin" when nothing claims it.
Sidebar active-state reads assigns[:url_path], which the kit's on_mount
chain fills in from a :handle_params hook. Two kinds of LiveView never get
it: one rendered via live_render/3 (an embed has no handle_params
lifecycle at all) and a host LV that renders admin chrome without going
through that chain. Both used to render with no tab highlighted and nothing
to suggest why. A tab already knows its own path, so ask it.
@spec pubsub_topic() :: String.t()
Gets the PubSub topic for tab updates.
LiveViews can subscribe to this topic to receive real-time tab updates.
Example
def mount(_params, _session, socket) do
if connected?(socket) do
Phoenix.PubSub.subscribe(PubSubHelper.pubsub(), Registry.pubsub_topic())
end
{:ok, socket}
end
def handle_info({:tab_updated, tab}, socket) do
# Handle tab update
{:noreply, socket}
end
@spec register(atom(), PhoenixKit.Dashboard.Tab.t() | [PhoenixKit.Dashboard.Tab.t()]) :: :ok
Registers tabs for an application namespace.
Examples
Registry.register(:my_app, [
Tab.new!(id: :home, label: "Home", path: "", icon: "hero-home"),
Tab.new!(id: :orders, label: "Orders", path: "orders")
])
# Register a single tab
Registry.register(:my_app, Tab.new!(id: :settings, label: "Settings", path: "settings"))
Registers tabs from a map/keyword configuration.
Useful for registering tabs from config files.
Examples
Registry.register_from_config(:my_app, [
%{id: :home, label: "Home", path: "", icon: "hero-home"},
%{id: :orders, label: "Orders", path: "orders"}
])
@spec register_groups([PhoenixKit.Dashboard.Group.t() | map()]) :: :ok
Registers tab groups.
Examples
Registry.register_groups([
%{id: :main, label: nil, priority: 100},
%{id: :farm, label: "Farm Management", priority: 200},
%{id: :account, label: "Account", priority: 900}
])
Sets an attention animation on a tab.
Examples
Registry.set_tab_attention(:alerts, :pulse)
Registry.set_tab_attention(:notifications, :bounce)
Starts the Registry GenServer.
This is typically called by the PhoenixKit supervisor.
@spec unregister(atom()) :: :ok
Unregisters all tabs for a namespace.
@spec unregister_tab(atom()) :: :ok
Unregisters a specific tab by ID.
Updates an existing tab's attributes.
Examples
Registry.update_tab(:admin_dashboard, %{label: "Home", icon: "hero-house"})
@spec update_tab_badge(atom(), PhoenixKit.Dashboard.Badge.t() | map() | nil) :: :ok
Updates a tab's badge.
This broadcasts an update to all subscribed LiveViews.
Examples
Registry.update_tab_badge(:notifications, Badge.count(5))
Registry.update_tab_badge(:printers, Badge.count(3, color: :warning))