Docs

Cinder UI

Component Library

Static docs for Cinder UI components. Open any component for preview, HEEx usage, generated attributes/slots docs, and a link to the original shadcn/ui reference.

Components: 110

Actions

Actions.button

Server-rendered Open docs

Renders a shadcn-style button.

  <.button type="submit">Save changes</.button>

Actions.button_group

Server-rendered Open docs

Renders a horizontal or vertical button group.

  <.button_group>
  <.button>Deploy</.button>
  <.button variant={:outline}>Rollback</.button>
</.button_group>

Actions.toggle

Server-rendered Open docs

Renders a shadcn-style toggle button.

  <.toggle pressed={true}>Bold</.toggle>

Actions.toggle_group

Server-rendered Open docs

Groups toggles in either single-select or multi-select mode.

  <.toggle_group type={:single}>
  <.toggle>Left</.toggle>
  <.toggle pressed={true}>Center</.toggle>
  <.toggle>Right</.toggle>
</.toggle_group>

Forms

Forms.autocomplete

Progressive Open docs

Renders a filterable autocomplete input backed by a hidden form value.

  <.autocomplete id="team-owner" name="owner" value="levi">
  <:option value="levi" label="Levi Buzolic" description="Engineering" />
  <:option value="mira" label="Mira Chen" description="Design" />
  <:option value="sam" label="Sam Hall" description="Operations" />
</.autocomplete>

Forms.checkbox

Server-rendered Open docs

Renders a checkbox control with optional inline label content.

  <.checkbox id="terms" name="terms">Accept terms</.checkbox>

Forms.field

Server-rendered Open docs

Field wrapper for label, control, description, and errors.

Shown in your profile.

  <.field>
  <:label for="name">Name</:label>
  <.input id="name" name="name" />
  <:description>Shown in your profile.</:description>
</.field>

Forms.field_control

Server-rendered Open docs

Wraps the main interactive control inside a field.

  <.field_control>
  <.input id="workspace_slug" value="cinder-ui" />
</.field_control>

Forms.field_description

Server-rendered Open docs

Helper text shown beneath a field control.

Used in your public workspace URL.

  <.field_description>Used in your public workspace URL.</.field_description>

Forms.field_error

Server-rendered Open docs

Error or validation message shown beneath a field control.

Please use your company domain.

  <.field_error>Please use your company domain.</.field_error>

Forms.field_label

Server-rendered Open docs

Wraps field labels so shared spacing and invalid-state styling remain consistent across controls. Inside field/1, provide it via the :label slot when you need richer label content than a single label/1.

Used across the dashboard.
  <.field_label>
  <.label for="workspace_name">Workspace name</.label>
  <span class="text-muted-foreground text-xs">Used across the dashboard.</span>
</.field_label>

Forms.field_message

Server-rendered Open docs

Neutral status or informational message shown beneath a field control.

Visible immediately after save.

  <.field_message>Visible immediately after save.</.field_message>

Forms.input

Server-rendered Open docs

Renders an input with shadcn classes.

  <.input id="email" type="email" placeholder="name@example.com" />

Forms.input_group

Server-rendered Open docs

Wraps an input and sibling controls (buttons/icons) in a single inline group.

  <.input_group>
  <.input placeholder="Search" />
  <.input_group_addon>
    <.input_group_button variant={:secondary}>Go</.input_group_button>
  </.input_group_addon>
</.input_group>

Forms.input_group_addon

Server-rendered Open docs

Text/icon/status/action segment used inside input_group/1.

  <.input_group>
  <.input_group_addon>
    <.icon name="mail" class="size-4" />
  </.input_group_addon>
  <.input type="email" placeholder="team@example.com" />
</.input_group>

Forms.input_group_button

Server-rendered Open docs

Compact action button for use inside input_group_addon/1.

  <.input_group>
  <.input placeholder="Search" />
  <.input_group_addon>
    <.input_group_button>Search</.input_group_button>
  </.input_group_addon>
</.input_group>

Forms.input_group_text

Server-rendered Open docs

Styled text segment for use inside input_group_addon/1.

USD
  <.input_group>
  <.input placeholder="Amount" />
  <.input_group_addon>
    <.input_group_text>USD</.input_group_text>
  </.input_group_addon>
</.input_group>

Forms.input_otp

Progressive Open docs

Renders an OTP-style segmented input layout.

  <.input_otp name="verification_code[]" length={6} />

Forms.label

Server-rendered Open docs

Renders a form label.

  <.label for="email">Email</.label>

Forms.native_select

Server-rendered Open docs

Renders a native <select> element with shadcn styles.

  <.native_select name="framework" value="phoenix">
  <:option value="phoenix" label="Phoenix" />
  <:option value="rails" label="Rails" />
  <:option value="laravel" label="Laravel" />
</.native_select>

Forms.number_field

Server-rendered Open docs

Renders a number input with increment and decrement controls.

  <.number_field id="seat-count" name="seats" value={3} min={1} max={10} />

Forms.radio_group

Server-rendered Open docs

Renders a radio group with native radio inputs.

  <.radio_group name="plan" value="pro">
  <:option value="free" label="Free" />
  <:option value="pro" label="Pro" />
</.radio_group>

Forms.select

Progressive Open docs

Renders a custom select with a button trigger and listbox content.

  <.select id="team-plan" name="plan" value="pro">
  <:option value="free" label="Free" />
  <:option value="pro" label="Pro" />
  <:option value="enterprise" label="Enterprise" />
</.select>

Forms.slider

Server-rendered Open docs

Renders a slider using native range input(s).

  <.slider id="volume" name="volume" value={45} min={0} max={100} step={1} />

Forms.switch

Server-rendered Open docs

Renders a switch control with optional label content.

  <.switch id="marketing" checked={true}>Email updates</.switch>

Forms.textarea

Server-rendered Open docs

Renders a textarea with shadcn classes.

  <.textarea id="bio" name="bio" rows={4} />

FieldFamily.field_content

Server-rendered Open docs

Groups field copy beside an inline control.

Show deployment alerts on this device.

  <.field_control class="flex items-start gap-3">
  <.checkbox id="desktop-alerts" name="alerts[desktop]" />
  <.field_content>
    <.field_label>
      <.label for="desktop-alerts">Desktop alerts</.label>
    </.field_label>
    <.field_description>Show deployment alerts on this device.</.field_description>
  </.field_content>
</.field_control>

FieldFamily.field_group

Server-rendered Open docs

Stacks related fields with consistent spacing.

Notification preferences

Choose how Cinder UI should notify your team.

Release and rollback notifications.

Send a digest every Monday morning.

  <.field_set>
  <.field_legend>Notification preferences</.field_legend>
  <.field_description>Choose how Cinder UI should notify your team.</.field_description>

  <.field_group>
    <.field>
      <:label for="deployments">Deployments</:label>
      <.input id="deployments" name="notifications[deployments]" value="email" />
      <:description>Release and rollback notifications.</:description>
    </.field>

    <.field_separator />

    <.field_control class="flex items-start gap-3">
      <.checkbox id="weekly-summary" name="notifications[weekly_summary]" />
      <.field_content>
        <.field_label>
          <.label for="weekly-summary">Weekly summary</.label>
        </.field_label>
        <.field_description>Send a digest every Monday morning.</.field_description>
      </.field_content>
    </.field_control>
  </.field_group>
</.field_set>

FieldFamily.field_legend

Server-rendered Open docs

Legend for a field_set/1.

Delivery method
  <.field_legend>Delivery method</.field_legend>

FieldFamily.field_set

Server-rendered Open docs

Semantic fieldset wrapper for grouping related controls.

Billing address

Used for invoices and payment receipts.

  <.field_set>
  <.field_legend>Billing address</.field_legend>
  <.field_description>Used for invoices and payment receipts.</.field_description>
  <.field_group>
    <.field>
      <:label for="billing_city">City</:label>
      <.input id="billing_city" name="billing[city]" />
    </.field>
  </.field_group>
</.field_set>

FieldFamily.field_title

Server-rendered Open docs

Label-styled title text for custom field content.

Virtual machine

Run workloads on a dedicated host.

  <.field_content>
  <.field_title>Virtual machine</.field_title>
  <.field_description>Run workloads on a dedicated host.</.field_description>
</.field_content>

Layout

Layout.aspect_ratio

Server-rendered Open docs

Maintains a fixed aspect ratio for content.

  <.aspect_ratio ratio="16 / 9">
  <img src="https://picsum.photos/id/191/800/800" class="h-full w-full object-cover" />
</.aspect_ratio>

Layout.card

Server-rendered Open docs

Card container.

Project status
Active deployments across environments.

Production healthy, staging pending one migration.

  <.card>
  <.card_header>
    <.card_title>Project status</.card_title>
    <.card_description>Active deployments across environments.</.card_description>
  </.card_header>
  <.card_content>
    <p class="text-sm">Production healthy, staging pending one migration.</p>
  </.card_content>
</.card>

Layout.card_action

Server-rendered Open docs

Right-aligned card action region for buttons/chips.

Project details
Manage metadata and ownership.
  <.card class="max-w-sm">
  <.card_header>
    <.card_title>Project details</.card_title>
    <.card_action>
      <.button size={:sm} variant={:ghost}>Edit</.button>
    </.card_action>
    <.card_description>Manage metadata and ownership.</.card_description>
  </.card_header>
</.card>

Layout.card_content

Server-rendered Open docs

Card content section.

API key
Use this key for network requests.

Your API key was generated successfully.

  <.card class="max-w-md">
  <.card_header>
    <.card_title>API key</.card_title>
    <.card_description>Use this key for network requests.</.card_description>
  </.card_header>
  <.card_content class="space-y-3">
    <p class="text-sm">Your API key was generated successfully.</p>
    <.input_group>
      <.input value="ck_live_************************" readonly />
      <.input_group_addon>
        <.input_group_button variant={:outline}>Copy</.input_group_button>
      </.input_group_addon>
    </.input_group>
  </.card_content>
</.card>

Layout.card_description

Server-rendered Open docs

Card description text.

Billing setup
Connect your billing details to unlock premium features.
  <.card class="max-w-sm">
  <.card_header>
    <.card_title>Billing setup</.card_title>
    <.card_description>
      Connect your billing details to unlock premium features.
    </.card_description>
  </.card_header>
</.card>

Layout.card_header

Server-rendered Open docs

Card header section.

Billing
Usage and invoices for this workspace.

Current cycle usage: 72%.

  <.card class="max-w-md">
  <.card_header class="border-b">
    <.card_title>Billing</.card_title>
    <.card_action>
      <.button size={:sm} variant={:outline}>Manage</.button>
    </.card_action>
    <.card_description>Usage and invoices for this workspace.</.card_description>
  </.card_header>
  <.card_content>
    <p class="text-sm">Current cycle usage: 72%.</p>
  </.card_content>
</.card>

Layout.card_title

Server-rendered Open docs

Card title text.

Payment method

Visa ending in 4242.

  <.card class="max-w-sm">
  <.card_header>
    <.card_title>Payment method</.card_title>
  </.card_header>
  <.card_content>
    <p class="text-sm">Visa ending in 4242.</p>
  </.card_content>
</.card>

Layout.kbd

Server-rendered Open docs

Keyboard key badge.

⌘K
  <.kbd>⌘K</.kbd>

Layout.kbd_group

Server-rendered Open docs

Groups multiple kbd/1 entries.

P
  <.kbd_group>
  <.kbd></.kbd>
  <.kbd></.kbd>
  <.kbd>P</.kbd>
</.kbd_group>

Layout.panel

Server-rendered Open docs

A bordered surface with card-like styling but no inner padding or gap, for flexible layouts where the caller controls spacing.

Notifications

  • New deployment completed
  • Invite accepted by teammate
  <.panel class="max-w-md">
  <div class="p-4 border-b">
    <h3 class="text-sm font-medium">Notifications</h3>
  </div>
  <ul class="divide-y">
    <li class="px-4 py-3 text-sm">New deployment completed</li>
    <li class="px-4 py-3 text-sm">Invite accepted by teammate</li>
  </ul>
</.panel>

Layout.resizable

Progressive Open docs

Resizable split layout container with optional client-side persistence.

Panel A
Panel B
  <.resizable id="resizable-1">
  <:panel size={35}>
    <div class="rounded-md bg-muted p-2 text-xs">Panel A</div>
  </:panel>
  <:panel size={65}>
    <div class="rounded-md bg-muted/60 p-2 text-xs">Panel B</div>
  </:panel>
</.resizable>

Layout.scroll_area

Server-rendered Open docs

Overflow container that mirrors shadcn scroll-area structure.

Scrollable content
Scrollable content
Scrollable content
Scrollable content
Scrollable content
  <.scroll_area class="h-24 rounded-md border">
  <div class="space-y-2 text-sm p-4">
    <div>Scrollable content</div>
    <div>Scrollable content</div>
    <div>Scrollable content</div>
    <div>Scrollable content</div>
    <div>Scrollable content</div>
  </div>
</.scroll_area>

Layout.separator

Server-rendered Open docs

Horizontal or vertical separator.

Overview

Details

  <div class="space-y-3">
  <p class="text-sm">Overview</p>
  <.separator />
  <p class="text-sm">Details</p>
</div>

Layout.skeleton

Server-rendered Open docs

Animated skeleton placeholder.

  <.skeleton class="h-4 w-[220px]" />

Icons

Icons.icon

Server-rendered Open docs

Renders a Lucide icon by name.

  <.icon name="chevron-down" class="size-4 text-muted-foreground" aria-hidden="true" />

Feedback

Feedback.alert

Server-rendered Open docs

Renders an alert container.

Default

Destructive

Success

Warning

Info

  <div class="space-y-4">
  <div>
    <h4 class="text-sm font-medium mb-2">Default</h4>
    <.alert>
      <.icon name="circle-alert" />
      <:title>Heads up!</:title>
      <:description>
        You can add components to your app using the install task.
      </:description>
    </.alert>
  </div>

  <div>
    <h4 class="text-sm font-medium mb-2">Destructive</h4>
    <.alert variant={:destructive}>
      <.icon name="triangle-alert" />
      <:title>Unable to deploy</:title>
      <:description>
        Your build failed. Check logs and try again.
      </:description>
    </.alert>
  </div>

  <div>
    <h4 class="text-sm font-medium mb-2">Success</h4>
    <.alert variant={:success}>
      <.icon name="circle-check-big" />
      <:title>Changes saved</:title>
      <:description>
        Your updates have been successfully saved to the server.
      </:description>
    </.alert>
  </div>

  <div>
    <h4 class="text-sm font-medium mb-2">Warning</h4>
    <.alert variant={:warning}>
      <.icon name="triangle-alert" />
      <:title>Deprecated API</:title>
      <:description>
        This endpoint will be removed in the next major version.
      </:description>
    </.alert>
  </div>

  <div>
    <h4 class="text-sm font-medium mb-2">Info</h4>
    <.alert variant={:info}>
      <.icon name="info" />
      <:title>FYI</:title>
      <:description>
        Additional information to help you understand the current situation.
      </:description>
    </.alert>
  </div>
</div>

Feedback.badge

Server-rendered Open docs

Renders a status badge.

New
  <.badge>New</.badge>

Feedback.empty_state

Server-rendered Open docs

Empty-state block for no-data screens.

No projects

Create your first project to get started.

  <.empty_state>
  <:title>No projects</:title>
  <:description>Create your first project to get started.</:description>
</.empty_state>

Feedback.flash

Server-rendered Open docs

Renders a flash notice.

  <.flash kind={:info}>Settings saved.</.flash>

Feedback.flash_group

Server-rendered Open docs

Shows the flash group with standard titles and content.

  <.flash_group flash={%{"info" =>> "Saved", "error" => "Unable to complete request"}} />

Feedback.progress

Server-rendered Open docs

Progress bar.

Deploy progress 72%
  <div class="space-y-2">
  <div class="flex items-center justify-between text-sm">
    <span>Deploy progress</span>
    <span>72%</span>
  </div>
  <.progress value={72} />
</div>

Feedback.spinner

Server-rendered Open docs

Generic loading spinner.

Syncing changes
  <div class="inline-flex items-center gap-2 text-sm text-muted-foreground">
  <.spinner />
  Syncing changes
</div>

Data Display

DataDisplay.accordion

Server-rendered Open docs

Accordion with multiple items.

What is CinderUI?
A Phoenix-first component library modeled after shadcn/ui patterns.
Does it require JavaScript?
Core interactions use semantic HTML first, with optional hooks for enhancement.
  <.accordion>
  <:item title="What is CinderUI?" open={true}>
    A Phoenix-first component library modeled after shadcn/ui patterns.
  </:item>
  <:item title="Does it require JavaScript?">
    Core interactions use semantic HTML first, with optional hooks for enhancement.
  </:item>
</.accordion>

DataDisplay.avatar

Server-rendered Open docs

Renders a circular avatar with optional image and fallback.

Levi
  <.avatar src="example.png" alt="Levi" fallback="LV" />

DataDisplay.avatar_group

Server-rendered Open docs

Groups avatars with overlap.

Levi
Mira
Shadcn
+2
  <.avatar_group>
  <.avatar src="example.png" alt="Levi" />
  <.avatar src="example.png" alt="Mira" />
  <.avatar src="example.png" alt="Shadcn" />
  <.avatar_group_count>+2</.avatar_group_count>
</.avatar_group>

DataDisplay.avatar_group_count

Server-rendered Open docs

Counter item for avatar groups (e.g. +3).

LB
MJ
+3
  <.avatar_group>
  <.avatar alt="Levi Buzolic" />
  <.avatar alt="Mira Jones" />
  <.avatar_group_count size={:sm}>+3</.avatar_group_count>
</.avatar_group>

DataDisplay.code_block

Progressive Open docs

Monospaced code block wrapper.


    mix cinder_ui.docs.build
  
  <.code_block>
  mix cinder_ui.docs.build
</.code_block>

DataDisplay.collapsible

Server-rendered Open docs

Generic collapsible section with trigger/content slots.

Release notes
Added generated attr tables and improved examples.
  <.collapsible open={true}>
  <:trigger>
    Release notes
  </:trigger>
  Added generated attr tables and improved examples.
</.collapsible>

DataDisplay.table

Server-rendered Open docs

Table wrapper with overflow container.

Active deployments across environments.
Service Status Latency
API Healthy 82ms
Worker Degraded 164ms
  <.table>
  <.table_caption>Active deployments across environments.</.table_caption>
  <.table_header>
    <.table_row>
      <.table_head>Service</.table_head>
      <.table_head>Status</.table_head>
      <.table_head class="text-right">Latency</.table_head>
    </.table_row>
  </.table_header>
  <.table_body>
    <.table_row>
      <.table_cell>API</.table_cell>
      <.table_cell>Healthy</.table_cell>
      <.table_cell class="text-right">82ms</.table_cell>
    </.table_row>
    <.table_row>
      <.table_cell>Worker</.table_cell>
      <.table_cell>Degraded</.table_cell>
      <.table_cell class="text-right">164ms</.table_cell>
    </.table_row>
  </.table_body>
</.table>

DataDisplay.table_body

Server-rendered Open docs

Table body (tbody).

API Healthy
  <.table>
  <.table_body>
    <.table_row>
      <.table_cell>API</.table_cell>
      <.table_cell>Healthy</.table_cell>
    </.table_row>
  </.table_body>
</.table>

DataDisplay.table_caption

Server-rendered Open docs

Table caption (caption).

Recent invoices
  <.table>
  <.table_caption>Recent invoices</.table_caption>
</.table>

DataDisplay.table_cell

Server-rendered Open docs

Table data cell (td).

$48.00
  <.table>
  <.table_body>
    <.table_row>
      <.table_cell>$48.00</.table_cell>
    </.table_row>
  </.table_body>
</.table>

DataDisplay.table_head

Server-rendered Open docs

Table heading cell (th).

Amount
  <.table>
  <.table_header>
    <.table_row>
      <.table_head class="text-right">Amount</.table_head>
    </.table_row>
  </.table_header>
</.table>

DataDisplay.table_header

Server-rendered Open docs

Table header (thead).

Name Status
  <.table>
  <.table_header>
    <.table_row>
      <.table_head>Name</.table_head>
      <.table_head>Status</.table_head>
    </.table_row>
  </.table_header>
</.table>

DataDisplay.table_row

Server-rendered Open docs

Table row (tr).

INV-002 Pending
  <.table>
  <.table_body>
    <.table_row state="selected">
      <.table_cell>INV-002</.table_cell>
      <.table_cell>Pending</.table_cell>
    </.table_row>
  </.table_body>
</.table>

Overlay

Overlay.alert_dialog

Progressive Open docs

Destructive-style dialog variant used for irreversible confirmation actions.

  <.alert_dialog id="delete-dialog">
  <:trigger><.button variant={:destructive}>Delete project</.button></:trigger>
  <:title>Delete project?</:title>
  <:description>This action is irreversible.</:description>
  All deployments and analytics will be removed.
  <:footer>
    <.button variant={:outline} type="button">Cancel</.button>
    <.button variant={:destructive} type="button">Delete</.button>
  </:footer>
</.alert_dialog>

Overlay.dialog

Progressive Open docs

Modal dialog with trigger/content slots.

  <.dialog id="delete-project-dialog">
  <:trigger>
    <.button variant={:destructive}>Delete project</.button>
  </:trigger>
  <:title>Delete project?</:title>
  <:description>This action cannot be undone.</:description>
  Are you sure you want to permanently remove this project?
  <:footer>
    <.button variant={:outline} type="button">Cancel</.button>
    <.button variant={:destructive} type="button">Delete</.button>
  </:footer>
</.dialog>

Overlay.drawer

Progressive Open docs

Drawer panel component.

  <.drawer id="mobile-filters">
  <:trigger><.button variant={:outline}>Filters</.button></:trigger>
  <:title>Filter results</:title>
  <:description>Refine issues by status and owner.</:description>
  <div class="space-y-2 text-sm">
    <p>Status: Open</p>
    <p>Owner: Platform</p>
  </div>
</.drawer>

Overlay.dropdown_menu

Progressive Open docs

Dropdown menu structure.

  <.dropdown_menu id="project-actions">
  <:trigger><.button variant={:outline}>Actions</.button></:trigger>
  <:item href="/projects/1">Open project</:item>
  <:item>Rename</:item>
  <:item disabled={true}>Archive</:item>
</.dropdown_menu>

Overlay.hover_card

Server-rendered Open docs

Hover card with trigger and content slots.

Levi Buzolic
  <.hover_card>
  <:trigger><span class="text-sm underline">Levi Buzolic</span></:trigger>
  <:content>
    <div class="space-y-1 text-sm">
      <p class="font-medium">Levi Buzolic</p>
      <p class="text-muted-foreground">Maintains docs and releases.</p>
    </div>
  </:content>
</.hover_card>

Overlay.menubar

Progressive Open docs

Menubar scaffold with dropdown-like triggers.

  <.menubar>
  <:menu label="File">
    <button type="button" class="flex w-full rounded-sm px-2 py-1.5 text-sm hover:bg-accent">
      New project
    </button>
  </:menu>
  <:menu label="View">
    <button type="button" class="flex w-full rounded-sm px-2 py-1.5 text-sm hover:bg-accent">
      Toggle sidebar
    </button>
  </:menu>
</.menubar>

Overlay.popover

Progressive Open docs

Popover with trigger and content slots.

  <.popover id="share-popover">
  <:trigger><.button variant={:outline}>Share</.button></:trigger>
  <:content>
    <div class="space-y-2 text-sm">
      <p>Invite collaborators to this workspace.</p>
      <.button size={:sm}>Copy link</.button>
    </div>
  </:content>
</.popover>

Overlay.sheet

Progressive Open docs

Sheet panel component for side or edge-mounted overlays.

  <.sheet id="settings-sheet">
  <:trigger><.button variant={:outline}>Open settings</.button></:trigger>
  <:title>Workspace settings</:title>
  <:description>Manage defaults for the current workspace.</:description>
  <div class="space-y-2 text-sm">
    <p>Theme: System</p>
    <p>Notifications: Enabled</p>
  </div>
</.sheet>

Overlay.tooltip

Server-rendered Open docs

Tooltip helper with hover/focus behavior.

  <.tooltip text="Copy API key">
  <.button size={:icon} variant={:outline} aria-label="Copy">C</.button>
</.tooltip>

Advanced

Advanced.chart

Scaffold Open docs

Chart frame component for wrapping chart libraries with shadcn tokens.

Traffic

Requests over the last 7 days.

  <.chart>
  <:title>Traffic</:title>
  <:description>Requests over the last 7 days.</:description>
  <div class="h-40 rounded-md bg-muted/60"></div>
</.chart>

Advanced.combobox

Progressive Open docs

Combobox scaffold using an input and option list.

  <.combobox id="plan" value="Pro">
  <:option value="Free" label="Free" />
  <:option value="Pro" label="Pro" />
</.combobox>

Advanced.command

Server-rendered Open docs

Command palette layout.

General
Profile
Billing
Workspace
Settings
  <.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>

Advanced.item

Server-rendered Open docs

Command/list item.

General
Profile
  <.command>
  <:group heading="General">
    <.item value="profile">Profile</.item>
  </:group>
</.command>

Advanced.sidebar

Progressive Open docs

Sidebar panel region.

  <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>

Advanced.sidebar_group

Server-rendered Open docs

Sidebar group wrapper.

  <.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>

Advanced.sidebar_header

Server-rendered Open docs

Sidebar header container.

  <.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>

Advanced.sidebar_item

Server-rendered Open docs

Sidebar navigation item.

  <.sidebar_group label="Navigation">
  <.sidebar_item icon="home" current={true}>Overview</.sidebar_item>
  <.sidebar_item icon="inbox">Inbox</.sidebar_item>
</.sidebar_group>

Advanced.sidebar_layout

Progressive Open docs

Phoenix-first sidebar shell for app layouts.

Release readiness

2 items need review before ship.

Current focus

Ship the refreshed component docs and tighten visual regression coverage.

This week

Sidebar primitives, docs examples, and browser-driven QA.

  <.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>

Advanced.sidebar_main

Server-rendered Open docs

Sidebar sibling content region.

Content area
Use the lower-level helper when you want manual control over the main region wrapper.
  <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>

Advanced.sidebar_profile_menu

Server-rendered Open docs

Profile/account menu pattern for sidebar footers.

  <.sidebar_layout id="sidebar-profile-menu-shell" full_screen={false}>
  <:header>
    <.sidebar_header>
      <span data-sidebar-label class="text-sm font-semibold">Workspace tools</span>
    </.sidebar_header>
  </:header>
  <:sidebar>
    <.sidebar_group label="Navigation">
      <.sidebar_item icon="settings">Settings</.sidebar_item>
      <.sidebar_item icon="circle-help">Get help</.sidebar_item>
      <.sidebar_item icon="search">Search</.sidebar_item>
    </.sidebar_group>
    <.sidebar_group label="Shortcuts">
      <.sidebar_item icon="command">Command palette</.sidebar_item>
      <.sidebar_item icon="bell">Notifications</.sidebar_item>
    </.sidebar_group>
  </:sidebar>
  <:footer>
    <.sidebar_footer>
      <.sidebar_profile_menu
        id="sidebar-profile-menu-example"
        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="rounded border bg-card p-4 text-sm">Inset</div></:main>
</.sidebar_layout>

Advanced.sidebar_trigger

Server-rendered Open docs

Button that toggles the surrounding sidebar_layout/1 between expanded and collapsed.

  <.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>

Typography

Typography.typography

Server-rendered Open docs

Shadcn-inspired typography recipe for semantic headings and text treatments.

Realtime payments need boring interfaces

Operators need clear hierarchy, calm defaults, and text that survives dense workflows.

Use typography recipes when component copy needs consistent rhythm without introducing a rich text renderer or client-side dependency.

  <div class="max-w-2xl">
  <.typography variant={:h1}>Realtime payments need boring interfaces</.typography>
  <.typography variant={:lead} class="mt-4">
    Operators need clear hierarchy, calm defaults, and text that survives dense workflows.
  </.typography>
  <.typography>
    Use typography recipes when component copy needs consistent rhythm without introducing
    a rich text renderer or client-side dependency.
  </.typography>
</div>