npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@object-ui/plugin-detail

v13.1.0

Published

DetailView plugin for Object UI - comprehensive detail page with sections, tabs, and related lists

Readme

@object-ui/plugin-detail

DetailView plugin for ObjectUI - A comprehensive detail page component with field grouping, tabs, related lists, and action buttons.

Features

  • Field Grouping/Sections: Organize fields into logical sections with titles
  • Collapsible Sections: Make sections collapsible to save space
  • Tab Navigation: Organize content into tabs for better UX
  • Related Lists: Display related records (e.g., contacts for an account)
  • Action Buttons: Edit, Delete, and custom action buttons
  • Readonly/Edit Mode: Toggle between view and edit modes
  • Back Navigation: Built-in back button with customizable behavior
  • Loading States: Skeleton loading for async data
  • Custom Headers/Footers: Flexible customization options

Installation

pnpm add @object-ui/plugin-detail

Usage

Basic Example

import { DetailView } from '@object-ui/plugin-detail';

function ContactDetail() {
  return (
    <DetailView
      schema={{
        type: 'detail-view',
        title: 'Contact Details',
        data: {
          name: 'John Doe',
          email: '[email protected]',
          phone: '+1234567890',
          company: 'Acme Corp',
        },
        fields: [
          { name: 'name', label: 'Full Name' },
          { name: 'email', label: 'Email' },
          { name: 'phone', label: 'Phone' },
          { name: 'company', label: 'Company' },
        ],
        showBack: true,
        showEdit: true,
        showDelete: true,
      }}
    />
  );
}

With Sections

<DetailView
  schema={{
    type: 'detail-view',
    title: 'Account Details',
    sections: [
      {
        title: 'Basic Information',
        icon: '📋',
        fields: [
          { name: 'name', label: 'Account Name' },
          { name: 'industry', label: 'Industry' },
          { name: 'website', label: 'Website' },
        ],
        columns: 2,
      },
      {
        title: 'Address',
        collapsible: true,
        defaultCollapsed: false,
        fields: [
          { name: 'street', label: 'Street' },
          { name: 'city', label: 'City' },
          { name: 'state', label: 'State' },
          { name: 'zipcode', label: 'Zip Code' },
        ],
        columns: 2,
      },
    ],
    data: accountData,
  }}
/>

With Tabs and Related Lists

<DetailView
  schema={{
    type: 'detail-view',
    title: 'Account: Acme Corp',
    objectName: 'accounts',
    resourceId: '12345',
    fields: [
      { name: 'name', label: 'Account Name' },
      { name: 'industry', label: 'Industry' },
    ],
    tabs: [
      {
        key: 'details',
        label: 'Details',
        icon: '📄',
        content: {
          type: 'detail-section',
          fields: [
            { name: 'description', label: 'Description' },
            { name: 'employees', label: 'Employee Count' },
          ],
        },
      },
      {
        key: 'activity',
        label: 'Activity',
        badge: '12',
        content: {
          type: 'activity-timeline',
          data: activityData,
        },
      },
    ],
    related: [
      {
        title: 'Contacts',
        type: 'table',
        api: '/api/accounts/12345/contacts',
        columns: ['name', 'email', 'phone', 'title'],
      },
      {
        title: 'Opportunities',
        type: 'table',
        api: '/api/accounts/12345/opportunities',
        columns: ['name', 'amount', 'stage', 'close_date'],
      },
    ],
    showEdit: true,
    showDelete: true,
  }}
  onEdit={() => navigate('/accounts/12345/edit')}
  onDelete={() => deleteAccount('12345')}
  onBack={() => navigate('/accounts')}
/>

Schema

The DetailView component accepts a DetailViewSchema:

interface DetailViewSchema {
  type: 'detail-view';
  title?: string;
  objectName?: string;
  resourceId?: string | number;
  api?: string;
  data?: any;
  sections?: DetailViewSection[];
  fields?: DetailViewField[];
  tabs?: DetailViewTab[];
  related?: RelatedList[];
  actions?: ActionSchema[];
  showBack?: boolean;
  showEdit?: boolean;
  showDelete?: boolean;
  backUrl?: string;
  editUrl?: string;
  deleteConfirmation?: string;
  loading?: boolean;
  header?: SchemaNode;
  footer?: SchemaNode;
}

Components

DetailSection

Renders a group of fields with optional collapsing.

DetailTabs

Tab navigation for organizing content into different views.

RelatedList

Displays related records in list, grid, or table format.

Compatibility

  • React: 18.x or 19.x
  • Node.js: ≥ 18
  • TypeScript: ≥ 5.0 (strict mode)
  • @objectstack/spec: ^3.3.0
  • @objectstack/client: ^3.3.0
  • Tailwind CSS: ≥ 3.4 (for packages with UI)

Links

Reference Rail decision matrix

The "Reference Rail" is the right-hand column on the record detail page that surfaces summary cards for related collections (similar to Salesforce's Related rail and HubSpot's About this record sidebar). It is rendered by the record:reference_rail component and emits automatically when:

  1. The page is generated by the synth (buildDefaultPageSchema) — i.e. no explicit Page overrides the object's detail view.
  2. The objectDef declares ≥2 related collections (lookup/master-detail inbound fields).
  3. The viewport is ≥ xl (1280 px) — below that the rail collapses and the Related tab keeps full coverage.
  4. The objectDef does not opt out via detail.hideReferenceRail.

When the rail emits, the synth automatically suppresses the Related tab so the same information isn't shown twice.

Per-object opt-out

Add a detail block to the objectDef:

ObjectSchema.create({
  name: 'product',
  // …
  detail: {
    hideReferenceRail: true,  // hide the rail; restore the Related tab
    hideRelatedTab: true,     // (optional) force-hide the Related tab too
  },
});

CRM business-domain guidance

| Object type | Rail | Why | |--------------------|--------|--------------------------------------------------------------| | Hub objects | on | Account / Opportunity / Contact / Case — users browse laterally to quotes, contacts, activities | | Transactional | on | Quote / Contract / Order — show line-items + related parties at a glance | | Campaign / Event | on | Members, responses, child campaigns | | Catalog | off| Product / Price Book — users edit attributes; lateral relationships are noise | | Atomic action | off| Task / Note — focused single-column edit beats a related-list rail | | Lead (unconverted) | off| Pre-conversion records have no children — keep it focused on the form |

Adding the rail to a custom Page

For explicit (non-synth) Pages, add an aside region after the main region:

{
  name: 'aside',
  width: 'small',
  className: 'hidden xl:flex flex-col gap-4',
  components: [
    {
      type: 'record:reference_rail',
      id: 'opp_reference_rail',
      properties: {
        entries: [
          { objectName: 'quote',                 relationshipField: 'opportunity', title: 'Quotes',     limit: 3 },
          { objectName: 'opportunity_line_item', relationshipField: 'opportunity', title: 'Products',   limit: 3 },
          { objectName: 'task',                  relationshipField: 'related_to_opportunity', title: 'Open Tasks', limit: 3 },
        ],
      },
    },
  ],
},

The renderer reads entries from both schema.entries and schema.properties.entries so either spec-style or flat authoring works.

License

MIT — see LICENSE.