Add developer-mode overlay shell with devLog and triggers - #21
Open
djscruggs wants to merge 8 commits into
Open
Conversation
Add the spec for the generic dev-mode shell (localStorage flag gate, overlay panel, and registerDevTool() registration API) that mounts via @bedrock/vue's beforeMount app-bootstrap hook. The trigger is app-owned and the overlay accepts a toggle signal rather than installing a global key listener. Domain tools (e.g. the wallet's paste-exchange-URL and seed-credentials) are registered by consuming libraries. Spec only; no implementation in this commit.
Adds the generic dev-mode shell to @bedrock/vue: a localStorage flag gate (bedrock.devMode), a tool-registration API (registerDevTool), an overlay panel rendered as a sibling of the root Vue app, and a toggle signal the host app drives. The overlay is lazily loaded as its own chunk only when the flag is set, so production builds are unaffected. An opt-in createTripleKeyDetector helper is provided for apps that want a key trigger; the shell does not install a global key listener itself. DevToolExample.vue is a docs-only reference tool and is not registered automatically. Domain tools (and the data they touch) stay with the consumer that registers them.
The overlay panel now docks as a right-hand rail on tablet and desktop widths and becomes a full-width bottom sheet (about 70% height, rounded top corners) on phone-sized viewports under 600px, via a CSS media query. No change to the overlay's behavior, registry, or toggle logic.
Adds a console.log-style API, devLog() with devLog.info/warn/error, for logging values to the dev-mode overlay with no setup. When dev mode is on, the shell auto-registers a built-in "Log" tool that renders each entry by type: text for strings and primitives, collapsible pretty JSON for objects and arrays, message and stack for Errors, and a dimmed literal for null/undefined. URLs in text entries become clickable links with a copy button. The buffer keeps the most recent 50 entries; getDevLogEntries() and clearDevLog() are also exported. The Log tool is lazily loaded into the existing dev-mode chunk, so it adds nothing to production when the flag is off.
The triple-key trigger is unusable on mobile, so this adds an opt-in corner-tap trigger: tapping a configurable screen corner a number of times in quick succession (default top-right, 5 taps within 2s) fires a callback the host app wires to toggleDevOverlay(). The corner hit-zone is small and invisible, so normal taps are unaffected. Like createTripleKeyDetector(), it is opt-in and not installed by the shell.
- Make devLog() a true no-op when dev mode is off: _add() now returns early instead of building and buffering entries nothing can display, matching the documented behavior. - Simplify value classification: fold the unused "primitive" kind into "text" since the renderer treats strings, numbers, and booleans identically. - Note in the trigger detectors that the time window is enforced between consecutive presses, not by a timer. - Add a "superseded by implementation" note to the spec, which still described the wallet-era design (wallet.devMode, Quasar, WalletLayout). - Remove the internal implementation plan doc from the repo; the spec is the canonical design record.
Per review, a separate devLog() API was a second way to log: it would only show calls that explicitly used it, missing the console.* output that other layers of the stack already emit. Replace it with a console mirror — when dev mode is on, the common console methods (log, info, debug, warn, error) are both forwarded to the real console and captured for the built-in Log tool, so existing console.* calls anywhere appear in the overlay with no code changes and there is a single way to log. Other console methods (group, table, trace, ...) are left untouched. Removes lib/devLog.js; adds lib/consoleMirror.js with installConsoleMirror()/uninstallConsoleMirror() and the existing getDevLogEntries()/clearDevLog(). The Log tool now renders each console call's arguments (varargs) by type.
The dev-tool registry is a reactive Map, which caused Vue to deep-wrap each registered component definition and emit a "Vue received a Component that was made a reactive object" warning on first overlay open. Wrap the component with markRaw() on registration so the registry still tracks add/remove reactively without making the component itself reactive.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a developer-only overlay shell to
@bedrock/vue— a generic, reusable devpanel that any consuming bedrock web app or library can populate with its own
debugging tools. It is off by default and ships nothing to end users unless a
developer explicitly enables it. Design follows
docs/dev-mode-spec.md.Origin/decisions: this started as a wallet feature in
digitalbazaar/bedrock-vue-wallet#131; review concluded the shell is not
wallet-specific and should live in
@bedrock/vue, with the trigger app-owned(the overlay accepts a toggle signal rather than installing a global listener).
Domain tools (paste-exchange-URL, seed-credentials) stay in the wallet.
What's here
isDevModeEnabled()readslocalStorage['bedrock.devMode'];when off, the overlay chunk is never loaded (zero production behavior change).
DevModeOverlay.vue, plain Vue + scoped CSS (no Quasardependency), auto-mounted as a sibling of the root app during
bootstrap(),lazily loaded into a
bedrock-vue-devmodechunk. Responsive: right-hand railon tablet/desktop, bottom sheet on phone.
registerDevTool({id, label, component}),unregisterDevTool(),getDevTools().DevToolExample.vueis anunregistered docs sample. (Components are
markRaw'd on registration so thereactive registry doesn't deep-wrap the component definition.)
console.*mirror — there is no separate logging API. When dev mode ison, the common console methods (
log/info/debug/warn/error) aremirrored into a built-in "Log" tool, so existing
console.*calls anywhere inthe stack show up in the overlay with no code changes (calls are still
forwarded to the real console). Entries render by type — text, collapsible
JSON, error + stack, dimmed null/undefined — and turn URLs in text into
clickable links. Other methods (
group/table/trace/…) pass throughuntouched.
installConsoleMirror()/uninstallConsoleMirror()are exportedfor hosts that want manual control.
createTripleKeyDetector()(desktop key trigger) andcreateTapTrigger()(corner multi-tap for touch devices). The shell installsneither; the host app wires whichever to
toggleDevOverlay().Out of scope
Wallet domain tools (paste-exchange-URL, seed-credentials, VC fixtures) and the
QR-code decoded-URL display stay in
bedrock-vue-wallet.Testing
npm run lintpasses (0 errors).CI is lint-only), so CI passing does not exercise behavior.
real shell files: overlay mount/toggle, the
console.*mirror (includingpre-existing console calls appearing with no changes), typed rendering
(text / collapsible JSON / error + stack / dimmed null / clickable + copyable
URLs),
registerDevTool, responsive layouts, and both triggers (key, andcorner-tap positive + negative cases). No runnable bedrock app exists in this
repo for an in-repo browser test.
Privacy / security
No customer or personal data. Off by default; no new network surface (the shell
only provides a panel + open/close mechanism — registered tools own their data).
🤖 Generated with Claude Code