From 80be7b43001ade289c712d6d7bc9bfd67077c606 Mon Sep 17 00:00:00 2001
From: william garrity <wgarrity@mieweb.com>
Date: Tue, 3 Feb 2026 19:11:27 -0500
Subject: [PATCH] feat(PageHeader): add Lucide icon selector and iconAlign prop

Stories improvements:
- Add interactive icon dropdown control with 15 Lucide React icons
  (Home, Settings, User, Users, Calendar, FileText, Building,
  Briefcase, Chart, Shield, Bell, Search, Stethoscope, Hospital,
  ClipboardList)
- Add iconAlign radio control to toggle between 'top' and 'center'
- Disable controls for ReactNode props (actions, children) to prevent
  Storybook serialization errors

Component enhancements:
- Add iconAlign prop with 'top' | 'center' options (default: 'center')
- When iconAlign='top', icon aligns with the top of title/subtitle
  instead of vertically centering
- Adds subtle mt-1 offset when top-aligned for better visual balance
---
 .../PageHeader/PageHeader.stories.tsx         | 57 +++++++++++++++++++
 src/components/PageHeader/PageHeader.tsx      | 15 ++++-
 2 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/src/components/PageHeader/PageHeader.stories.tsx b/src/components/PageHeader/PageHeader.stories.tsx
index 0ccd4213..65e4ea65 100644
--- a/src/components/PageHeader/PageHeader.stories.tsx
+++ b/src/components/PageHeader/PageHeader.stories.tsx
@@ -1,11 +1,68 @@
 import type { Meta, StoryObj } from '@storybook/react';
 import { PageHeader } from './PageHeader';
 import { Button } from '../Button/Button';
+import {
+  HomeIcon,
+  SettingsIcon,
+  UserIcon,
+  UsersIcon,
+  CalendarIcon,
+  FileTextIcon,
+  BuildingIcon,
+  BriefcaseIcon,
+  ChartIcon,
+  ShieldIcon,
+  BellIcon,
+  SearchIcon,
+  StethoscopeIcon,
+  HospitalIcon,
+  ClipboardListIcon,
+} from '../Icons';
+import type { LucideIcon } from 'lucide-react';
+
+const iconMap: Record<string, LucideIcon> = {
+  Home: HomeIcon,
+  Settings: SettingsIcon,
+  User: UserIcon,
+  Users: UsersIcon,
+  Calendar: CalendarIcon,
+  FileText: FileTextIcon,
+  Building: BuildingIcon,
+  Briefcase: BriefcaseIcon,
+  Chart: ChartIcon,
+  Shield: ShieldIcon,
+  Bell: BellIcon,
+  Search: SearchIcon,
+  Stethoscope: StethoscopeIcon,
+  Hospital: HospitalIcon,
+  ClipboardList: ClipboardListIcon,
+};
 
 const meta: Meta<typeof PageHeader> = {
   title: 'Components/PageHeader',
   component: PageHeader,
   tags: ['autodocs'],
+  argTypes: {
+    actions: { control: false },
+    icon: {
+      control: 'select',
+      options: ['None', ...Object.keys(iconMap)],
+      mapping: {
+        None: undefined,
+        ...Object.fromEntries(
+          Object.entries(iconMap).map(([name, Icon]) => [
+            name,
+            <Icon key={name} className="h-6 w-6" />,
+          ])
+        ),
+      },
+    },
+    iconAlign: {
+      control: 'radio',
+      options: ['top', 'center'],
+    },
+    children: { control: false },
+  },
   parameters: {
     layout: 'padded',
   },
diff --git a/src/components/PageHeader/PageHeader.tsx b/src/components/PageHeader/PageHeader.tsx
index 5516a3e0..88f5a870 100644
--- a/src/components/PageHeader/PageHeader.tsx
+++ b/src/components/PageHeader/PageHeader.tsx
@@ -9,6 +9,8 @@ export interface PageHeaderProps {
   subtitle?: string;
   /** Optional icon to display before the title */
   icon?: React.ReactNode;
+  /** Vertical alignment of the icon */
+  iconAlign?: 'top' | 'center';
   /** Action buttons or controls to display on the right */
   actions?: React.ReactNode;
   /** Additional content below the title (e.g., breadcrumbs, tabs) */
@@ -29,6 +31,7 @@ export function PageHeader({
   title,
   subtitle,
   icon,
+  iconAlign = 'center',
   actions,
   children,
   className = '',
@@ -51,10 +54,16 @@ export function PageHeader({
     <div
       className={` ${sizeClasses[size]} ${bordered ? 'border-b border-gray-200 dark:border-gray-700' : ''} ${className} `.trim()}
     >
-      <div className="flex items-center justify-between gap-4">
-        <div className="flex min-w-0 items-center gap-3">
+      <div
+        className={`flex justify-between gap-4 ${iconAlign === 'top' ? 'items-start' : 'items-center'}`}
+      >
+        <div
+          className={`flex min-w-0 gap-3 ${iconAlign === 'top' ? 'items-start' : 'items-center'}`}
+        >
           {icon && (
-            <div className="flex-shrink-0 text-gray-500 dark:text-gray-400">
+            <div
+              className={`flex-shrink-0 text-gray-500 dark:text-gray-400 ${iconAlign === 'top' ? 'mt-1' : ''}`}
+            >
               {icon}
             </div>
           )}
