Views
How to declare list and detail views for objects and mount them in React.
A view declares how an object is presented — a list/grid for collections, or a detail page for a single record. The schema declares views; the UI mounts them.
// @noverify
import { detailView, group, listView, viewRegistry } from "@stndrds/schema";
export const CONTACT_LIST = listView("contacts-list", "Contacts")
.for("contacts")
.default()
.tab("all", "All contacts")
.columns("firstName", "lastName", "email", "status")
.sort("lastName", "asc")
.default()
.build();
export const CONTACT_DETAIL = detailView("contacts-detail", "Contact")
.for("contacts")
.default()
.tab("general", "General")
.form(group("identity", "Identity").fields("firstName", "lastName", "email"))
.build();
viewRegistry.register(CONTACT_LIST);
viewRegistry.register(CONTACT_DETAIL);Call viewRegistry.register() once per view, typically in a schema/index.ts entry point loaded at startup.
Detail vs list
listView targets a collection. Each tab carries its own layout (table or kanban), column set, filters, and sorts. The tab is where you pick what columns are visible and in what order.
detailView targets a single record. It organises attributes into tabs, with each tab containing one or more groups of fields. A detail view can also include tabs that show related records via tableFrom(), rich-text notes (.richtext()), documents (.documents()), and activity (.activity()).
Tabs and groups
// @noverify
detailView("contacts-detail", "Contact")
.for("contacts")
.default()
.tab("general", "General")
.form(
group("identity", "Identity")
.field("firstName", { span: 6 })
.field("lastName", { span: 6 })
.field("email", { span: 12 }),
group("meta", "Details").fields("status", "company")
)
.tab("activity", "Activity")
.activity()
.build();group(id, label) organises fields inside a form tab. Each field accepts a span (1–12 grid columns) and an optional readOnly flag. Tabs are added in declaration order; the first tab is shown by default unless you call .default() on another.
Mounting in React
// @noverify
import { ViewAwareRecordsView } from "@stndrds/ui";
export function ContactsPage() {
return <ViewAwareRecordsView objectId="contacts" />;
}ViewAwareRecordsView resolves the default list view for the object and renders it. The active tab is controlled by URL state — switching tabs updates the URL so the state is bookmarkable and shareable.
ViewAwareRecordsView requires SchemaClientProvider in the tree. See the React frontend guide for provider setup.