Refactor visual brainstorming: browser displays, terminal commands (#509)

* Refactor visual brainstorming: browser displays, terminal commands

Replaces the blocking TaskOutput/wait-for-feedback.sh pattern with a
non-blocking model where the browser is an interactive display and the
terminal stays available for conversation.

Server changes:
- Write user click events to .events JSONL file (per-screen, cleared on
  new screen push) so Claude reads them on its next turn
- Replace regex-based wrapInFrame with <!-- CONTENT --> placeholder
- Add --foreground flag to start-server.sh for sandbox environments
- Harden startup with nohup/disown and liveness check

UI changes:
- Remove feedback footer (textarea + Send button)
- Add selection indicator bar ("Option X selected — return to terminal")
- Narrow click handler to [data-choice] elements only

Skill changes:
- Rewrite visual-companion.md for non-blocking loop
- Fix visual companion being skipped on Codex (no browser tools needed)
- Make visual companion offer a standalone question (one question rule)

Deletes wait-for-feedback.sh entirely.

* Add visual companion offer to brainstorming checklist for UX topics

The visual companion was a disconnected section at the bottom of SKILL.md
that agents never reached because it wasn't in the mandatory checklist.
Now step 2 evaluates whether the topic involves visual/UX decisions and
offers the companion if so. Non-visual topics (APIs, data models, etc.)
skip the step entirely.

* Add multi-select support to visual companion

Containers with data-multiselect allow toggling multiple selections.
Without it, behavior is unchanged (single-select). Indicator bar shows
count when multiple items are selected.
This commit is contained in:
Drew Ritter
2026-02-19 16:31:51 -08:00
committed by GitHub
parent 3a254ba002
commit ce0f9a28be
10 changed files with 960 additions and 207 deletions

View File

@@ -8,12 +8,11 @@
*
* This template provides a consistent frame with:
* - OS-aware light/dark theming
* - Fixed header and feedback footer
* - Fixed header and selection indicator bar
* - Scrollable main content area
* - CSS helpers for common UI patterns
*
* CLAUDE: Replace the contents of #claude-content with your content.
* Keep the header, main wrapper, and feedback-footer intact.
* Content is injected via placeholder comment in #claude-content.
*/
* { box-sizing: border-box; margin: 0; padding: 0; }
@@ -79,37 +78,21 @@
.main { flex: 1; overflow-y: auto; }
#claude-content { padding: 2rem; min-height: 100%; }
.feedback-footer {
.indicator-bar {
background: var(--bg-secondary);
border-top: 1px solid var(--border);
padding: 0.75rem 1.5rem;
padding: 0.5rem 1.5rem;
flex-shrink: 0;
text-align: center;
}
.feedback-footer label { display: block; font-size: 0.65rem; color: var(--text-secondary); margin-bottom: 0.4rem; text-transform: uppercase; letter-spacing: 0.05em; }
.feedback-row { display: flex; gap: 0.5rem; }
.feedback-footer textarea {
flex: 1;
background: var(--bg-primary);
border: 1px solid var(--border);
border-radius: 6px;
padding: 0.5rem 0.75rem;
color: var(--text-primary);
font-family: inherit;
font-size: 0.85rem;
resize: none;
height: 36px;
.indicator-bar span {
font-size: 0.75rem;
color: var(--text-secondary);
}
.feedback-footer textarea:focus { outline: none; border-color: var(--accent); }
.feedback-footer button {
background: var(--accent);
color: white;
border: none;
padding: 0 1rem;
border-radius: 6px;
font-size: 0.8rem;
cursor: pointer;
.indicator-bar .selected-text {
color: var(--accent);
font-weight: 500;
}
.feedback-footer button:hover { background: var(--accent-hover); }
/* ===== TYPOGRAPHY ===== */
h2 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
@@ -218,18 +201,12 @@
<div class="main">
<div id="claude-content">
<!-- CLAUDE: Replace this content -->
<h2>Visual Brainstorming</h2>
<p class="subtitle">Claude will show mockups and options here.</p>
<!-- CONTENT -->
</div>
</div>
<div class="feedback-footer">
<label>Feedback for Claude</label>
<div class="feedback-row">
<textarea id="feedback" placeholder="Add notes (optional)..." onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();send()}"></textarea>
<button onclick="send()">Send</button>
</div>
<div class="indicator-bar">
<span id="indicator-text">Click an option above, then return to the terminal</span>
</div>
</body>