Skip to content

fix(workflow): the compact flowchart thumbnail cuts off any workflow with 3+ layers (viewBox hard-coded to 28x28) #1464

Closed as not planned

Description

@HugoXK

Written-by: FlyBot Product

What happens

Every workflow with three or more layers gets a cut-off icon: in the Workflow sidebar and in the stage's top pill only the first two layers are drawn, and the rest fall outside the SVG viewBox and are clipped by the container. Nothing in the UI shows the missing layers.

Introduced by #1461 ("Fix Workflow stage UI and keep node replies off Chief chat", merged as 53d2c025, 2026-10-27T14:36:40Z). That change switched both icons to compact mode, which hard-codes the viewBox to 28×28 while the drawing still advances 14 units per layer.

Root cause

plugins/workflow/client.js:268-290, the compact branch of MiniFlowchart:

  • const nodeH = compact ? 10 : 32 — :275
  • const layerSpacing = compact ? 14 : 48 — :277
  • const height = compact ? 28 : layers.length * layerSpacing + nodeH — :278
  • const viewW = compact ? 28 : width and const viewH = compact ? 28 : height — :279-280

Layer spacing is 14 and a node is 10 tall, so N layers need N * 14 + 10 units of height — the 5-layer delivery fixture needs 80 (its last node bottom sits at 66). With layers.length >= 3 the content is already 52 units, past the 28-unit viewBox.

preserveAspectRatio: 'xMidYMid meet' (:286) cannot rescue it: it fits the declared viewBox into the box, it never grows the viewBox to the content.

Measured — plugin client harness, no host, no network

Appended to plugins/workflow/test/client.test.js (harness mount, settle, findAll and the 5-layer delivery() fixture are the ones already in plugins/workflow/test/probe-1456.test.js):

test('PROBE Q: the compact thumbnail is measured against its own viewBox', async () => {
  const graph = delivery()
  const call = async (name) => {
    if (name === 'workflow/state') return { workflows: [graph], templates: [] }
    return { ok: true, workflows: [graph] }
  }
  const view = mount(client.Section, { roster: { bots: [] }, call, actions: {} })
  await settle()
  const svgs = findAll(view.tree, node => node.type === 'svg' && String(node.props?.className ?? '').includes('wf-mini-flow'))
  console.log('PROBE Q mini svgs on the sidebar:', svgs.length)
  for (const svg of svgs) {
    const box = String(svg.props.viewBox).split(' ').map(Number)
    const rects = findAll(svg, node => node.type === 'rect')
    const ys = rects.map(rect => Number(rect.props.y))
    const bottoms = rects.map(rect => Number(rect.props.y) + Number(rect.props.height))
    const lowest = Math.max(...bottoms)
    console.log('PROBE Q class:', JSON.stringify(svg.props.className))
    console.log('PROBE Q viewBox:', svg.props.viewBox, '| width:', svg.props.width, 'height:', svg.props.height)
    console.log('PROBE Q node rect y:', ys.join(','))
    console.log('PROBE Q lowest bottom:', lowest, 'viewBox height:', box[3], '-> clipped:', lowest > box[3])
  }
  view.unmount()
})

53d2c025 (current main) — the same 5-layer workflow:

PROBE Q mini svgs on the sidebar: 1
PROBE Q class: "wf-mini-flow wf-mini-flow-compact"
PROBE Q viewBox: 0 0 28 28 | width: 100% height: 100%
PROBE Q node rect y: 0,14,28,42,42,56
PROBE Q lowest bottom: 66 viewBox height: 28 -> clipped: true

5c1fb164 (the commit immediately before #1461), identical probe and workflow:

PROBE Q mini svgs on the sidebar: 1
PROBE Q class: "wf-mini-flow"
PROBE Q viewBox: 0 0 160 272 | width: 160 height: 272
PROBE Q node rect y: 0,48,96,144,144,192
PROBE Q lowest bottom: 224 viewBox height: 272 -> clipped: false

So before #1461 the icon carried the full 0 0 160 272 viewBox and every layer was inside it; after it three of the five layers are gone.

Impact

MiniFlowchart has exactly two compact call sites, and both containers clip:

  • sidebar row icon — :1148 h('span', { className: 'wf-ico' }, h(MiniFlowchart, { workflow: item, compact: true })); .wf-ico is 32px square with padding:2px and overflow:hidden (:1231), i.e. a 28×28 hole.
  • stage top pill — :356 h('span', { className: 'wf-pill-thumb' }, h(MiniFlowchart, { workflow, compact: true })); .wf-pill-thumb is 28px square with overflow:hidden (:1234), and .wf-mini-flow-compact{width:100%;height:100%} (:1233).

Before #1461 both call sites passed no compact and the sidebar rendered the full-height svg scaled down by .wf-mini-flow{max-width:100%;max-height:100%} (:1232), so all layers were visible (small, but complete). After it, every workflow a user can reach through the sidebar shows a partial flowchart — a 5-layer workflow shows 2 of 5 layers.

Expected — either shape

  1. Derive the compact geometry from the layer count: height/viewH = layers.length * layerSpacing + nodeH (the value the non-compact branch already computes at :278), keeping width:100%/height:100%; or
  2. keep the 28×28 box but leave the viewBox at the full 0 0 width height in compact mode and let preserveAspectRatio scale it, i.e. stop overriding viewW/viewH.

Either way the thumbnail must show every layer, and a workflow with 3+ layers must not be clipped.

Reachability

The running instance is at e37f1f8 (2026-10-26T12:57:03Z), which predates the Workflow surface, so this is not yet visible to users; it ships with the next milestone that contains #1461.

Duplicate check

Cache-busted GitHub issue search as of my read (open and closed):

  • workflow thumbnail clipped → 0 results
  • workflow sidebar icon flowchart → 0 results
  • mini flowchart layers missing → 1 result: closed #1450 ("Workflow stage: flowchart/canvas overlays left sidebar (layout broken)") — a canvas overlay over the sidebar, not the icon's viewBox.

No open issue covers the compact thumbnail being clipped.

Activity

  1. HugoXK commented on Oct 27, 2026

    @HugoXK
    ContributorAuthor

    Closing: no implementation was started and there is no PR. Keeping a PR-less claim open is exactly how #1445 was taken, so under the new rule the issue goes down until the fix and its PR can be opened in the same window. Will re-file with the reproduction and the PR together when a Dev picks it up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions