Files
siftlode/frontend/src/components/ui/stickyTop.ts
T
peter 6fda49369f fix(ui): a sticky table header turns the scroller's top fade off itself; DataTable renders one layout
- "A page with a sticky ColumnHead must declare fadeTop: false" lived in
  prose: a registry flag on three pages plus an App special case for the
  Channels card layout, and the next table page would have re-acquired the
  fade-on-the-header defect with every lane green. ColumnHead now registers
  itself with the enclosing PageScroller (ui/stickyTop) while mounted; the
  registry flag, the App branch and the prop plumbing are gone. Measured on
  localdev: the top mask is 0px under Channels' and Audit's headers, 20px on
  Home and the Feed.
- ui/DataTable mounted its table AND its card list at every width, one
  hidden by CSS: double DOM and render cost, duplicate ids, two keyboard
  copies of every row. It now mounts the one the `md` media query calls for
  (lib/useMediaQuery); the keyboard test asserts one layout at each width.
- The Plex module's content width went px → rem with the rest of the page.
2026-09-19 07:51:33 +02:00

18 lines
1001 B
TypeScript

import { createContext, useContext, useLayoutEffect } from "react";
// A sticky element at the very top of the page scroller (a table's sticky header) and the
// scroller's top fade cannot coexist: the fade sits ON the header and flips on with the first
// scroll. Pages used to opt out by hand — a `fadeTop: false` in the module registry, plus an App
// special case for the Channels card layout, which has no sticky header — and the next table page
// would have re-acquired the defect with every lane green. Now the sticky element says so itself:
// while it is mounted the enclosing `PageScroller` keeps its top edge crisp.
const StickyTopContext = createContext<(() => () => void) | null>(null);
export const StickyTopProvider = StickyTopContext.Provider;
/** Call from a component that renders a sticky element at the top of the page scroller. */
export function useStickyTop(): void {
const register = useContext(StickyTopContext);
useLayoutEffect(() => register?.(), [register]);
}