Skip to content
Components

List row

The workhorse row — neutral glyph tile, title and sub, something on the right — for things that are one of many and get scanned.

Anatomy

Creek floodingRear of lot · mapped overlay18%
Registered easementOn title · not drawn on the mapOn title
Code
<GdListRow title="A granny flat" :expanded="open" @click="open = !open">
  <template #tile><GdTile :size="36"><GdIcon d="…" :size="22" /></GdTile></template>
  <template #sub><GdApprovalStack inline :required="['building', 'council']" /></template>
</GdListRow>

<GdListRow title="Creek flooding" sub="Rear of lot · mapped overlay">
  <template #swatch><span class="swatch" :style="{ background: overlay.colour }" /></template>
  <template #trailing><span data-gd-numeric>18%</span></template>
</GdListRow>

States

Code
<GdListRow title="Rest" action />
<GdListRow title="Selected" selected action />

API

Props

PropTypeDefault
titlerequiredstring—

The row's headline — the thing being scanned for.

substring—

The qualifier under the title. The `sub` slot takes markup instead, for a chip row or an approval stack.

tostring—

Internal route. Renders a NuxtLink.

hrefstring—

External URL. Renders an `<a>`.

actionbooleanfalse

The row is a control — renders a `<button>`.

selectedbooleanfalse

The chosen row in a list. A surface change, never an elevation change.

expandedboolean—

For an expandable row: renders the chevron and sets `aria-expanded`. Left undefined the row is not a disclosure at all, which is why it has no `false` default — the third state has to stay sayable.

Slots

swatch

A cartographic square before the tile, for a constraint's published colour.

tile

The neutral glyph tile — usually a `GdTile` holding a `GdIcon`.

sub

Markup in place of the `sub` prop.

trailing

Whatever sits on the right — a value, a chip, a badge.

Events

click[]

Fired when the row is activated. Only reachable when the row renders as a button — a bare row is a `<div>` and inert.

Usage Guidelines

  • Use to or href when activating the row lands you somewhere else. That is what makes middle-click and open-in-new-tab work.
  • Use action when the row does something in place — selects, toggles a layer, opens a panel beside it.
  • Use expanded when the row reveals content beneath itself. Bind it; do not pass a literal false to a row that never expands.
  • Pass none of the four for an inert fact row. It renders a div and takes no focus, which is correct for something you only read.
  • Use the swatch slot for colour, never the tile. A swatch is a council's published cartography; the tile is the system's neutral furniture.
  • Use trailing for the value and sub for the qualifier. A row scanned in a list is read left to right once — the right edge is where the number goes.
  • Reach for a data table instead when the things being scanned are compared column by column. Rows are for one-of-many, not for a grid of values.

Behavior & Anatomy

Surface, not elevation

A list that lifts under the pointer shimmers as the pointer crosses it, and thirty of them on a map panel is a strobe. Hover darkens; it does not raise.

Which element it renders

<GdListRow to="/parcel/L14RP80432"> → NuxtLink <GdListRow href="https://…"> → <a> <GdListRow action> → <button> <GdListRow :expanded="open"> → <button aria-expanded> <GdListRow> → <div> (inert)

A row that does something is never a div with a click handler: that answers Enter, silently ignores Space, and is not reachable at all without a tabindex.

Why expanded has no default

Vue resolves an ABSENT Boolean prop to false unless a default is declared, which would collapse this prop's three states into two: every plain row would then read as expandable and render as <button aria-expanded="false"> with a chevron, announcing a disclosure that does not exist. Declaring expanded: undefined keeps "not expandable" sayable. action and selected need no such thing — they are read truthily, so absent and false mean the same.

Navigate

Esc