fix: Separate mobile/desktop sidebar components
- Mobile: fixed overlay sidebar with proper z-index - Desktop: sticky sidebar with correct top offset - Extracted SidebarContent component to avoid duplication - Matches App.tsx submenu bar positioning logic
This commit is contained in:
@@ -27,14 +27,15 @@ export default function Help() {
|
|||||||
const currentSlug = searchParams.get('doc') || 'getting-started';
|
const currentSlug = searchParams.get('doc') || 'getting-started';
|
||||||
|
|
||||||
// Calculate sticky top position based on mode
|
// Calculate sticky top position based on mode
|
||||||
// Standalone/fullscreen mode: top-16 (below 64px header)
|
// This matches the submenu bar logic in App.tsx:
|
||||||
// WP Admin mode: top-[calc(7rem+32px)] (header + topnav + wp-admin bar)
|
// - Standalone/fullscreen: top-0 (header already handles offset)
|
||||||
const sidebarTopClass = isStandalone
|
// - WP Admin: top-[calc(7rem+32px)] = 144px (header 64px + topnav 48px + wp-admin bar 32px)
|
||||||
? 'top-16'
|
const sidebarStickyTop = isStandalone
|
||||||
|
? 'top-0'
|
||||||
: 'top-[calc(7rem+32px)]';
|
: 'top-[calc(7rem+32px)]';
|
||||||
|
|
||||||
// Height calculation: full height minus header
|
// Height calculation matches App.tsx Sidebar pattern
|
||||||
const sidebarHeightClass = isStandalone
|
const sidebarHeight = isStandalone
|
||||||
? 'h-[calc(100vh-64px)]'
|
? 'h-[calc(100vh-64px)]'
|
||||||
: 'h-[calc(100vh-7rem-32px)]';
|
: 'h-[calc(100vh-7rem-32px)]';
|
||||||
|
|
||||||
@@ -53,7 +54,6 @@ export default function Help() {
|
|||||||
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
setSections(data.sections);
|
setSections(data.sections);
|
||||||
// Expand all sections by default
|
|
||||||
const expanded: Record<string, boolean> = {};
|
const expanded: Record<string, boolean> = {};
|
||||||
data.sections.forEach((section: DocSection) => {
|
data.sections.forEach((section: DocSection) => {
|
||||||
expanded[section.key] = true;
|
expanded[section.key] = true;
|
||||||
@@ -85,8 +85,8 @@ export default function Help() {
|
|||||||
const isActive = (slug: string) => slug === currentSlug;
|
const isActive = (slug: string) => slug === currentSlug;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-0">
|
<div className="flex">
|
||||||
{/* Mobile menu button */}
|
{/* Mobile menu button - only show on small screens */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
@@ -96,20 +96,80 @@ export default function Help() {
|
|||||||
{sidebarOpen ? <X className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
|
{sidebarOpen ? <X className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{/* Sidebar - sticky on desktop, fixed on mobile */}
|
{/* Backdrop for mobile sidebar */}
|
||||||
|
{sidebarOpen && (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 bg-black/50 z-30 lg:hidden"
|
||||||
|
onClick={() => setSidebarOpen(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Mobile sidebar - fixed overlay */}
|
||||||
<aside
|
<aside
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-72 border-r bg-muted/30 flex-shrink-0 overflow-y-auto",
|
"lg:hidden fixed left-0 z-40 w-72 bg-background border-r overflow-y-auto",
|
||||||
// Mobile: fixed position covering from below header
|
sidebarStickyTop,
|
||||||
"fixed left-0 z-40",
|
sidebarHeight,
|
||||||
sidebarTopClass,
|
sidebarOpen ? "block" : "hidden"
|
||||||
sidebarHeightClass,
|
|
||||||
// Desktop: sticky instead of fixed
|
|
||||||
"lg:sticky",
|
|
||||||
sidebarOpen ? "block" : "hidden lg:block"
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="p-4 border-b bg-muted/30">
|
<SidebarContent
|
||||||
|
loading={loading}
|
||||||
|
sections={sections}
|
||||||
|
expandedSections={expandedSections}
|
||||||
|
toggleSection={toggleSection}
|
||||||
|
selectDoc={selectDoc}
|
||||||
|
isActive={isActive}
|
||||||
|
/>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Desktop sidebar - sticky */}
|
||||||
|
<aside
|
||||||
|
className={cn(
|
||||||
|
"hidden lg:block w-72 flex-shrink-0 border-r bg-muted/30 overflow-y-auto sticky",
|
||||||
|
sidebarStickyTop,
|
||||||
|
sidebarHeight
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<SidebarContent
|
||||||
|
loading={loading}
|
||||||
|
sections={sections}
|
||||||
|
expandedSections={expandedSections}
|
||||||
|
toggleSection={toggleSection}
|
||||||
|
selectDoc={selectDoc}
|
||||||
|
isActive={isActive}
|
||||||
|
/>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Main content - uses page scroll */}
|
||||||
|
<main className="flex-1 min-w-0">
|
||||||
|
<div className="max-w-4xl mx-auto py-6 px-6 lg:px-10">
|
||||||
|
<DocContent slug={currentSlug} />
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extracted sidebar content to avoid duplication
|
||||||
|
function SidebarContent({
|
||||||
|
loading,
|
||||||
|
sections,
|
||||||
|
expandedSections,
|
||||||
|
toggleSection,
|
||||||
|
selectDoc,
|
||||||
|
isActive,
|
||||||
|
}: {
|
||||||
|
loading: boolean;
|
||||||
|
sections: DocSection[];
|
||||||
|
expandedSections: Record<string, boolean>;
|
||||||
|
toggleSection: (key: string) => void;
|
||||||
|
selectDoc: (slug: string) => void;
|
||||||
|
isActive: (slug: string) => boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="p-4 border-b bg-muted/30 sticky top-0">
|
||||||
<h2 className="text-lg font-semibold flex items-center gap-2">
|
<h2 className="text-lg font-semibold flex items-center gap-2">
|
||||||
<Book className="w-5 h-5" />
|
<Book className="w-5 h-5" />
|
||||||
Documentation
|
Documentation
|
||||||
@@ -161,22 +221,6 @@ export default function Help() {
|
|||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
</aside>
|
</>
|
||||||
|
|
||||||
{/* Backdrop for mobile */}
|
|
||||||
{sidebarOpen && (
|
|
||||||
<div
|
|
||||||
className="fixed inset-0 bg-black/50 z-30 lg:hidden"
|
|
||||||
onClick={() => setSidebarOpen(false)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Main content - uses page scroll, not internal overflow */}
|
|
||||||
<main className="flex-1 min-w-0">
|
|
||||||
<div className="max-w-4xl mx-auto py-6 px-6 lg:px-10">
|
|
||||||
<DocContent slug={currentSlug} />
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user