refactor: Move page header outside content container using context

Problem:
- Page header inside scrollable content container
- Complex sticky positioning logic
- Different behavior in different modes

Better Architecture:
Move page header to same level as submenu, outside scroll container

Structure:
<main flex flex-col>
  <SubmenuBar sticky>           ← Sticky outside scroll
  <PageHeader sticky>            ← Sticky outside scroll 
  <div overflow-auto>            ← Only content scrolls
    <AppRoutes />

Implementation:
1. PageHeaderContext - Global state for page header
   - title: string
   - action: ReactNode (e.g., Save button)
   - setPageHeader() / clearPageHeader()

2. PageHeader Component - Renders at app level
   - Positioned after submenu
   - Sticky top-[49px] (below submenu)
   - Boxed layout (max-w-5xl, centered)
   - Consumes context

3. SettingsLayout - Sets header via context
   - useEffect to set/clear header
   - No inline sticky header
   - Cleaner component

Benefits:
 Page header outside scroll container
 Sticky works consistently (no mode detection)
 Submenu layout preserved (justify-start)
 Page header uses page layout (boxed, centered)
 Separation of concerns
 Reusable for any page that needs sticky header

Layout Hierarchy:
┌─────────────────────────────────────┐
│ <main flex flex-col>                │
│   ┌─────────────────────────────┐   │
│   │ SubmenuBar (sticky)         │   │ ← justify-start
│   ├─────────────────────────────┤   │
│   │ PageHeader (sticky)         │   │ ← max-w-5xl centered
│   ├─────────────────────────────┤   │
│   │ <div overflow-auto>         │   │
│   │   Content (scrolls)         │   │
│   └─────────────────────────────┘   │
└─────────────────────────────────────┘

Files Created:
- PageHeaderContext.tsx: Context provider
- PageHeader.tsx: Header component

Files Modified:
- App.tsx: Added PageHeader after submenu in all layouts
- SettingsLayout.tsx: Use context instead of inline header

Result:
 Clean architecture
 Consistent sticky behavior
 No mode-specific logic
 Reusable pattern
This commit is contained in:
dwindown
2025-11-06 15:34:00 +07:00
parent 99748ca202
commit 2ec76c7dec
4 changed files with 98 additions and 28 deletions

View File

@@ -0,0 +1,19 @@
import React from 'react';
import { usePageHeader } from '@/contexts/PageHeaderContext';
export function PageHeader() {
const { title, action } = usePageHeader();
if (!title) return null;
return (
<div className="sticky top-[49px] z-10 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container max-w-5xl mx-auto px-4 py-3 flex items-center justify-between">
<div>
<h1 className="text-lg font-semibold">{title}</h1>
</div>
{action && <div>{action}</div>}
</div>
</div>
);
}