Marigold
v18.1.0
Marigold
v18.1.0

Application

MarigoldProvider
RouterProvider

Layout

AppShellbeta
Aside
Aspect
Center
Columns
Container
Grid
Inline
Inset
OverflowRegionbeta
Pagebeta
Panelbeta
Scrollable
Split
Stack
Tiles

Actions

Buttonupdated
ButtonGroupbeta
Link
LinkButton
ToggleButtonbeta

Form

Autocomplete
Calendar
Checkbox
ComboBox
DateField
DatePicker
DateRangePickerbeta
FileField
Form
NumberField
Radio
RangeCalendaralpha
SearchField
SegmentedControlbeta
Select
SelectListupdated
Slider
Switchupdated
TagFieldbeta
TextArea
TextField
TimeField

Collection

Cardupdated
Table
ListViewbeta
Tag
ActionBaralpha

Navigation

Accordion
Breadcrumbs
Pagination
Sidebarbeta
Tabs
TopNavigationbeta

Overlay

ActionMenualpha
ContextualHelp
Dialog
Drawer
Menuupdated
Toastbeta
Tooltip

Content

Badge
Descriptionalpha
Divider
EmptyState
ErrorStatebeta
Headline
Keyboardbeta
List
Loader
SectionMessage
SVG
Text
TextValuealpha
Titlealpha

Formatters

DateFormat
NumericFormat

Hooks and Utils

cn
cva
extendTheme
parseFormData
useAsyncList
useLandmark
useListData
useTheme
VisuallyHidden
Components

ListView

Show a collection of items as a list, with optional per-row controls.

A <ListView> shows a collection of items as rows in a list. Each row can carry its own controls, such as a <Button> or an <ActionMenu>, so users can act on an item without leaving the page. Rows can also be selectable, for a flow that gathers several items and then acts on all of them at once.

Use it for collections people work through, like a notification feed, a list of uploaded files, or the venues a user picks from in a dialog.

Anatomy

ItemSelectionindicatorListText valueDescriptionActions(e.g. Button, ActionMenu)
  • List: The container that holds all rows.
  • Item: A single row representing one entry of the collection.
  • Selection indicator: The mark for a row's selected state, present only once the list has a selectionMode. A checkbox for multiple selection, a radio circle for single.
  • Text value: The primary text of a row.
  • Description: Optional secondary text below the text value, like a timestamp or a file size. One per row, and it takes inline markup, so several facts can share a line: "Updated 3 days ago · 2.1 MB".
  • Actions: Optional trailing controls for the row, such as a button or a row menu.

Appearance

The appearance of a component can be customized using the variant and size props. These props adjust the visual style and dimensions of the component, available values are based on the active theme.

The selected theme does not has any options for"size".
Quarterly reportUpdated 3 days ago · 2.1 MB
RoadmapUpdated today · 640 KB
Budget forecastUpdated yesterday · 480 KB
PropertyTypeDescription
variantdefaultThe available variants of this component.
size-The available sizes of this component.

Usage

Reach for a <ListView> when the user works through a collection one entry at a time, acting on a row where it sits instead of opening it. Typical cases:

  • Notification and activity feeds: a stream of events the user scans, then dismisses or mutes per row.
  • Resource lists: files, documents, or team members, each with rename, share, and delete behind a row menu.
  • Connections and integrations: linked accounts or services the user reviews and disconnects individually.

A row is one item, not a record split into fields. A <ListView> gives you a text column and a trailing control, with nothing aligned between rows, so there is no way to scan a column or sort by one. Once the user needs to compare entries against each other (a status column, a size to sort by, dates to line up), reach for a <Table>.

Rows can be selected, but the selection stays in your own state and never submits with a form. That is the line between a <ListView> and a <SelectList>, and the decision test below is how you pick between them.

Row text

Author a row's primary text with <TextValue>, or pass a bare string. Secondary text goes in a <Description>, one per row.

To emphasise part of a row's text, nest <Text as="span"> inside <TextValue> or <Description> rather than adding a <Text> of its own:

<ListView.Item id="deploy" textValue="Deploy succeeded">
  <TextValue>
    Deploy{' '}
    <Text as="span" weight="bold">
      succeeded
    </Text>
  </TextValue>
</ListView.Item>

The same rule covers everything else a row carries. A row has a cell for its text, a cell for its trailing control, and, once the list is selectable, a cell for its selection indicator. A child that claims none of them, like a <Badge>, gets placed wherever the grid has room. On its own that means a new full-width line under the description, where it reads as part of the row's text. In a selectable list it is worse: the badge lands in the indicator column and widens it, so that row's text no longer lines up with any other row's. Nest it in the text it belongs to instead:

<ListView.Item id="gasometer" textValue="Gasometer">
  <TextValue>
    Gasometer <Badge variant="warning">Sold out</Badge>
  </TextValue>
  <Description>Vienna · 1600 seats</Description>
</ListView.Item>

Row actions

Keep the action users reach for most often visible as an icon button and group the rest behind an <ActionMenu>. More than two visible buttons per row turns the list into a wall of controls that competes with the text people are scanning.

Pick a glyph that says what happens to the row, like Archive, Check, or BellOff. An X means "close this" everywhere else in Marigold, and a row's action doesn't close anything. Rare or irreversible commands like deleting belong in the menu, as an <ActionMenu.Item variant="destructive">, not behind a one-click icon button.

Build finished2 minutes ago
Deploy succeeded1 hour ago
Review requestedYesterday

When no single action stands out, or the available actions differ from row to row, drop the visible button and use the menu on its own.

Quarterly reportUpdated 3 days ago · 2.1 MB
RoadmapUpdated today · 640 KB

A row has a single cell for trailing controls, so wrap two or more in a <ButtonGroup>. Left loose, they claim the same cell and stack. That cell takes Button-family controls only: a <Badge> or a status pill belongs in the row's text, as shown under Row text above.

Selection

Make rows selectable when the user's next step needs a row they haven't acted on yet. Two situations earn it:

  • Staging one choice. The list is where the user picks a record, and something else commits it, like a venue chosen in a dialog and applied with its confirm button. Set selectionMode="single".
  • Gathering rows for one operation. The user marks several records, then runs one action across all of them, like archiving six files at once. Set selectionMode="multiple" and give them an action bar to run it.

Leave selection off otherwise, which is the default. A row the user acts on where it sits doesn't need marking first, and an indicator on every row of a notification feed adds a step to a list that had none.

Oak Ridge BarnHee-Haw City · 150 seats
Harborfront PromenadePort Funsies · 600 seats
Cellar LoungeLaughville · 250 seats

Whichever mode you pick, the selection is yours to keep. Hold it in your own state, read it through onSelectionChange, and decide when it commits. It never reaches a surrounding <form>, so a choice that has to submit and validate with the rest of the form is a <SelectList> instead.

Rows are marked one at a time. A press adds or removes a single row, and there is no Shift+click to take a range, in a <ListView> or in a <Table>. Plan a flow that depends on range selection around that.

Selecting and opening a row

A selectable list can still open its rows. Set onAction alongside selectionMode and the press does whichever the user is more likely to mean:

  • Nothing selected: pressing a row opens the item, and Enter does the same. The checkbox and Space select without opening anything.
  • Something selected: pressing a row marks it instead, and nothing opens. Space marks the focused row, and Enter does nothing at all.
Report Q1.pdf3 days ago · 2.1 MB
Season plan.xlsxYesterday · 640 KB
Venue contract.pdf2 weeks ago · 1.2 MB

One list serves browsing and selecting this way, without a mode switch of your own to build. The catch is the second state: while anything is selected there is no way to open a row, and a keyboard user who presses Enter gets no response of any kind. Escape clears the selection and opening works again, so keep a clear button within reach rather than leaving that as the only way out.

Bulk actions

Pair a multi-select list with an <ActionBar>, rendered as a sibling inside the list's scroll container. The bar is sticky, so it pins itself to the bottom of that container and appears once something is selected.

Drive it with useActionBar, which holds the selection, fills in the count and the clear button, and measures the bar. You need that measurement: a <ListView> does not know the bar is there, so without it the bar covers the last rows and keyboard navigation parks a focused row underneath it. Reserve its height on the scroll container in both padding-bottom and scroll-padding-bottom, which is what a <Table> does for you.

Report Q1.pdf3 days ago · 2.1 MB
Season plan.xlsxYesterday · 640 KB
Venue contract.pdf2 weeks ago · 1.2 MB
Floor plan.png3 weeks ago · 4.7 MB
Tech rider.pdfLast month · 320 KB
Invoice 2291.pdfLast month · 88 KB

A list short enough not to scroll needs none of that. Render the <ActionBar> after it and pass selectedItemCount and onClearSelection yourself.

One piece of the Bulk Actions pattern is missing here: select-all. That is a checkbox in the collection's header, and a list has no header row to hold one, so a flow where users regularly select every visible record belongs in a <Table>. Everything else in the pattern applies to a <ListView> unchanged, including bounding the selection to the rows the user can see, clearing it when a filter or a page changes what is visible, and confirming a destructive action with the exact count.

Empty state

Pass an <EmptyState> to the emptyState prop so a list with nothing to show still explains itself instead of rendering as a blank surface.

No resources yet

Files you add show up here.

<ListView> vs. <SelectList>

On screen these two are hard to tell apart: the same stack of rich rows, an indicator on each, a description under the label. What differs is where the selection goes, and one question settles it:

Does the selection need to submit with the form?

  • Yes, it is a field value that submits and validates: <SelectList>.
  • No, you read it and commit it yourself: <ListView>.

One exception runs the other way. A pick that never submits but still needs a visible label, helper text, or a validation message wants a <SelectList> anyway, because a <ListView> renders none of those. It takes an aria-label and nothing else, so a list that has to name itself on screen or explain a rule like "choose at least one" is a field whether or not a <form> is involved.

Underneath, one is a form field and the other a collection view. A <SelectList> carries a label, validation, and a hidden input, so its selection is the field's value and travels with the rest of the form. A <ListView> keeps its selection as state you own, and its rows can carry their own focusable controls, like a link or a row menu, which a field has no room for.

That is the real distinction, and a poor decision aid on its own, because most flows can be described either way. Start from the question.

Do

Use <ListView> when you own the selection: a notification feed, a list of files, or records staged in a dialog and committed with its button.

Don't

Don't use <ListView> for a choice that submits with a form. It has no label, no validation, and no value, which is what <SelectList> is for.

Accessibility

  • Arrow keys move focus between rows, Tab reaches the controls inside the focused row.
  • Give the list an aria-label, or aria-labelledby when a heading nearby already names it.
  • Set textValue on a row whose text isn't a plain string, screen readers use it as the row's accessible name.

In a selectable list, moving focus never changes the selection. Space selects the focused row and Escape clears the whole selection, so a user who started selecting by accident has a way out. The row itself announces whether it is selected, which is why the radio circle in single mode stays out of the accessibility tree: it says nothing a screen reader has not already heard.

<Title> normally renders a real heading. Inside a row it renders as a <span> instead, so a heading-like row doesn't add an entry to the page's heading outline.

Props

Did you know? You can explore, test, and customize props live in Marigold's storybook. Watch the effects they have in real-time!
View ListView stories

ListView

Prop

Type

Accessibility props (4)

Prop

Type

DOM event handlers (64)

Prop

Type

ListView.Item

Prop

Type

DOM event handlers (63)

Prop

Type

Alternative components

  • List: Use for a static list of text with no per-row controls.
  • SelectList: Use when the selection becomes a submitted form value.
  • Select: Use for a compact single/multi-select form field.
  • Table: Use when each row is a record with multiple columns of structured data to compare, not a flat list of operable items.
  • Menu: Use for a set of commands that close the surface on activation.
  • Card: Use to present one item, like an event or a product, as a self-contained visual unit.

Related

ActionBar

Bulk actions on top of a selection.

Form fields

How form fields work in Marigold, and why ListView is not one.
Last update: 21 minutes ago

Table

Display and interact with structured data in rows and columns.

Tag

Used to manage related options.

© Reservix GmbH — Marigold Design System
ImpressumDatenschutzGitHubRSS

On this page

AnatomyAppearanceUsageRow textRow actionsSelectionEmpty state<ListView> vs. <SelectList>AccessibilityPropsListViewListView.ItemAlternative componentsRelated