@versini/ui-debug-overlay
v2.2.1
Published
[](https://www.npmjs.com/package/@versini/ui-debug-overlay) .
@versini/ui-debug-overlay lets you:
- Automatically snapshot an
appStateobject on referential changes - Push manual, labeled, color‑coded snapshots from anywhere (via a hook)
- Target snapshots to specific overlay instances
- Copy a merged chronological timeline (always includes manual snapshots)
- Clear everything in a click
- Position the panel with shorthands or explicit edges
- Keep bundle weight minimal (inline styles only, no CSS frameworks)
Features
- ⚡ Zero Config – Drop in and pass
appState - 🔄 Auto State Capture – Retains a rolling window (FIFO) of snapshots
- 📝 Manual Snapshots – Arbitrary data logging with labels & colors
- 🎯 Targetable – Route manual events to named overlays
- 🪄 Cycle‑Safe JSON – Deterministic, circular reference tolerant stringify
- 📋 One‑Click Copy – Chronological timeline, numbering stable regardless of UI order
- 🧹 Clear Control – Reset buffer instantly
- 📐 Flexible Position – Shorthands or
{ top/right/bottom/left } - 🔍 Order Toggle – Show newest first while numbering still reflects true time
- 🪶 Lightweight – Pure inline styling, TypeScript types
Installation
npm install @versini/ui-debug-overlayPeer deps: react, react-dom.
Quick Start
import { DebugOverlay } from "@versini/ui-debug-overlay";
export function App() {
const appState = { user: { id: 1, name: "Ada" }, online: true };
return (
<>
<YourRealApp />
<DebugOverlay appState={appState} />
</>
);
}Manual Snapshots
Use the hook to push ad‑hoc snapshots (successful responses, errors, timings, etc.).
import { useDebugOverlay, LOG_GREEN, LOG_RED } from "@versini/ui-debug-overlay";
function SomeLogic() {
const debug = useDebugOverlay();
async function run() {
debug("start", { ts: Date.now() });
try {
const data = await fetch("/api/data").then((r) => r.json());
debug("success", data, LOG_GREEN);
} catch (e) {
debug("error", { message: (e as Error).message }, LOG_RED);
}
}
return <button onClick={run}>Run</button>;
}Multiple / Targeted Overlays
const debug = useDebugOverlay();
debug("metrics", { fps: 60 }, { targetOverlays: ["perf"] });
debug("state-change", someStateSlice); // broadcast to all overlays
return (
<>
<DebugOverlay overlayId="perf" position="left" title="Performance" />
<DebugOverlay
overlayId="main"
position="right"
title="Main State"
appState={rootState}
/>
</>
);Rules:
- Omit
targetOverlays(or empty array) ⇒ broadcast - Non‑empty array ⇒ deliver only to overlays whose
overlayIdmatches - Buffered (pre‑mount) manual snapshots still respect targeting when overlays mount
Positioning
<DebugOverlay position="bottom-right" />
<DebugOverlay position="left" /> {/* alias of top-left */}
<DebugOverlay position={{ bottom: "8px", left: "8px" }} />Supported shorthands: left, right, top, bottom, top-left, top-right, bottom-left, bottom-right.
Copy Behavior
Pressing "Copy" produces a plain text timeline. Chronological numbering always starts at #1 (oldest), even if UI order shows newest first. Manual snapshots are always included.
Collapsing
<DebugOverlay initialCollapsed />Props
| Prop | Type | Default | Description |
| ---------------------------- | -------------------------- | ------------ | -------------------------------------------------------------------- | ---------------------------------------------------- |
| appState | unknown | – | Value to snapshot on reference change. Omit for manual‑only overlay. |
| title | string | "AppState" | Panel header. |
| initialCollapsed | boolean | false | Start minimized. |
| overlayId | string | "default" | Name used for targeted manual snapshots. |
| position | shorthand | partial edges | – | Placement via shorthand or { top/right/bottom/left }. |
| maxBodyHeight | number | string | 320 | Scroll region max height. |
| indent | number | 2 | JSON indent spaces. |
| maxSnapshots | number | 50 | Retained automatic state snapshot cap (FIFO). |
| maxVisibleSnapshots | number | 10 | Visible snapshot limit; remainder summarized. |
| snapshotOrder | "asc" | "desc" | "desc" | Visual ordering only. Numbering stays chronological. |
| appendSnapshotCountInTitle | boolean | false | Append live count to title. |
Hook: useDebugOverlay()
const debug = useDebugOverlay();
debug(
label: string,
data: unknown,
options?: LogColor | { color?: LogColor; targetOverlays?: string[] }
);Color constants: LOG_YELLOW, LOG_GREEN, LOG_BLUE, LOG_MAGENTA, LOG_RED (yellow is default fallback).
Tips
- Keep
maxVisibleSnapshotssmall (1–3) on narrow/mobile viewports - Derive / shape very large objects before passing to reduce noise & stringify cost
- Multiple overlays can focus on separate domains (state vs. performance vs. network)
- Use colors to visually cluster snapshot categories (success, error, timing)
License
MIT © Arno Versini
