Read a flow name, a port name and an honest docstring

Give the Home flow-activity name cell a `sm:min-w-32` floor beside its
`max-w-0` cap, so an ordinary name reads in full where there is room
while the phone keeps today's truncation. Name the bar widget's nested
reading by its port rather than its qualified message. Correct
`MarkdownWidget`'s docstring to the subset it actually renders.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SKL7sUgNWhukDEz95vSMQv
This commit is contained in:
2026-08-20 14:52:51 +02:00
co-authored by Claude Opus 5
parent 26833d63ee
commit 8d5dde003b
4 changed files with 12 additions and 8 deletions
-3
View File
@@ -30,7 +30,6 @@ should reopen it.
- FEAT/UI/MOBILE: a rank of many nodes — a connector feeding eight dashboard tiles — is thousands of pixels wide however the graph is turned, so on a phone the fit shrinks it past reading. The layout is right and the flow is simply too big for the screen; a "one rank at a time" reading mode, or wrapping a wide rank, is what would make it legible.
- CHORE/UI: an edge's value chip sits at the bezier midpoint while the layout reserves its room at dagre's label rank. The two agree closely enough today; if chips ever pile up, take the position from the layout instead.
- CHORE/UI: the bar widget's nested fill is `--chart-5` against a `--primary` outer fill, which measures 2.53:1 in light mode — under the 3:1 guideline for non-text. The `inset-y-1` gutter supplies the edge, and every other slot of the ramp collapses in dark mode instead.
- CHORE/UI: the Home flow-activity table's name cell is `max-w-0` with nothing setting a floor, so `demo_training` reads as "demo⋯" at 1440px while the row has slack to spare. The cap is what keeps the table from widening the page; it wants a minimum beside it.
- FEAT/UI (deferred until MCP lands): add a "bot" icon button to the home view (graph panel) which opens a chat window (reuse general concept of a side panel like in flows/nodes to make it a chat panel which can open on any screen (stacks below any other existing panel -> introduce stacking) to give support on errors/write code, generate dashboards etc) to explain the error(s)
- FEAT/UI make the header (Fluksio - YEAR) and the logo in the sidebar link to the main page (fluksio.com)
- FEAT/UI consider adding a diagram to the Home view which shows a histogram of the different classes of nodes and which time it takes to execute (logarithmic scale); this should give a hint on the load and help to detect bottle necks/hotspots
@@ -118,7 +117,6 @@ Decisions taken up front, because most items below depend on them:
- Nothing e-ink-specific in the widgets. Panel access is a credential problem
(see below); the display's demands are a rendering profile, deferred.
- CHORE/UI: `MarkdownWidget`'s docstring claims "headings, bold, code, links, list items"; only headings and bullets are implemented. Either the inline spans or the docstring.
- CHORE/UI: identical in-flight chart requests are deduplicated per browser tab,
so two wall panels showing the same tile still run the query twice. An
`interval` on the request port is the backstop, and it belongs to the flow
@@ -150,7 +148,6 @@ as an em dash.
### Dashboard follow-ups
- BUG/UI: ensure dashboard wallpanel (read-only) links hot reload automatically on dashboard changes
- CHORE/UI: `BarWidget`'s caption names the nested reading by its raw message name, so a wall panel reads "home.self_use_kw 1.14 kW". The widget title is what the rest of the panel shows; the caption wants a label of its own, or the port's name rather than the qualified one.
- FEAT/NODE: the hosted demo covers thirteen of the fifteen built-in node types. `switch` and `delay` are unplaced — a `switch` branch needs either a dead-end port or trivial nodes to turn a branch back into a label, and neither read as something a person would hang. Worth revisiting when the demo grows a second page.
- CHORE/UI: an icon rule stores a `label` — the widget draws it under the glyph and uses it as the glyph's accessible name — but the mapping editor offers no field for it, so it can only be set through the API.
- BUG/UI: shrinking the canvas silently clips whatever now falls past its bottom edge. `maxRows` only constrains a new drag, not a stored placement, so nothing warns and nothing offers to reflow.
@@ -1,3 +1,4 @@
import { displayName, flowOf } from "@/components/Flow/deriveEdges"
import { useLiveValue } from "@/components/Flow/liveStore"
import { cn } from "@/lib/utils"
import type { WidgetProps } from "./widgets"
@@ -28,6 +29,9 @@ export function BarWidget({ widget }: WidgetProps) {
const cfg = config(widget)
const message = text(cfg.message)
const nested = text(cfg.inner)
// The panel already carries the widget's title, so the caption names the
// reading by its port rather than repeating the flow it comes from.
const innerName = nested ? displayName(flowOf(nested), nested) : ""
const outer = useLiveValue(message || undefined)
const inner = useLiveValue(nested || undefined)
if (!message)
@@ -56,7 +60,7 @@ export function BarWidget({ widget }: WidgetProps) {
role="img"
aria-label={
nested
? `${write(value)} of ${max}${unit}, ${write(innerValue)} of it from ${nested}`
? `${write(value)} of ${max}${unit}, ${write(innerValue)} of it from ${innerName}`
: `${write(value)} of ${max}${unit}`
}
>
@@ -89,7 +93,7 @@ export function BarWidget({ widget }: WidgetProps) {
</div>
{innerValue === null ? null : (
<p className="truncate text-xs text-muted-foreground">
{nested} {write(innerValue)}
{innerName} {write(innerValue)}
</p>
)}
</div>
@@ -382,7 +382,8 @@ function GaugeWidget({ widget }: WidgetProps) {
}
/**
* A very small markdown subset: headings, bold, code, links, list items.
* A very small markdown subset, read a line at a time: headings and list items.
* Inline spans — bold, code, links — are not parsed and read as written.
*
* Enough for the labels and notes a dashboard carries, and not worth a parser.
*/
@@ -185,10 +185,12 @@ export function HealthOverview({
<tbody>
{(flows ?? []).map((row: FlowRollup) => (
<tr key={row.flow} className="border-t border-border">
<td className="max-w-0 py-2 pr-3">
<td className="max-w-0 py-2 pr-3 sm:min-w-32">
{/* `max-w-0` is what lets a cell truncate at all: without
it the table sizes to the longest name and pushes the
page sideways. */}
page sideways. The floor beside it keeps an ordinary
name readable where there is room for one; a phone has
none to spare, so it starts at `sm` like the trend. */}
<Link
to="/flows/$flowName"
params={{ flowName: row.flow }}