fix: Sticky header offset for fullscreen vs WP-Admin modes

Problem:
- Fullscreen: Sticky header covered by submenu bar
- WP-Admin: Sticky header working correctly

Root Cause:
Different layout structures in each mode:

Fullscreen Mode:
<main overflow-auto>
  <SubmenuBar sticky> ← Inside scrollable
  <SettingsLayout>
    <div sticky top-0> ← Covered by submenu!

WP-Admin Mode:
<SubmenuBar sticky> ← Outside scrollable
<main overflow-auto>
  <SettingsLayout>
    <div sticky top-0> ← Works fine

Solution:
Detect fullscreen mode and apply correct offset:
- Fullscreen: top-[49px] (offset by submenu height)
- WP-Admin: top-0 (no offset needed)

Implementation:
1. MutationObserver to detect .woonoow-fullscreen-root class
2. Dynamic sticky position based on mode
3. Re-checks on mode toggle

Code:
const [isFullscreen, setIsFullscreen] = useState(false);

useEffect(() => {
  const checkFullscreen = () => {
    setIsFullscreen(document.querySelector('.woonoow-fullscreen-root') !== null);
  };

  const observer = new MutationObserver(checkFullscreen);
  observer.observe(document.body, {
    attributes: true,
    attributeFilter: ['class'],
    subtree: true
  });

  return () => observer.disconnect();
}, []);

const stickyTop = isFullscreen ? 'top-[49px]' : 'top-0';

Result:
 Fullscreen: Header below submenu (49px offset)
 WP-Admin: Header at top (0px offset)
 Smooth transition when toggling modes
 Gap maintained in both modes (mb-6)

Files Modified:
- SettingsLayout.tsx: Dynamic sticky positioning
This commit is contained in:
dwindown
2025-11-06 14:51:07 +07:00
parent 9b0b2b53f9
commit 7538316afb

View File

@@ -33,11 +33,31 @@ export function SettingsLayout({
} }
}; };
// Detect fullscreen mode
const [isFullscreen, setIsFullscreen] = React.useState(false);
React.useEffect(() => {
const checkFullscreen = () => {
setIsFullscreen(document.querySelector('.woonoow-fullscreen-root') !== null);
};
checkFullscreen();
// Re-check on route changes or mode toggles
const observer = new MutationObserver(checkFullscreen);
observer.observe(document.body, { attributes: true, attributeFilter: ['class'], subtree: true });
return () => observer.disconnect();
}, []);
// In fullscreen: submenu is inside scrollable area, so offset by submenu height (49px)
// In WP-Admin: submenu is outside scrollable area, so no offset needed (top-0)
const stickyTop = isFullscreen ? 'top-[49px]' : 'top-0';
return ( return (
<div className="space-y-6"> <div className="space-y-6">
{/* Sticky Header with Save Button - Edge to edge */} {/* Sticky Header with Save Button - Edge to edge */}
{onSave && ( {onSave && (
<div className="sticky top-0 z-10 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 -mx-4 px-4 mb-6"> <div className={`sticky ${stickyTop} z-10 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 -mx-4 px-4 mb-6`}>
<div className="container px-0 max-w-5xl mx-auto py-3 flex items-center justify-between"> <div className="container px-0 max-w-5xl mx-auto py-3 flex items-center justify-between">
<div> <div>
<h1 className="text-lg font-semibold">{title}</h1> <h1 className="text-lg font-semibold">{title}</h1>