Components

Record Panel

A right-side record peek — slides in over the grid to show one record's Highlights and Activity.

The peek panel that opens when you click into a row: a 420px sheet that slides in from the right over the main content, showing one record's Highlights (a set of label/value/icon cards) and its Activity feed. Measured from the live app — a 52px header (favicon/logo + name + close), a scrolling body, and — like every floating surface here — an 8px gutter inset from the main area's edges, 12px corners, and the shared floating elevation (no border, no directional shadow).

This is a measured rebuild of a specific record peek, not a general slide-in panel — for your own content reach for Drawer.

Available since@crisp-ui-kit/crisp@0.11.0

Hover any row below and click the "Open preview" icon that appears on the Company cell to peek the record; Esc or the × closes it.

Installation

npm install @crisp-ui-kit/crisp

Usage

RecordPanel is driven by a record prop — pass { id, name } (plus whatever else you want to read from it) to open, or null to close. It renders nothing when record is null, so keep it mounted and flip the state. highlights and activity are both entirely yours — crisp has no fixed Highlights set or activity-feed model of its own, only the measured chrome around them:

import { DataTable, RecordPanel } from "@crisp-ui-kit/crisp";
import type { DataTableColumn } from "@crisp-ui-kit/crisp";
import * as React from "react";

export function Companies() {
  const [open, setOpen] = React.useState<Row | null>(null);
  // `onOpenPreview` is a column-level prop (type: "entity" only) — the icon
  // it adds is what peeks the record; a plain row click can stay wired to
  // something else entirely (opening the full record page, say).
  const columns: DataTableColumn<Row>[] = [
    { key: "company", header: "Company", type: "entity", onOpenPreview: setOpen },
    // ...the rest of your columns
  ];
  return (
    // a position: relative container — the panel positions absolutely inside it
    <div style={{ position: "relative", height: "100%" }}>
      <DataTable columns={columns} data={rows} />
      <RecordPanel
        record={open}
        highlights={
          open
            ? [
                { key: "domain", label: "Domain", value: open.domain },
                { key: "employees", label: "Employees", value: open.employees },
              ]
            : undefined
        }
        activity={<MyActivityFeed recordId={open?.id} />}
        onClose={() => setOpen(null)}
      />
    </div>
  );
}

Props

Prop

Type

Notes

  • Positioning. The panel is position: absolute; inset-block: 0; right: 0, so it must live inside a position: relative ancestor — the app's main content area, or the demo frame above. It overlays rather than pushing the grid.
  • No editable field list. Attio's own peek panel has no click-to-edit Details list (measured live, #448) — clicking a Highlights value or the record title never moves focus into an input. RecordPanel matches that; the editable-field API stays on RecordPage's own Details column, where Attio does let you edit in place.
  • Highlights. A 2-column grid of { label, value, icon? } cards, no card chrome (no border/background/shadow) — matching Attio's own peek exactly. Omit highlights for no Highlights section at all.
  • Activity. A plain slot — RecordPanel only renders the measured "Activity" heading (with an optional "View all" action via onViewAllActivity) above whatever you give it. Omit activity for no Activity section at all.
  • Enter animation. It slides in from the right via @starting-style (translateX(100%) → 0), the same technique the Command menu uses.
  • Escape to close. While open it listens for Esc; the listener is removed when closed.

See it composed into the full page in the Companies page example.

On this page