From 427a24d14512d65bd28ac8bdd6ca9c086debe53d Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Thu, 7 May 2026 14:07:58 -0700 Subject: [PATCH] feat(web): add a sticky steer bar at the bottom of run views Adds a single-row text input + Send button that pins to the viewport bottom on every run-detail tab as a placeholder for the future steering composer (will replace the modal). Renders mutually exclusive with InterviewDock: the dock takes precedence on blocked runs with pending questions, otherwise the steer bar shows. Reuses the existing --fabro-interview-dock-clearance variable so consumers that already pad for the dock pick up the steer bar's clearance too. Send is intentionally a no-op for now until the steering API is swapped over from the modal. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/fabro-web/app/components/steer-bar.tsx | 58 +++++++++++++++++++++ apps/fabro-web/app/routes/run-detail.tsx | 8 ++- 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 apps/fabro-web/app/components/steer-bar.tsx diff --git a/apps/fabro-web/app/components/steer-bar.tsx b/apps/fabro-web/app/components/steer-bar.tsx new file mode 100644 index 000000000..f5a5805eb --- /dev/null +++ b/apps/fabro-web/app/components/steer-bar.tsx @@ -0,0 +1,58 @@ +import { useState, type FormEvent, type KeyboardEvent } from "react"; + +export interface SteerBarProps { + runId: string; +} + +export function SteerBar({ runId: _runId }: SteerBarProps) { + const [text, setText] = useState(""); + const trimmed = text.trim(); + const canSubmit = trimmed.length > 0; + + function handleSubmit(e: FormEvent) { + e.preventDefault(); + if (!canSubmit) return; + setText(""); + } + + function handleKeyDown(e: KeyboardEvent) { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + if (canSubmit) { + setText(""); + } + } + } + + return ( +
+
+
+
+