---
title: "Record page"
description: "The page of one record, finished: pass the header’s data, the sections as items and the properties as label/value items, and fill in the content. Sections are tabs of the page (each with its content) or links to their own URLs (with the route’s content as children)."
---

> Documentation Index
> Fetch the complete documentation index at: https://epidermis.getarbol.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Record page

## Patient: tabs of the page

The tab lives in the app’s state (?tab=); the Data tab keeps its draft while another shows.

```tsx
import { ArchiveIcon, CalendarPlusIcon, PhoneIcon } from '@phosphor-icons/react';
import { useState } from 'react';
import { Avatar, Notice, RecordPage, SettingGroup, SettingToggle } from '@arbol-ai/ui';

const PatientPage = () => {
  const [tab, setTab] = useState('appointments');
  return (
    <RecordPage
      actions={[{ label: 'Call', icon: <PhoneIcon />, href: 'tel:+573005550101' }]}
      avatar={<Avatar name="Laura Gómez" size="xl" />}
      className="px-0 md:px-0"
      menu={[{ label: 'Archive patient', icon: <ArchiveIcon />, isDestructive: true }]}
      menuLabel="More actions for Laura Gómez"
      meta={['CC 1.020.304.050', '34 years', 'Sura EPS']}
      onSectionChange={setTab}
      primaryAction={{ label: 'Book', icon: <CalendarPlusIcon />, href: '#/record-page' }}
      section={tab}
      sections={[
        {
          id: 'appointments',
          label: 'Appointments',
          count: 12,
          content: <p className="text-sm">Monday 14 · Annual check-up with Dr. Ruiz</p>,
        },
        {
          id: 'notes',
          label: 'Notes',
          count: 3,
          content: <p className="text-sm">Prefers morning appointments. Allergic to penicillin.</p>,
        },
        {
          id: 'profile',
          label: 'Data',
          keepMounted: true,
          content: (
            <SettingGroup title="Contact">
              <SettingToggle label="Receives reminders by WhatsApp" />
            </SettingGroup>
          ),
        },
      ]}
      sectionsLabel="Patient sections"
      summary={<Notice tone="info">Next visit: Monday 14 at 9:30, with Dr. Ruiz.</Notice>}
      title="Laura Gómez"
    />
  );
};

<PatientPage />
```

## Campaign: properties beside the content

Narrow the window below 1280px: the properties fold into “Campaign details” above the content.

```tsx
import { PauseIcon, PencilSimpleIcon, TrashIcon } from '@phosphor-icons/react';
import { Badge, RecordPage } from '@arbol-ai/ui';

<RecordPage
  actions={[{ label: 'Pause', icon: <PauseIcon /> }]}
  className="px-0 md:px-0"
  menu={[{ label: 'Delete campaign', icon: <TrashIcon />, isDestructive: true }]}
  menuLabel="More actions for Spring reminders"
  meta="WhatsApp · started Monday"
  onTitleChange={() => undefined}
  properties={[
    { label: 'Agent', value: 'Front desk' },
    { label: 'Line', value: '+57 601 555 0101' },
    { label: 'Contact hours', value: 'Weekdays, 8:00 to 18:00' },
    { label: 'End', value: null },
  ]}
  propertiesAction={{ label: 'Edit settings', icon: <PencilSimpleIcon />, href: '#/record-page' }}
  propertiesLabel="Campaign details"
  status={<Badge tone="success">Running</Badge>}
  title="Spring reminders"
  titleLabel="Campaign name"
>
  <p className="text-muted-foreground rounded-card border p-6 text-sm">
    812 reached · 164 booked · 66% answered
  </p>
  <p className="text-muted-foreground rounded-card border p-6 text-sm">
    The recipients table goes here.
  </p>
</RecordPage>
```

## Professional: sections at their own URLs

Each section is a page; the router’s content for it is the children. Here a small router in memory follows the links.

```tsx
import { CalendarBlankIcon } from '@phosphor-icons/react';
import { useState } from 'react';
import { RouterProvider } from 'react-aria-components';
import { Avatar, RecordPage } from '@arbol-ai/ui';

const PROFESSIONAL_SECTIONS = {
  schedule: 'Weekdays, 7:00 to 13:00. Closed on holidays.',
  services: 'General consultation, follow-up visit.',
  profile: 'Internal medicine · Room 4.',
} as const;

const ProfessionalPage = () => {
  const [section, setSection] = useState<keyof typeof PROFESSIONAL_SECTIONS>('schedule');
  return (
    <RouterProvider
      navigate={(href) => {
        const next = href.split('/').at(-1);
        if (next === 'schedule' || next === 'services' || next === 'profile') {
          setSection(next);
        }
      }}
    >
      <RecordPage
        actions={[{ label: 'View agenda', icon: <CalendarBlankIcon />, href: '#/record-page/agenda' }]}
        avatar={<Avatar name="Ana Ruiz" size="xl" />}
        className="px-0 md:px-0"
        meta={['Internal medicine', 'Room 4']}
        section={section}
        sections={[
          {
            id: 'schedule',
            label: 'Schedule',
            href: '#/record-page/schedule',
          },
          {
            id: 'services',
            label: 'Services',
            href: '#/record-page/services',
            attention: 'No services yet',
          },
          { id: 'profile', label: 'Profile', href: '#/record-page/profile' },
        ]}
        sectionsLabel="Professional sections"
        title="Dra. Ana Ruiz"
      >
        <p className="text-sm">{PROFESSIONAL_SECTIONS[section]}</p>
      </RecordPage>
    </RouterProvider>
  );
};

<ProfessionalPage />
```

## Source

The examples above are [`src/blocks/record-page/record-page.examples.tsx`](https://github.com/getarbol/project-arbol-ui/blob/main/src/blocks/record-page/record-page.examples.tsx), which the library's tests render too.

Source: https://epidermis.getarbol.com/components/blocks/record-page/index.mdx
