react-resource-view

Split & columns

Master-detail, and a board grouped by a key.

Split#

The list on the left, the selected record on the right. It replaces the separate detail page rather than complementing it — which is why the resource often has no read screen to maintain at all.

import { splitViewFactory } from "react-resource-view"
import { ActionList } from "react-data-form"

viewVariants: [
  splitViewFactory({
    // What the right-hand pane shows. `update` makes it an editor.
    resourceAction: ActionList.read,
    // Shown before anything is selected.
    emptySelected: () => <p>Pick an article on the left.</p>,
    // `read/{id}` redirects to `list/{id}`, so incoming links land here.
    redirectReadToList: true,
  }),
]

Pick a row on the left

NameTypeDefaultDescription
resourceActionActionListreadWhat the right pane renders. update turns it into an editor, which is what makes a split feel like a mail client.
emptySelectedFCRendered before anything is selected.
redirectReadToListbooleanMakes read/{id} redirect to list/{id}.

Incoming links#

Links built elsewhere — a notification, an email, a share — point at the detail view. With no detail view to point at, they would land nowhere.

That is what redirectReadToList is for

It turns read/42 into list/42, so an existing link opens the split with that item selected. Set it whenever the split is the only detail your resource has.

Columns#

A board: one column per value of a chosen field. It needs two things — which field groups the records, and which values are columns.

import { columnViewOptionFactory } from "react-resource-view"

const STATUSES = [
  { label: "Draft", value: "draft" },
  { label: "In review", value: "review" },
  { label: "Published", value: "published" },
]

viewVariants: [
  columnViewOptionFactory({
    // Which field decides the column…
    identifierKey: "status",
    // …and which columns exist, in which order.
    identifierKeyList: STATUSES,
  }),
]

Grouped by status

Both keys are required

Without identifierKey the layout renders “Not Identifiant Found”, and without identifierKeyList, “no identifierKeyList”. The list is explicit on purpose: an empty column has to exist to be dropped into, and deriving the columns from the data would make it vanish.

identifierKeyList takes the same option shape as a select field, so the field's own valueOptions can be reused directly — one list, both places.

Moving a card#

Dragging a card into another column writes the new value of identifierKey through the repository and refetches. There is no drag handler to write: moving a card is editing that field.

Which one, when#

  • Split when records are read one after another and the list is a navigation aid — an inbox, a queue, a log.
  • Columns when the interesting operation is moving a record between states — a pipeline, a kanban, an editorial workflow.
  • Neither when the reader is comparing records, in which case a table beats both.