mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-05-18 20:08:19 +00:00
feat: PageHeader component + refactor all 6 list pages
New reusable PageHeader component (src/components/layout/page-header.tsx) with consistent layout: title + badge + subtitle on left, controls on right, optional tabs below with no extra borders. Refactored pages: - All Leads: inline header → PageHeader - Contacts: inline header → PageHeader - Appointments v2: inline header → PageHeader with tabs - Call History: removed p-7 wrapper + TableCard.Root → flat table - Patients: removed p-7 wrapper + TableCard.Root → flat table - Missed Calls: removed TopBar → PageHeader with tabs All pages now share identical header spacing, font sizing, and control alignment. No more double borders from tab + container. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
55
src/components/layout/page-header.tsx
Normal file
55
src/components/layout/page-header.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
// PageHeader — consistent header layout for all list pages.
|
||||
//
|
||||
// Row 1: Title (+ optional badge + subtitle) on the left,
|
||||
// controls (search, columns, export, etc.) on the right.
|
||||
// Row 2: Optional tabs (underline style) — no extra borders.
|
||||
//
|
||||
// Usage:
|
||||
// <PageHeader
|
||||
// title="Appointments"
|
||||
// badge={37}
|
||||
// subtitle="Manage appointments"
|
||||
// controls={<><Input .../> <Button .../></>}
|
||||
// tabs={<Tabs ...><TabList ...>{...}</TabList></Tabs>}
|
||||
// />
|
||||
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
interface PageHeaderProps {
|
||||
title: string;
|
||||
badge?: number | string;
|
||||
subtitle?: string;
|
||||
controls?: ReactNode;
|
||||
tabs?: ReactNode;
|
||||
}
|
||||
|
||||
export const PageHeader = ({ title, badge, subtitle, controls, tabs }: PageHeaderProps) => (
|
||||
<div className="shrink-0">
|
||||
{/* Row 1: title + controls */}
|
||||
<div className="flex items-center justify-between px-6 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<h1 className="text-lg font-bold text-primary">{title}</h1>
|
||||
{badge != null && (
|
||||
<span className="inline-flex items-center justify-center rounded-full bg-brand-secondary px-2 py-0.5 text-xs font-semibold text-white">
|
||||
{badge}
|
||||
</span>
|
||||
)}
|
||||
{subtitle && (
|
||||
<span className="text-sm text-tertiary ml-1">{subtitle}</span>
|
||||
)}
|
||||
</div>
|
||||
{controls && (
|
||||
<div className="flex items-center gap-2">
|
||||
{controls}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Row 2: optional tabs — no container border, tab underline is the separator */}
|
||||
{tabs && (
|
||||
<div className="px-6">
|
||||
{tabs}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
Reference in New Issue
Block a user