Component Showcase

Overlays & Content Scripts

These are the surfaces Tabatha injects into every page you visit: the InBar strip, the Gatekeeper, the BlockGate, and the pause sticky note. Each one is reproduced here from the shipped content-script source, down to the hardcoded colors, radii, and button labels.

InBar states

one 26px strip, five states · src/content/inbar.js

The InBar is the one piece of Tabatha that is always on screen, so it is the one that had to be smallest. It sits on the page you are actually reading and states what you said this tab was for. That is the whole job: a tab with a declared purpose is hard to drift away from without noticing, and noticing is the point. The states below are the interesting part - what it looks like when a focus is paused, when a tab has no intent at all, when an agent is driving, and when you have collapsed it down to a nub because you need the pixels back.

12:48 04:11 🎯 Q1 Report
🔗 Finalize Q1 revenue charts
📊
InBar — active
The default state. Left: intent timer (cyan) and total task timer (green) flanking the active focus. Center: the tab's intent, with the link glyph showing it is bound to that focus. Right: the full action row.
src/content/inbar.js · buildBarHTML()
⏸ PAUSED — "Was debugging line 234, check the race c…"
InBar — paused
Pausing collapses the bar to an amber strip carrying the first 40 characters of your pause note, so you can see where you left off without expanding anything. The action row drops to resume, note, and collapse.
src/content/inbar.js · buildBarHTML() paused branch
No intent set
InBar — no intent set
With no context and no focus, the timers give way to a single dash and the center becomes a red call to action. Clicking the badge opens the popup so the tab can be given a purpose.
src/content/inbar.js · .badge-no-intent
12:48 04:11 🎯 Q1 Report
🤖 AGENT 🔗 Finalize Q1 revenue charts
🍳
🤖
InBar — agent mode
When an AI agent is driving the tab, the bar takes a violet cast and the time is attributed as agent-driven rather than yours. The pan glyph appears alongside it when Let Me Cook mode is on.
src/content/inbar.js · .badge-agent / .bar.agent-mode
Default
Paused
InBar — nub (collapsed)
Collapsing the bar leaves a 22px nub pinned to the corner. It keeps its state color, so a paused session still reads as amber from across the screen and one click brings the bar back.
src/content/inbar.js · .nub / .nub.is-paused
📝 Quick Note
✓ Saved
📝
Notes panel
A scratchpad that slides out of the bar and autosaves against the current focus, task, or intent. The note glyph turns amber whenever a note exists, so the bar itself tells you there is something written down.
src/content/inbar.js · .notes-panel

Overlays & prompts

full-page interrupts and bar-anchored panels

Everything Tabatha injects that interrupts rather than informs. The Gatekeeper is the load-bearing one: open a new tab with no link behind it and it asks "Why are you here?" before the page resolves. Strict mode wants an answer, Relaxed mode takes a shrug. This is deliberate friction, applied at the one moment it is cheap - before you have started - rather than in a report you read afterwards. The rest hold lines you drew earlier: BlockGate on sites you blocked, Welcome Back after time away, the Backburner prompt when you park something you are blocked on.

Q1 Report
Was debugging line 234 — the race condition only fires when two installs sync at once. Check syncService watermark.
📌
Sticky note overlay
Come back to a paused tab and this is what greets you: the note you wrote to yourself, on paper, over the page. The tilt is randomized per note and the whole thing is deliberately analog, because a system dialog is too easy to dismiss without reading.
src/content/inbar.js · buildStickyHTML() / .sticky-note
✏️ Edit Intent
Assign to Focus
🎯 Q1 Reportactive
⏸ Learning Reactpaused
📋 Vacation Planningqueued
✏️
InBar edit dropdown
Rewrite the tab's intent or reassign it to another focus without leaving the page. Completed and resolved items are filtered out, and the list sorts active first, then paused, so the likely target is always at the top.
src/content/inbar.js · .edit-dropdown
🔥 Backburner: "Q1 Report"
Put this aside while waiting. We'll remind you to return.
Duration: mins
What will you work on instead?
— OR CREATE NEW —
🔥
Backburner prompt
For work that is blocked rather than finished. Name what you are waiting on, set a timer, and pick what you will do instead. Tabatha reopens the loop when the timer expires so the blocked item is never silently dropped.
src/content/inbar.js · .backburner-prompt
📋
Progress Check
"Q1 Report" · Elapsed: 48:12 · Timer: 60:00
Checkpoint #3
Submit with progress level:
📋
Checkpoint card
The periodic progress check. Answering costs one sentence and a single button, and the progress level is what feeds the follow-through data: five honest options including Stuck, because pretending is worse than admitting.
src/content/inbar.js · _showCPNOverlay()
Strict mode

Why are you here? Strict

Define your intent to proceed.
Relaxed mode

Why are you here? Relaxed

Define your intent to proceed.
🚪
Gatekeeper — Strict vs Relaxed
The same question in two temperaments. Strict requires an intent before the page loads; Relaxed adds a dismiss path that lets you browse untracked. The badge is the only thing that tells you which contract you are under.
src/content/gatekeeper.js · .mode-strict / .mode-relaxed

Why are you here? Strict

Define your intent to proceed.
Inherited from parent tab — confirm or change:
🦊
Gatekeeper — inherited context
Open a link from a tab that already has a context and the child inherits it, pre-filled. The hint above the control makes the inheritance visible so it can be corrected rather than accepted by inertia.
src/content/gatekeeper.js · contextSource === 'inherited'

Why are you here? Strict

Define your intent to proceed.
🤖
Gatekeeper — agent selected
The "Who's working?" control defaults to human. Choosing Agent opens a tab-scoped controller span, so the whole intent's time is attributed as agent-driven instead of quietly inflating your own hours.
src/content/gatekeeper.js · .who-opt.agent.selected

🚫 Blocked Site

This site has been blocked by Tabatha.
reddit.com
Why do you need to visit? (min 50 characters)
71 / 50
How long do you need?
🚫
BlockGate
A friction wall on blocked sites. Fifty characters of justification and an explicit time box, or take the exit and bank a focus win. The leave button is styled to be the attractive one on purpose.
src/content/blockgate.js
👋
Welcome back! You were away for 12m
👋
Welcome Back overlay
A three-second flash when you return from an idle gap over a minute. It reports the gap and gets out of the way, because the point is to account for the missing time, not to interrogate you about it.
src/home/index.jsx · WELCOME_BACK broadcast
🎉 What's New

Tabatha updated to v6.7.16

v6.7.18
Added
  • Component showcase pages covering the in-page overlays and content scripts.
  • Capture folder and last-frame timestamp surfaced on the Cortex panel.
🎉
What's New modal
Fires once per version bump on the new tab page, reading from the parsed changelog. It shows up to three releases so a user who skipped a few still sees everything that changed, and Esc or a click outside dismisses it.
src/components/ui/WhatsNewModal.jsx