DataList

A list of key and value pairs: an order summary, a profile, a settings pane, the input of a tool call. It is a native dl, so each term and its details are a dt and a dd. The gaps follow density, and the term and details colors, the term weight and the term column width come from the datalist contract tokens.

On this page
<DataList.Root aria-label="Order summary">
  <DataList.Item>
    <DataList.Term>Order</DataList.Term>
    <DataList.Details>#10482</DataList.Details>
  </DataList.Item>
  <DataList.Item>
    <DataList.Term>Status</DataList.Term>
    <DataList.Details>Shipped on 2027-01-04</DataList.Details>
  </DataList.Item>
  <DataList.Item>
    <DataList.Term>Total</DataList.Term>
    <DataList.Details>$42.00</DataList.Details>
  </DataList.Item>
</DataList.Root>
Order
#10482
Status
Shipped on 2027-01-04
Ship to
Mina Park
12 Harbor Street
Busan
Total
$42.00

Server Components can import it from @tounsoo/todae/data-list. That entry has no 'use client' and no hooks; the main @tounsoo/todae entry is a client module.

DataList.Item is a div that holds one term and its details. A div is valid inside a dl for this, and it is the one row you can style, move or key. Give each item one DataList.Term and one DataList.Details. Several values for one term go inside that one DataList.Details, for example as a list.

Orientation

orientation="vertical" puts the term above its details. The default, "horizontal", puts the term in a column beside the details. The value reaches CSS as data-orientation.

<DataList.Root orientation="vertical" aria-label="Profile">
  <DataList.Item>
    <DataList.Term>Name</DataList.Term>
    <DataList.Details>Mina Park</DataList.Details>
  </DataList.Item>
  <DataList.Item>
    <DataList.Term>Email</DataList.Term>
    <DataList.Details>mina@example.com</DataList.Details>
  </DataList.Item>
</DataList.Root>
Name
Mina Park
Email
mina@example.com
Teams
Design systems, Docs

Columns

minItemSize lays the items out in columns, each no narrower than the CSS length you give it, such as "10rem". As many columns fit as the width allows, so the list reflows without a media query, and in a list narrower than minItemSize the single column shrinks to fit. Items fill the rows in DOM order, so the reading order stays the source order. The gap between columns is datalist.gap.between-columns, and the gap between rows stays datalist.gap.row. Grid can't lay out a list's items, since it renders a div and the items have to be children of the dl.

<DataList.Root orientation="vertical" minItemSize="10rem" aria-label="Plan">
  <DataList.Item>
    <DataList.Term>Plan</DataList.Term>
    <DataList.Details>Team</DataList.Details>
  </DataList.Item>
  <DataList.Item>
    <DataList.Term>Seats</DataList.Term>
    <DataList.Details>12 of 20</DataList.Details>
  </DataList.Item>
  {/* … */}
</DataList.Root>
Plan
Team
Seats
12 of 20
Storage
48 GB of 100 GB
Billing
Monthly
Renews
2027-02-01
Support
Business hours

Each item keeps its orientation inside its column. A horizontal item stacks when its column is narrower than the term column, datalist.gap.column and the details minimum together, so give columns of horizontal items a minItemSize of at least calc(var(--todae-datalist-term-width) + var(--todae-datalist-gap-column) + var(--todae-datalist-details-min-width)).

In a parent that sizes the list to its content, the number of columns follows the width of the items' text; the next section says how to give the list a width.

Narrow widths

A horizontal list stacks by itself when it is too narrow for the term column and a readable details column. The term takes up to datalist.term.width, and shrinks in a list narrower than that column. The details wrap below it once they would be narrower than datalist.details.min-width. No container query is involved, so a company can change both tokens. The gap between a stacked term and its details is datalist.gap.stacked.

The list takes the width its parent gives it. A parent that sizes the list to its content, such as a flex row or an inline-block, gives it only the width of its text, so its rows stack. Give the list a width there, for example flex: 1 in a flex row.

Accessible composition

Todae handles: The dl, dt and dd elements, which expose each dt as a term and each dd as its definition or details, and assistive technology can report the list as a description list. Nothing is added with ARIA, and the div around each pair is invisible to the accessibility tree.

You supply: A name for the list when it needs one, with aria-label or aria-labelledby. Term text that makes sense on its own, such as "Total" or "Ship to".

Watch for: Content that is not a term inside DataList.Term, such as a button or a form control: the dt is exposed as the term for its details. A DataList that holds data with several columns per row; that is a table, which gives each cell its column header.

When to use

When: A set of named values for one thing, such as an order, a person, a plan or a tool call's input.

When not: Rows of the same fields for many things → Table. Values the user edits → Field.

Props

DataList.Root props
NameTypeDescription
orientation"horizontal" | "vertical"

Sets data-orientation. Horizontal puts each term in a column beside its details, and stacks them when the list is too narrow for both. Vertical puts the term above its details.

Default: "horizontal"

minItemSizestring

Lays the items out in columns no narrower than this CSS length, such as "24rem". As many columns fit as the width allows, with datalist.gap.between-columns between them, and a single column never overflows. A horizontal item stacks in a column narrower than its term column, datalist.gap.column and details minimum together. Without it the items sit in one column.

childrenReact.ReactNode

DataList.Item parts.

DataList.Item props
NameTypeDescription
childrenReact.ReactNode

One DataList.Term, then one DataList.Details.

DataList.Term props
NameTypeDescription
childrenReact.ReactNode

The term, as text.

DataList.Details props
NameTypeDescription
childrenReact.ReactNode

The value. Put a list of values in one DataList.Details.