The panel
The header row, the toolbar row, and the two gates that are easily confused.
<DevtoolsOverlay /> renders a draggable floating button. Tapping it opens a full-screen modal; the
button itself never appears inside the modal.
Header row
| Item | What it does |
|---|---|
| Tab bar | Network, Console, Performance, Storage, Crashes, Debug. Scrolls horizontally on a narrow screen. |
| Error badge | A red count on the Console tab when it is not the active tab, showing captured console.errors. The Crashes tab carries the same badge for unread reports. |
| Palette (🎨) | Opens the theme list; the active one is ticked. Applies immediately. |
| Close (✕) | Dismisses the panel. Recording carries on while it is closed. |
The tab you last had open is remembered for the life of the app process, so reopening the panel returns you to it. Only the active tab is mounted, so switching tabs and back resets that tab's filters, its open detail sheet and its scroll position. Captured data is untouched: it lives in the stores, not the views.
Toolbar row
On the three tabs that record — Network, Console, Performance — it opens with the same two controls:
| Control | What it does |
|---|---|
| Record (⏺) | Pauses and resumes capture for that tab. Red when recording, hollow when paused. |
| Clear (⊘) | Throws away everything that tab has collected. Not undoable. |
Not every tab has one:
- Storage has no record button, on purpose: it reads on demand rather than recording, so there is no stream to pause, and a clear button there would mean wiping your storage rather than dropping a log. It opens with Refresh instead.
- Crashes has a clear button but no record button — a crash is not a stream you can afford to have switched off.
- Debug has no toolbar at all: nothing there records or collects.
The two gates
Pausing and .init() are different switches, and the difference matters when you ship.
| Gate | Set by | What it does |
|---|---|---|
.init() | Your call, once at startup | Until it runs, nothing is patched, observed or recorded anywhere. There is no UI for it. |
| Record | The record button in a toolbar | Pauses a tab that .init() already turned on. |
disabledByDefault in the config sets the record gate, not the .init() one, so a tab that starts
paused can always be started from its own toolbar.
.init() controls both capture and access: the overlay subscribes to whether .init()
finished and draws nothing until it has, so an unguarded mount in a release build shows no button
rather than a panel over empty lists. There is no config flag that says "off" — not calling .init()
is what says it.
The one thing the overlay keeps rendering is the crash report sheet, which is meant to work in production. Guarding the mount as well is still worth doing; it just is not what keeps the panel out.