Tabs component with two visual styles and optional LiveView URL-sync.
Variants
underline— classic bottom-border tabs (default, like GitHub)pills— rounded pill buttons (like Notion or shadcn)boxed— segmented control style (like macOS)
Modes
LiveView event mode (default) — tab changes push a switch_tab event:
<.tabs active={@active_tab} on_change="switch_tab">
<:tab id="overview">Overview</:tab>
<:tab id="deployments">Deployments</:tab>
<:tab id="settings">Settings</:tab>
</.tabs>
def handle_event("switch_tab", %{"tab" => tab}, socket) do
{:noreply, assign(socket, active_tab: tab)}
endURL patch mode — tab changes patch the current URL:
<.tabs active={@active_tab} patch="/projects/:id" param="tab">
<:tab id="overview">Overview</:tab>
<:tab id="settings">Settings</:tab>
</.tabs>
# In mount/handle_params:
def handle_params(%{"tab" => tab}, _uri, socket) do
{:noreply, assign(socket, active_tab: tab || "overview")}
endTabs with content panels — pass panels via inner_block:
<.tabs active={@tab} on_change="switch_tab">
<:tab id="code">Code</:tab>
<:tab id="preview">Preview</:tab>
<:tab id="settings">Settings</:tab>
<:panel id="code"><pre><code>...</code></pre></:panel>
<:panel id="preview"><.live_preview /></:panel>
<:panel id="settings"><.settings_form /></:panel>
</.tabs>
Summary
Functions
Renders a tabs component with optional content panels.
Functions
Renders a tabs component with optional content panels.
Attributes
active(:string) (required) - ID of the currently active tab.variant(:string) - Defaults to"underline". Must be one of"underline","pills", or"boxed".on_change(:string) - phx event name on tab click. Defaults tonil.patch(:string) - URL prefix for patch navigation. Defaults tonil.param(:string) - Query param name when using patch. Defaults to"tab".size(:string) - Defaults to"md". Must be one of"sm","md", or"lg".class(:string) - Defaults tonil.
Slots
tab(required) - Accepts attributes:id(:string) (required)badge(:string) - Optional count badge shown next to tab label.icon(:string) - Optional SVG path for an icon.
panel- Content panel — rendered when its id matches active. Accepts attributes:id(:string) (required)