Move panel explanations into tooltips

The node, flow, widget and dashboard panels explained themselves in
paragraphs under every control. They now carry a caption and an info
tooltip, so a panel reads as a list of settings.

InfoTip, PanelSection and FieldLabel live beside PANEL_SECTION in
SidePanel.tsx, which the panels already share. InfoTip holds its own open
state because a Radix tooltip ignores a touch pointer, and below md the
whole panel is a full-screen sheet — hover-only help would leave a phone
with the caption and nothing else.

Dashboard/panels.tsx drops from 30 helper paragraphs to 5; the ones left
are empty states and status, not explanation. Em-dashes are out of the
user-facing strings, except where one separates the halves of a select
item.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015YrQnKV3bnQd4K342y8tKj
This commit is contained in:
2026-08-31 10:24:26 +02:00
co-authored by Claude Opus 5
parent d01a8dad37
commit 954d90fbf7
6 changed files with 303 additions and 224 deletions
+26 -18
View File
@@ -22,7 +22,7 @@ import { cn } from "@/lib/utils"
import { qualify } from "./deriveEdges"
import { useLiveValue } from "./liveStore"
import { asText, DTYPES } from "./NodePanel"
import { PANEL_SECTION } from "./SidePanel"
import { InfoTip, PANEL_SECTION } from "./SidePanel"
import { ValuePreview } from "./ValuePreview"
/**
@@ -274,12 +274,17 @@ export function BoundarySections({
return (
<>
<div className="grid gap-3">
<span className={PANEL_SECTION}>Mode</span>
<div className="flex items-center gap-1">
<span className={PANEL_SECTION}>Mode</span>
<InfoTip label="Mode">
A live flow runs continuously, with its subscriptions, schedules and
webhooks active. A batch flow runs only when a run asks it to, from
its inputs to its outputs.
</InfoTip>
</div>
<div className="flex items-center justify-between gap-3">
<p className="text-sm text-muted-foreground">
{batch
? "Runs when a run asks it to, from its inputs to its outputs. Nothing here is subscribed or scheduled."
: "Runs continuously: subscriptions, schedules and webhooks are live."}
{batch ? "Batch" : "Live"}
</p>
<Select
value={definition.mode ?? "live"}
@@ -301,6 +306,10 @@ export function BoundarySections({
<div className="grid gap-3">
<div className="flex items-center justify-between">
<span className={PANEL_SECTION}>Inputs</span>
<InfoTip label="Inputs">
Messages that arrive from outside, such as a dashboard control, a
run or the API, and the value the flow starts from.
</InfoTip>
<Button
variant="ghost"
size="sm"
@@ -315,13 +324,6 @@ export function BoundarySections({
</Button>
</div>
{inputs.length === 0 ? (
<p className="text-sm text-muted-foreground">
Messages that arrive from outside a dashboard control, a run, the
API and the value the flow starts from.
</p>
) : null}
{inputs.map((declared, index) => (
// Keyed by position: renaming an input must not remount its row.
<InputRow
@@ -341,12 +343,18 @@ export function BoundarySections({
{batch ? (
<div className="grid gap-3">
<span className={PANEL_SECTION}>Result</span>
<p className="text-sm text-muted-foreground">
{provided.length === 0
? "Nothing is produced here yet, so a run has nothing to report."
: "What a run reports when it finishes. Everything else it computed goes with it."}
</p>
<div className="flex items-center gap-1">
<span className={PANEL_SECTION}>Result</span>
<InfoTip label="Result">
What a run reports when it finishes. Everything else it computed
goes with it.
</InfoTip>
</div>
{provided.length === 0 ? (
<p className="text-sm text-muted-foreground">
Nothing is produced here yet, so a run has nothing to report.
</p>
) : null}
{provided.map((name) => (
<label
key={name}