Files
siftlode/frontend/src/lib/toastDock.ts
T
peter 2d9595b0e5 feat(ui): a control can dock under the toasts and ride every toast host
The toast stack already has a host in the page and in every overlay (dialogs,
both players, the fullscreen player), the topmost one shows it, and inside an
overlay it sits above the player's control band. lib/toastDock lets one control
use exactly that placement; it renders outside the live region, so a ticking
control is not read out every second.
2026-09-19 22:08:10 +02:00

28 lines
1.4 KiB
TypeScript

import type { ComponentType } from "react";
import { createStore } from "./store";
// A control that lives where the toasts live, under them (E16: the debug recorder's pill).
//
// The toast stack already solves the hard part of "always visible, never in the way": it has a host
// in the page and one inside every overlay — the dialogs, both players, the fullscreen player — the
// topmost host shows it, and inside an overlay it sits above the player's control band. A control
// that must stay reachable while the user reproduces a bug anywhere needs exactly that, so it rides
// the same hosts instead of rebuilding them: `ui/Toaster` renders whatever is docked here below its
// stack, in the host that is on top.
//
// One slot, not a list: one surface uses it, and a second would have to decide how they share the
// corner before this grows.
const docked = createStore<ComponentType | null>(null);
/** Dock `component` under the toasts until the returned function undocks it. */
export function dockUnderToasts(component: ComponentType): () => void {
// Always the updater form: a component IS a function, so `set(component)` would be taken for one
// and called with the previous value instead of stored.
docked.set(() => component);
return () =>
docked.set((current: ComponentType | null) => (current === component ? null : current));
}
/** What is docked (the Toaster reads it). */
export const useToastDock = (): ComponentType | null => docked.use();