let a maximized panel take the whole window, header included

Maximize had one depth: fill the content region, leave the nav header visible. That was never a choice
about how much room to take — the region is an `absolute z-2` stacking context and the header is a
`fixed z-10` sibling, so no z-index a panel gives itself can paint over the nav. `top-[56px]` was the
workaround.

So full screen is cooperative rather than a bigger overlay. The panel asks, and the shell hides its own
header for it; `inset-0` is then genuinely the window. Still the same element and the same class swap —
no portal, no remount, so scroll position and playback survive the step between depths the way they
already survived maximize.

The mode rides beside the maximized panel id in sessionStorage as one value, so the two cannot drift;
a tab open across this change reads the old bare string, gets undefined for `.id`, and lands on
"nothing is maximized".

The toggle is offered from every state, so taking the window is one click from a tiled panel, and it
steps back to a maximized panel rather than all the way out. The amber light is present at both depths
and always goes all the way out, so neither is a trap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-08 21:56:58 +01:00
co-authored by Claude Opus 5
parent 9974736587
commit 417860b892
10 changed files with 301 additions and 65 deletions
@@ -53,14 +53,20 @@ function EditablePageTitle() {
type HeaderProps = {
dockItems?: DockItem[];
/**
* Stand down for a panel that has taken the whole window. `display: none` rather than an unmount: the
* header holds a half-typed tab rename and its own popovers, and a panel going fullscreen is not a
* reason to throw those away. It is `fixed`, so hiding it costs no layout shift either.
*/
hidden?: boolean;
};
export function Header({ dockItems }: HeaderProps) {
export function Header({ dockItems, hidden }: HeaderProps) {
const [open, setOpen] = useState(false);
const isTouch = useIsTouch();
return (
<header className="fixed z-10 w-full">
<header className={`fixed z-10 w-full ${hidden ? 'hidden' : ''}`}>
<div
className="relative shrink-0 border-b backdrop-blur-xl shadow-lg px-3 py-2 md:px-6 md:py-3 flex items-center justify-between"
style={{ backgroundColor: 'rgba(255, 255, 255, 0.25)', borderColor: 'rgba(255, 255, 255, 0.35)' }}