Data display
Tables & lists
Table, description list, resource list and flat list rows.
Table
The presentational family data_table composes — use it directly
for simple, non-Flop tables.
Basic
table_head / table_body / table_row with :col and :cell slots; selected highlights a row.
| Name | Role | Commits |
|---|---|---|
| Ada Lovelace | Analyst | 1,842 |
| Grace Hopper | Rear Admiral | 2,214 |
<.table>
<.table_head>
<:col>Name</:col>
<:col>Role</:col>
<:col class="lui-th-num">Commits</:col>
</.table_head>
<.table_body>
<.table_row>
<:cell>Ada Lovelace</:cell>
<:cell>Analyst</:cell>
<:cell class="lui-td-num">1,842</:cell>
</.table_row>
<.table_row selected>
<:cell>Grace Hopper</:cell>
<:cell>Rear Admiral</:cell>
<:cell class="lui-td-num">2,214</:cell>
</.table_row>
</.table_body>
</.table>
API reference
Props and slots, introspected from the component.
table/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the root element. |
| Slots | |||
:inner_block* |
table_head and table_body children. | ||
table_head/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the root element. |
| Slots | |||
:col |
Header cell content for one column. | ||
:inner_block |
Optional raw thead row content after :col cells. | ||
table_body/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the root element. |
| Slots | |||
:inner_block* |
table_row children. | ||
table_row/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the root element. |
selected |
boolean |
false |
Highlight the row as selected. |
| Slots | |||
:cell |
One body cell in column order. | ||
:inner_block |
Optional raw row content after :cell cells. | ||
Description list
Label/value pairs for a record's detail view. layout="stacked"
(default) puts the label above the value; inline puts it
alongside; layout="dense" is the inspector-rail grid.
Stacked
columns sets how many pairs sit side by side on a wide viewport.
- Created
- Jan 4, 2026
- Host
- Alex Smith
- Description
- Long free text…
<.description_list>
<:item label="Created">Jan 4, 2026</:item>
<:item label="Host">Alex Smith</:item>
<:item label="Description" wide>Long free text…</:item>
</.description_list>
Dense (inspector rail)
layout="dense" is the label-column + value grid used inside inspector.
- Repo
- enventory_new
- Status
- in_progress
- Tags
- ui
<.description_list layout="dense">
<:item label="Repo">enventory_new</:item>
<:item label="Status">in_progress</:item>
<:item label="Tags"><.badge size="sm">ui</.badge></:item>
</.description_list>
API reference
Props and slots, introspected from the component.
| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the root element. |
columns |
1 | 2 | 3 |
2 |
Pairs per row on wide viewports. |
layout |
stacked | inline | dense |
"stacked" |
`stacked` puts the label above the value; `inline` puts it alongside; `dense` is the inspector rail. |
| Slots | |||
:item* |
One label/value pair. | ||
Resource list
Use list rows for compact indexes or grid cards for resource overviews. Linked rows make the whole row the hit target.
List
Subtitle, leading content, and trailing metadata compose a linked resource row.
-
Atlas atlas
-
Beacon beacon
<.resource_list layout={:list}><.resource_list_item navigate="/projects/atlas" title="Atlas" subtitle="atlas"><.badge>Healthy</.badge></.resource_list_item></.resource_list>
Grid
The same item contract becomes cards with layout={:grid}.
-
Atlas atlas
-
Beacon beacon
<.resource_list layout={:grid}><.resource_list_item title="Atlas" subtitle="atlas">3 apps</.resource_list_item></.resource_list>
API reference
Props and slots, introspected from the component.
resource_list/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the root element. |
layout |
list | grid |
:list |
List (full-width rows) or grid (card layout). Rendered as data-layout. |
| Slots | |||
:inner_block* |
One or more `resource_list_item/1` children. | ||
resource_list_item/1| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the item root. |
href |
string |
nil |
External or full-page href; whole row is a link. |
navigate |
string |
nil |
LiveView navigate target; whole row is a link. |
patch |
string |
nil |
LiveView patch target; whole row is a link. |
subtitle |
string |
nil |
Optional secondary line (e.g. a slug). Class only; face is CSS-owned. |
subtitle_mono |
boolean |
false |
Render the subtitle in the mono face. Set it when the subtitle is a value the SYSTEM produced (a slug, a domain, a bucket name) rather than language a human wrote. Surveying the six index pages this component targets, five carry a machine value there, so an opt-in beats every call site reaching for an override class. |
title* |
string |
— |
Primary line (resource name). |
| Slots | |||
:inner_block |
Trailing meta (badges, counts). | ||
List row
Dense issue/inbox row: leading glyph, muted mono id, truncating title,
meta, trailing. Lists stay flat — one scroll area, one
status_glyph column per row, rows ordered by status then
recency. Whatever a group header would have said (status name, count)
lives on each row or in the filter chips above the list, with counts.
Put data-lantern-list-nav on the list and
data-lantern-list-item on each row for j/k keyboard nav.
Flat list with status
Filter chips carry the status names and counts; every row carries its own status glyph. Focus the list, then j/k or arrows move the ring. Enter follows the row link.
<div class="docs-row">
<.badge size="sm">All (3)</.badge>
<.badge size="sm">In progress (1)</.badge>
<.badge size="sm">To do (1)</.badge>
<.badge size="sm">Done (1)</.badge>
</div>
<.scroll_area label="Tickets" data-lantern-list-nav>
<.list_row
identifier="#241"
title="Visible progress ring"
parent="Dense primitives"
href="/docs/data-display/tables-lists"
selected
data-lantern-list-item
>
<:leading>
<.priority_glyph priority={:high} />
<.status_glyph status={:in_progress} />
</:leading>
<:meta><.badge size="sm">ui</.badge></:meta>
<:trailing>Sep 3</:trailing>
</.list_row>
<.list_row
identifier="#238"
title="Inspector rail"
href="/docs/layout/panels"
data-lantern-list-item
>
<:leading><.status_glyph status={:todo} /></:leading>
<:meta><.badge size="sm">docs</.badge></:meta>
<:trailing>Sep 1</:trailing>
</.list_row>
<.list_row
identifier="#199"
title="Closed ring"
href="/docs/foundations/status"
data-lantern-list-item
>
<:leading><.status_glyph status={:done} /></:leading>
<:trailing>Aug 28</:trailing>
</.list_row>
</.scroll_area>
API reference
Props and slots, introspected from the component.
| Prop | Type | Default | Description |
|---|---|---|---|
class |
any |
nil |
Extra classes merged onto the row. |
href |
any |
nil |
External or full-page href; whole row is a link. |
identifier |
string |
nil |
Muted mono id shown after the leading glyph (e.g. `#241`). |
navigate |
string |
nil |
LiveView navigate target; whole row is a link. |
parent |
string |
nil |
Optional parent title rendered muted with a › before `title`. |
patch |
string |
nil |
LiveView patch target; whole row is a link. |
selected |
boolean |
false |
Selected/active row tint. |
title* |
string |
— |
Primary line; truncated. |
| Slots | |||
:leading |
Leading glyph (status/priority/kind). | ||
:meta |
Inline tags, counts, or other chips before the trailing column. | ||
:trailing |
Trailing column (date, assignee). | ||