Task #448: remove gap under Notes header by switching back to sticky

Task #446 made the Notes header `position: fixed` and added an
aria-hidden spacer below it sized to the header's measured height
(via ResizeObserver). The spacer was exactly the "big empty band"
the user kept seeing between the header bar and the
"اكتب ملاحظة..." composer — the page background gradient showed
through the reserved space.

Switched the header back to `sticky top-0 z-20`. Sticky keeps it
pinned to the top of the viewport while the page scrolls, but it
stays in document flow, so the composer renders immediately under
the bar with no artificial gap. Removed the now-unused
`headerRef`, `headerHeight` state, ResizeObserver effect, and the
spacer div. Bumped composer wrapper padding from `pt-1` back to
`pt-3` for a small breathing space (no longer competing with the
spacer).

No other changes; folders rail, composer behavior, RTL/LTR all
untouched.
This commit is contained in:
riyadhafraa
2026-05-10 07:33:30 +00:00
parent fa3b56be4c
commit 4dd28a821c
+2 -31
View File
@@ -295,28 +295,6 @@ export default function NotesPage() {
const pinned = filteredNotes.filter((n) => n.isPinned);
const others = filteredNotes.filter((n) => !n.isPinned);
// The header is rendered position:fixed so it stays pinned to the top
// of the viewport even as the page scrolls. Because its height varies
// (label chips wrap, the active tab can show or hide the grid/list
// toggle, etc.), we measure it with a ResizeObserver and reserve the
// same amount of vertical space below with a spacer div — that keeps
// the first row of content from sliding under the bar.
const headerRef = useRef<HTMLDivElement | null>(null);
const [headerHeight, setHeaderHeight] = useState(0);
useEffect(() => {
const el = headerRef.current;
if (!el) return;
const update = () => setHeaderHeight(el.offsetHeight);
update();
const ro = new ResizeObserver(update);
ro.observe(el);
window.addEventListener("resize", update);
return () => {
ro.disconnect();
window.removeEventListener("resize", update);
};
}, []);
// Composer is rendered above the folders area so the user can capture
// a quick note from anywhere on the active "My Notes" view without
// first drilling into a folder. It is hidden on read-only / non-owner
@@ -330,10 +308,7 @@ export default function NotesPage() {
dir={isRtl ? "rtl" : "ltr"}
data-testid="notes-page"
>
<div
ref={headerRef}
className="glass-panel border-b border-slate-200/70 px-4 py-3 fixed top-0 inset-x-0 z-30"
>
<div className="glass-panel border-b border-slate-200/70 px-4 py-3 sticky top-0 z-20">
<div className="flex items-center gap-3 flex-wrap">
<button
onClick={() => setLocation("/")}
@@ -488,13 +463,9 @@ export default function NotesPage() {
</div>
</div>
{/* Spacer reserves the same vertical space the fixed header occupies
so the first row of content doesn't slide under it. */}
<div aria-hidden style={{ height: headerHeight }} />
{showTopComposer && (
<div
className="px-4 pt-1 max-w-6xl w-full mx-auto"
className="px-4 pt-3 max-w-6xl w-full mx-auto"
data-testid="notes-top-composer"
>
<Composer