Higher-level components that map to shadcn patterns with progressive enhancement.
Included:
command/1combobox/1carousel/1chart/1sidebar_layout/1sidebar/1sidebar_main/1sidebar_header/1sidebar_footer/1sidebar_group/1sidebar_item/1sidebar_profile_menu/1sidebar_trigger/1item/1
These components intentionally favor no-JS defaults and expose hooks/classes so advanced interactions can be layered in using LiveView hooks.
Summary
Functions
Carousel shell.
Chart frame component for wrapping chart libraries with shadcn tokens.
Combobox scaffold using an input and option list.
Command palette layout.
Command/list item.
Sidebar panel region.
Sidebar footer container.
Sidebar group wrapper.
Sidebar header container.
Sidebar navigation item.
Phoenix-first sidebar shell for app layouts.
Sidebar sibling content region.
Profile/account menu pattern for sidebar footers.
Button that toggles the surrounding sidebar_layout/1 between expanded and collapsed.
Functions
Carousel shell.
Render slides in :item slots and wire interactions with a LiveView hook or
external script.
## Example
heex title="Carousel" align="full" <.carousel id="feature-carousel"> <:item><div class="rounded-md bg-muted p-8 text-sm">Slide one</div></:item> <:item><div class="rounded-md bg-muted/60 p-8 text-sm">Slide two</div></:item> </.carousel>
heex title="Autoplay with indicators" align="full" <.carousel id="marketing-carousel" autoplay={4000} indicators={true}> <:item><div class="rounded-md bg-muted p-8 text-sm">Overview</div></:item> <:item><div class="rounded-md bg-muted/60 p-8 text-sm">Analytics</div></:item> <:item><div class="rounded-md bg-muted/40 p-8 text-sm">Deployments</div></:item> </.carousel>
Screenshot

Chart frame component for wrapping chart libraries with shadcn tokens.
## Example
heex title="Chart shell" align="full" <.chart> <:title>Traffic</:title> <:description>Requests over the last 7 days.</:description> <div class="h-40 rounded-md bg-muted/60"></div> </.chart>
Screenshot

Combobox scaffold using an input and option list.
It is intentionally unopinionated on state and filtering logic.
## When to use it
Use combobox/1 when you want a lightweight client-side filter input that
writes the selected label back into the visible text field.
Typing narrows the list and implicitly highlights the first visible match, so
Enter can accept it without extra arrow-key navigation. Escape and
clicking away restore the last committed value.
Prefer autocomplete/1 when the selected value needs to submit through a
hidden input, when labels and values differ, or when the control participates
in a larger form workflow.
## Example
heex title="Combobox" align="full" <.combobox id="plan" value="Pro"> <:option value="Free" label="Free" /> <:option value="Pro" label="Pro" /> </.combobox>
Screenshot

Command palette layout.
This renders the shell of a command palette (input + list + items).
## Examples
heex title="Command palette" align="full" <.command placeholder="Search commands..."> <:group heading="General"> <.item value="profile">Profile</.item> <.item value="billing">Billing</.item> </:group> <:group heading="Workspace"> <.item value="settings">Settings</.item> </:group> </.command>
heex title="Project switcher" align="full" <.command placeholder="Jump to project..."> <:group heading="Projects"> <.item value="docs">Docs site</.item> <.item value="demo">Demo app</.item> </:group> <:group heading="Teams"> <.item value="platform">Platform team</.item> </:group> </.command>
Screenshot

Command/list item.
## Example
heex title="Command item" align="full" <.command> <:group heading="General"> <.item value="profile">Profile</.item> </:group> </.command>
Screenshot

Sidebar panel region.
This is the left-hand sidebar itself. Use it inside sidebar_layout/1.
## Example
heex title="Sidebar panel" align="full" <div class="h-64 overflow-hidden rounded-xl border"> <.sidebar class="h-full"> <:header> <.sidebar_header> <span data-sidebar-label class="text-sm font-semibold">Workspace</span> </.sidebar_header> </:header> <.sidebar_group label="Navigation"> <.sidebar_item icon="home" current={true}>Home</.sidebar_item> <.sidebar_item icon="folder">Projects</.sidebar_item> </.sidebar_group> <:footer> <.sidebar_footer> <span class="text-sidebar-foreground/70 text-xs">Low-level panel helper</span> </.sidebar_footer> </:footer> </.sidebar> </div>
Screenshot

Sidebar group wrapper.
Groups are useful for labeled sections such as navigation, tools, or account
controls. Pass label for the section heading and render sidebar_item/1
children directly inside the group.
## Example
heex title="Sidebar group" align="full" <.sidebar_layout id="sidebar-group-example" full_screen={false}> <:header> <.sidebar_header> <span data-sidebar-label class="text-sm font-semibold">Product nav</span> </.sidebar_header> </:header> <:sidebar> <.sidebar_group label="Workspace"> <.sidebar_item icon="folder-kanban" current={true} collapsible={true} default_open={true}> Projects <:children> <.sidebar_item>Roadmap</.sidebar_item> <.sidebar_item>Releases</.sidebar_item> </:children> </.sidebar_item> <.sidebar_item icon="ship-wheel" badge="2">Deployments</.sidebar_item> <.sidebar_item icon="message-square">Feedback</.sidebar_item> </.sidebar_group> <.sidebar_group label="Insights"> <.sidebar_item icon="chart-column">Analytics</.sidebar_item> <.sidebar_item icon="bell-ring" badge="4">Alerts</.sidebar_item> </.sidebar_group> </:sidebar> <:main> <div class="rounded border bg-card p-4 text-sm"> A sidebar can stack multiple labeled groups while keeping each section visually separate. </div> </:main> </.sidebar_layout>
Screenshot

Sidebar header container.
Use this inside the :header slot of sidebar_layout/1 for branding,
workspace selectors, or the collapse trigger.
## Example
heex title="Sidebar header" align="full" <.sidebar_layout id="sidebar-header-example" full_screen={false}> <:header> <.sidebar_header> <div data-sidebar-label class="min-w-0 flex-1"> <p class="truncate text-sm font-semibold">Workspace</p> <p class="text-sidebar-foreground/70 truncate text-xs">Active release branch</p> </div> <.badge variant={:outline}>3 open</.badge> </.sidebar_header> </:header> <:sidebar> <.sidebar_group label="Navigation"> <.sidebar_item icon="home" current={true}>Overview</.sidebar_item> </.sidebar_group> </:sidebar> <:main><div class="rounded border bg-card p-4 text-sm">Inset</div></:main> </.sidebar_layout>
Screenshot

Sidebar navigation item.
Use this inside sidebar_group/1 for app routes, navigation rows, and
nested secondary items.
## Examples
heex title="Sidebar item" align="full" <.sidebar_group label="Navigation"> <.sidebar_item icon="home" current={true}>Overview</.sidebar_item> <.sidebar_item icon="inbox">Inbox</.sidebar_item> </.sidebar_group>
heex title="Collapsible nested items" align="full" <.sidebar_group label="Workspace"> <.sidebar_item icon="folder-kanban" collapsible={true} default_open={true}> Docs <:children> <.sidebar_item>Getting started</.sidebar_item> <.sidebar_item>Components</.sidebar_item> </:children> </.sidebar_item> <.sidebar_item icon="ship-wheel" href="#deployments" badge="3"> Deployments </.sidebar_item> </.sidebar_group>
Screenshot

Phoenix-first sidebar shell for app layouts.
This component is designed for LiveView and server-rendered Phoenix apps,
rather than mirroring shadcn's React-only primitive structure. Use the
:header, :sidebar, :footer, and :main slots as the primary API.
sidebar/1 and sidebar_main/1 remain available as lower-level escape
hatches when you need manual control.
Use default_open for the default uncontrolled behavior. Pass open to let
LiveView control the current state, and pair it with toggle_event if the
built-in trigger should push a server event instead of toggling locally.
By default the sidebar shell stretches to the viewport height. Set
full_screen={false} when rendering inside a nested panel or container that
already manages its own height.
## Examples
heex title="Workspace shell" align="full" vrt <.sidebar_layout id="workspace-shell-sidebar" persist_key="docs:workspace-shell"> <:header> <.sidebar_header> <button type="button" class="hover:bg-sidebar-accent hover:text-sidebar-accent-foreground flex w-full items-center gap-3 rounded-lg px-2 py-2 text-left transition-colors" > <div class="bg-sidebar-primary text-sidebar-primary-foreground flex size-8 items-center justify-center rounded-lg"> <.icon name="briefcase-business" class="size-4" /> </div> <div data-sidebar-label class="min-w-0 flex-1"> <p class="truncate text-sm font-medium">Acme Inc</p> <p class="text-sidebar-foreground/70 truncate text-xs">Enterprise</p> </div> <div data-sidebar-label class="text-sidebar-foreground/70 flex flex-col"> <.icon name="chevron-up" class="size-3" /> <.icon name="chevron-down" class="size-3 -mt-1" /> </div> </button> </.sidebar_header> </:header> <:sidebar> <.sidebar_group label="Platform"> <.sidebar_item icon="square-play" current={true} collapsible={true} default_open={true}> Playground <:children> <.sidebar_item>History</.sidebar_item> <.sidebar_item>Starred</.sidebar_item> <.sidebar_item>Settings</.sidebar_item> </:children> </.sidebar_item> <.sidebar_item icon="bot">Models</.sidebar_item> <.sidebar_item icon="book-open">Documentation</.sidebar_item> <.sidebar_item icon="settings-2">Settings</.sidebar_item> </.sidebar_group> </:sidebar> <:footer> <.sidebar_footer> <.sidebar_profile_menu id="workspace-shell-profile-menu" name="shadcn" subtitle="m@example.com" avatar_src="example.png" avatar_alt="shadcn" > <:item icon="badge-check">Account</:item> <:item icon="credit-card">Billing</:item> <:item icon="bell">Notifications</:item> <:item icon="log-out" separator_before={true}>Log out</:item> </.sidebar_profile_menu> </.sidebar_footer> </:footer> <:main> <div class="space-y-4"> <div class="flex h-7 items-center"> <.sidebar_trigger /> </div> <section class="rounded-xl border bg-card p-5"> <div class="flex items-center justify-between gap-4"> <div> <h3 class="text-sm font-semibold">Release readiness</h3> <p class="text-muted-foreground mt-1 text-sm">2 items need review before ship.</p> </div> <.button size={:sm}>Open queue</.button> </div> </section> <div class="grid gap-4 md:grid-cols-2"> <section class="rounded-xl border bg-card p-4"> <h3 class="text-sm font-semibold">Current focus</h3> <p class="text-muted-foreground mt-3 text-sm"> Ship the refreshed component docs and tighten visual regression coverage. </p> </section> <section class="rounded-xl border bg-card p-4"> <h3 class="text-sm font-semibold">This week</h3> <p class="text-muted-foreground mt-3 text-sm"> Sidebar primitives, docs examples, and browser-driven QA. </p> </section> </div> </div> </:main> </.sidebar_layout>
heex title="Collapsed by default" align="full" <.sidebar_layout id="collapsed-sidebar" default_open={false} full_screen={false}> <:header> <.sidebar_header> <span data-sidebar-label class="text-sm font-semibold">Navigation</span> </.sidebar_header> </:header> <:sidebar> <.sidebar_group label="Navigation"> <.sidebar_item icon="home" current={true}>Home</.sidebar_item> <.sidebar_item icon="inbox">Inbox</.sidebar_item> <.sidebar_item icon="settings">Settings</.sidebar_item> </.sidebar_group> </:sidebar> <:main> <div class="space-y-4"> <div class="flex h-7 items-center"> <.sidebar_trigger /> </div> <div class="rounded-xl border bg-card p-4"> <h3 class="text-sm font-semibold">Compact inset content</h3> <p class="text-muted-foreground mt-2 text-sm"> Collapse the rail by default when the surrounding panel already provides context. </p> </div> </div> </:main> </.sidebar_layout>
heex title="Server-controlled open state" align="full" <.sidebar_layout id="server-controlled-sidebar" open={false} toggle_event="sidebar:set_open" full_screen={false} > <:header> <.sidebar_header> <span data-sidebar-label class="text-sm font-semibold">Workspace</span> <.sidebar_trigger /> </.sidebar_header> </:header> <:sidebar> <.sidebar_group label="Workspace"> <.sidebar_item icon="home" current={true}>Overview</.sidebar_item> <.sidebar_item icon="inbox">Approvals</.sidebar_item> <.sidebar_item icon="settings">Settings</.sidebar_item> </.sidebar_group> </:sidebar> <:main> <div class="space-y-4"> <div class="rounded-xl border bg-card p-4"> <h3 class="text-sm font-semibold">Sidebar state comes from LiveView assigns.</h3> <p class="text-muted-foreground mt-2 text-sm"> The trigger pushes an event, but the shell stays collapsed until the server sends back `open={true}`. </p> </div> <div class="rounded-xl border border-dashed p-4 text-sm text-muted-foreground"> Useful when a layout-level toggle also drives persistence, analytics, or permission-based nav changes. </div> </div> </:main> </.sidebar_layout>
heex title="Internal scrolling in a nested panel" align="full" <div class="h-80 overflow-hidden rounded-xl border"> <.sidebar_layout id="scrolling-sidebar" full_screen={false}> <:sidebar> <.sidebar_group label="Large section"> <.sidebar_item :for={index <- 1..14} icon="folder-open"> Project {index} </.sidebar_item> </.sidebar_group> <.sidebar_group label="Pinned"> <.sidebar_item icon="star">Launch checklist</.sidebar_item> <.sidebar_item icon="clock-3">Weekly review</.sidebar_item> </.sidebar_group> </:sidebar> <:main> <div class="space-y-4"> <div class="rounded-xl border bg-card p-4"> <h3 class="text-sm font-semibold">Internal scrolling</h3> <p class="text-muted-foreground mt-2 text-sm"> Constrain the parent height and the sidebar’s content region becomes internally scrollable. </p> </div> <div class="rounded-xl border border-dashed p-4 text-sm text-muted-foreground"> This pattern works well for nested inspectors, settings panes, or workflow steps embedded in a larger page. </div> </div> </:main> </.sidebar_layout> </div>
Screenshot

Sidebar sibling content region.
Use this inside sidebar_layout/1 for the main page content that sits beside
the sidebar.
## Example
heex title="Sidebar main" align="full" <div class="overflow-hidden rounded-xl border"> <.sidebar_main class="space-y-4"> <div class="rounded border bg-card p-4 text-sm">Content area</div> <div class="rounded border border-dashed p-4 text-sm text-muted-foreground"> Use the lower-level helper when you want manual control over the main region wrapper. </div> </.sidebar_main> </div>
Screenshot

Button that toggles the surrounding sidebar_layout/1 between expanded and collapsed.
By default this renders the compact shadcn-style icon button. You can also
supply your own trigger content or change the rendered tag with as.
## Example
heex title="Sidebar trigger" align="full" <.sidebar_layout id="sidebar-trigger-example" full_screen={false}> <:header> <.sidebar_header> <span data-sidebar-label class="text-sm font-semibold">Navigation</span> <.sidebar_trigger /> </.sidebar_header> </:header> <:sidebar> <.sidebar_group label="Navigation"> <.sidebar_item icon="home" current={true}>Overview</.sidebar_item> <.sidebar_item icon="box">Releases</.sidebar_item> </.sidebar_group> </:sidebar> <:main><div class="rounded border bg-card p-4 text-sm">Inset</div></:main> </.sidebar_layout>
heex title="Custom trigger content" align="full" <.sidebar_layout id="sidebar-trigger-custom-example" full_screen={false}> <:header> <.sidebar_header> <span data-sidebar-label class="text-sm font-semibold">Workspace</span> <.sidebar_trigger as="div" class="gap-2 px-2 text-xs"> <.icon name="panel-left" class="size-4" /> <span data-sidebar-label>Collapse</span> </.sidebar_trigger> </.sidebar_header> </:header> <:sidebar> <.sidebar_group label="Workspace"> <.sidebar_item icon="folder">Projects</.sidebar_item> <.sidebar_item icon="users">Team</.sidebar_item> </.sidebar_group> </:sidebar> <:main><div class="rounded border bg-card p-4 text-sm">Inset</div></:main> </.sidebar_layout>
Screenshot


