Layout and structural primitives inspired by shadcn/ui.
Included:
- Card family (
card/1,card_header/1,card_title/1,card_description/1,card_action/1,card_content/1,card_footer/1) panel/1separator/1skeleton/1aspect_ratio/1kbd/1kbd_group/1scroll_area/1resizable/1(in progress, not ready for use)
Summary
Functions
Maintains a fixed aspect ratio for content.
Card container.
Right-aligned card action region for buttons/chips.
Card content section.
Card description text.
Card footer section.
Card header section.
Card title text.
Keyboard key badge.
Groups multiple kbd/1 entries.
A bordered surface with card-like styling but no inner padding or gap, for flexible layouts where the caller controls spacing.
Resizable split layout container with optional client-side persistence.
Overflow container that mirrors shadcn scroll-area structure.
Horizontal or vertical separator.
Animated skeleton placeholder.
Functions
Maintains a fixed aspect ratio for content.
Example
<.aspect_ratio ratio="16 / 9">
<img src="https://picsum.photos/id/191/800/800" class="h-full w-full object-cover" />
</.aspect_ratio>Screenshot

View live examples and full component docs.
Attributes
ratio(:string) - Defaults to"16 / 9".class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Card container.
Examples
heex title="Project status" <.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>
heex title="Team invite" vrt <.card class="max-w-md"> <.card_header class="border-b"> <.card_title>Team invite</.card_title> <.card_action> <.button size={:sm} variant={:outline}>Skip</.button> </.card_action> <.card_description>Invite teammates before launch.</.card_description> </.card_header> <.card_content class="space-y-3"> <.field> <:label for="invite_email">Email</:label> <.input id="invite_email" type="email" placeholder="dev@company.com" /> </.field> </.card_content> <.card_footer class="justify-end gap-2 border-t"> <.button variant={:outline}>Cancel</.button> <.button>Send invite</.button> </.card_footer> </.card>
Minimal
<.card>
<.card_header>
<.card_title>Settings</.card_title>
</.card_header>
<.card_content>...</.card_content>
</.card>Screenshot

View live examples and full component docs.
Attributes
class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Right-aligned card action region for buttons/chips.
Example
heex title="Header action slot" align="full" <.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>
## Screenshot

View live examples and full component docs.
## Attributes
class (:string) - Defaults to nil.
Global attributes are accepted.
## Slots
* inner_block (required)
Card content section.
Example
heex title="Card content body" align="full" <.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>
## Screenshot

View live examples and full component docs.
## Attributes
class (:string) - Defaults to nil.
Global attributes are accepted.
## Slots
* inner_block (required)
Card description text.
Examples
heex title="Standard description" align="full" <.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>
heex title="Muted timestamp description" align="full" <.card class="max-w-sm"> <.card_header> <.card_title>System status</.card_title> <.card_description class="text-xs">Last updated 5 minutes ago.</.card_description> </.card_header> </.card>
Screenshot

View live examples and full component docs.
Attributes
class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Card header section.
Example
heex title="Card header with action" align="full" <.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>
## Screenshot

View live examples and full component docs.
## Attributes
class (:string) - Defaults to nil.
Global attributes are accepted.
## Slots
* inner_block (required)
Card title text.
Examples
heex title="Basic title" align="full" <.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>
heex title="Custom title size" align="full" <.card class="max-w-sm"> <.card_header> <.card_title class="text-xl">Pro plan</.card_title> <.card_description>Renews on the 1st of each month.</.card_description> </.card_header> </.card>
Screenshot

View live examples and full component docs.
Attributes
class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Keyboard key badge.
Examples
heex title="Single shortcut key" <.kbd>⌘K</.kbd>
heex title="Shortcut combination" <.kbd_group> <.kbd>⌘</.kbd> <.kbd>K</.kbd> </.kbd_group>
Screenshot

View live examples and full component docs.
Attributes
class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Groups multiple kbd/1 entries.
Example
heex title="Key group" <.kbd_group> <.kbd>⌘</.kbd> <.kbd>⇧</.kbd> <.kbd>P</.kbd> </.kbd_group>
## Screenshot

View live examples and full component docs.
## Attributes
class (:string) - Defaults to nil.
Global attributes are accepted.
## Slots
* inner_block (required)
A bordered surface with card-like styling but no inner padding or gap, for flexible layouts where the caller controls spacing.
Example
heex title="Panel with custom content" <.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>
## Screenshot

View live examples and full component docs.
## Attributes
class (:string) - Defaults to nil.
Global attributes are accepted.
## Slots
* inner_block (required)
Resizable split layout container with optional client-side persistence.
Current Scope
resizable/1currently supports adjacent panel resizing, keyboard handle controls, optional visible handles, andlocalStoragepersistence. It does not yet include collapsed panels, imperative panel APIs, or the richer nested-group ergonomics of a full panel system.
Uses the optional CuiResizable LiveView hook to support drag handles.
Provide storage_key to persist panel percentages in localStorage.
Example
heex title="Default" align="full" <.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>
heex title="Vertical" align="full" vrt <.resizable id="resizable-2" direction={:vertical} class="h-[240px]"> <:panel size={45}> <div class="h-full rounded-md bg-muted p-2 text-xs">Top panel</div> </:panel> <:panel size={55}> <div class="h-full rounded-md bg-muted/60 p-2 text-xs">Bottom panel</div> </:panel> </.resizable>
heex title="Handle + persisted sizes" align="full" vrt <.resizable id="resizable-3" with_handle storage_key="docs-layout-main"> <:panel size={30} min_size={20}> <div class="rounded-md bg-muted p-2 text-xs">Explorer</div> </:panel> <:panel size={70} min_size={30}> <div class="rounded-md bg-muted/60 p-2 text-xs">Editor</div> </:panel> </.resizable>
## Screenshot

View live examples and full component docs.
## Attributes
direction (:atom) - Defaults to :horizontal. Must be one of :horizontal, or :vertical.
with_handle (:boolean) - Defaults to false.
storage_key (:string) - Defaults to nil.
id (:string) - Defaults to nil.
class (:string) - Defaults to nil.
Global attributes are accepted.
## Slots
* panel (required) - Accepts attributes:
size (:integer)
min_size (:integer)
* class (:string)
Overflow container that mirrors shadcn scroll-area structure.
Example
heex title="Scrollable container" align="full" <.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>
## Screenshot

View live examples and full component docs.
## Attributes
class (:string) - Defaults to nil.
viewport_class (:string) - Defaults to nil.
* Global attributes are accepted.
## Slots
* inner_block (required)
Horizontal or vertical separator.
Example
heex title="Horizontal separator" align="full" <div class="space-y-3"> <p class="text-sm">Overview</p> <.separator /> <p class="text-sm">Details</p> </div>
## Screenshot

View live examples and full component docs.
## Attributes
orientation (:atom) - Defaults to :horizontal. Must be one of :horizontal, or :vertical.
decorative (:boolean) - Defaults to true.
class (:string) - Defaults to nil.
Global attributes are accepted.
Animated skeleton placeholder.
Examples
heex title="Single line placeholder" <.skeleton class="h-4 w-[220px]" />
heex title="Avatar + text row" align="full" <div class="flex items-center gap-3"> <.skeleton class="size-10 rounded-full" /> <div class="space-y-2"> <.skeleton class="h-4 w-[180px]" /> <.skeleton class="h-4 w-[120px]" /> </div> </div>
heex title="Card loading state" align="full" vrt <.card class="max-w-sm"> <.card_header> <.skeleton class="h-5 w-[140px]" /> <.skeleton class="h-4 w-[220px]" /> </.card_header> <.card_content class="space-y-2"> <.skeleton class="h-4 w-full" /> <.skeleton class="h-4 w-[90%]" /> <.skeleton class="h-4 w-[75%]" /> </.card_content> </.card>
## Screenshot

View live examples and full component docs.
## Attributes
class (:string) - Defaults to nil.
Global attributes are accepted.
