CRUD / foldkit-mixins-crud

Rows instead of a table

When a list is a navigation or a picker of whole rows, a table is the wrong markup. RowListView carries the same state contract over ul/li: you draw each row's content, and onOpen makes the whole row a button.

ts
import { RowListView } from 'foldkit-mixins-crud'

const PageList = RowListView.forMessages<Message>().define<PageRow>({ name: 'Pages' })

const pages = (model: Model, h: HtmlBuilder<Message>): Html =>
  PageList(
    {
      page: SitePages.read(model),
      row: (page, h) => [h.span([], [page.label])],
      onOpen: page => Message.OpenedPage({ id: page.id }),
      onRetry: Message.RetriedPages(),
    },
    h,
  )

define<Row>({ name }) names the view and the row type. Its Slots are RowListSlots: root, status, list (the ul), row (an li), open, more, retry. Loading, empty, a failed read with its retry, and a failed refresh kept above its rows are handled exactly as for ListView — one implementation, so the two cannot drift.

Follow a row click

The table reads the page value you pass it. onOpen constructs OpenedPost; it does not open an editor by itself. Handle that Message in the parent update, for example by applying the placed editor's open(id) Step. Loading and saves then follow the editor's Remote integration.

Similarly, onMore and a sort header only send your Messages. Your update must change the query window or ordering. Rendering the table alone never starts a query. This lets the same view render a test page or a live Remote page.