Skip to content

Polish workflow editor UX: condition ports, approval chat, and agent controls#10

Merged
matheusgalvao1 merged 11 commits intomainfrom
polish-ui
Feb 25, 2026
Merged

Polish workflow editor UX: condition ports, approval chat, and agent controls#10
matheusgalvao1 merged 11 commits intomainfrom
polish-ui

Conversation

@matheusgalvao1
Copy link
Collaborator

Summary

  • improve Condition node UX with collapsed branch aggregation, count badge, and stable connector alignment
  • refine approval flow and chat UI styling and ordering, including proper approval result rendering and spinner timing
  • add Agent header duplicate action (icon-content) and deterministic duplicate placement outside source node area
  • add token highlighting for PREVIOUS_OUTPUT in Agent input with edit-mode fallback and input visual parity
  • add custom tooltips for node header actions (duplicate, settings, delete)
  • disable Clear Canvas while workflows are running, with disabled hint tooltip behavior

Validation

  • npm run typecheck:web

@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f337698 and 0351f6e.

📒 Files selected for processing (2)
  • apps/server/src/routes/workflows.ts
  • apps/web/src/workflow-editor.css

📝 Walkthrough

Walkthrough

Adds many UI and runtime features centered in apps/web/src/app/workflow-editor.ts and supporting CSS and server/types changes: exposes WorkflowGraph-related types and numerous public helpers for port positioning, prompt highlighting, approval/result rendering, node duplication, and active run-graph synchronization; introduces constants and templates for previous-output handling; augments log parsing and approval flows to render structured approval result cards; updates CSS for tooltips, prompt highlights, approval UI, and run/clear hints; and modifies server run routes and shared types to optionally include the workflow graph on run results.

Possibly related PRs

  • PR #5: Overlaps on PREVIOUS_OUTPUT templating, approval/log handling, and additions to WorkflowRunResult.workflow — directly touches prompt, approval, and types code paths.
  • PR #8: Implements multi-condition/Condition-node refactor and port-layout helpers that align with the new if-condition port positioning and aggregation logic.
  • PR #9: Modifies workflow-editor rendering and approval/log flows with overlapping edits to node rendering, port handling, and approval result UI.
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main changes: polish to workflow editor UX focusing on condition ports, approval chat, and agent controls, which aligns with the changeset's primary improvements.
Description check ✅ Passed The description is directly related to the changeset, detailing specific improvements across condition nodes, approval flows, agent controls, token highlighting, tooltips, and canvas clear behavior, all of which are present in the code changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/app/workflow-editor.ts`:
- Around line 736-740: The clear-canvas control currently only blocks when
workflowState === 'running' but must be gated to idle-only; change the
enablement condition so clearButton.disabled is true whenever this.workflowState
!== 'idle' (and update setClearButtonHint to reflect non-idle/paused runs), and
also add the same guard at the clear action handler (prevent execution inside
the method that performs clearing—e.g., the clearCanvas/handleClear method) so
it returns early unless this.workflowState === 'idle'; apply the same change to
the other occurrence referenced around the second spot.
- Around line 1323-1332: The duplicate button currently binds a mouse-only
'mousedown' listener which prevents keyboard activation; change the event
listener on duplicateBtn from 'mousedown' to 'click' (keeping
e.stopPropagation() and the this.duplicateAgentNode(node) call) and add an
explicit accessible name by setting duplicateBtn.setAttribute('aria-label',
'Duplicate Agent') (you can reuse the existing title/data-tooltip text) so
keyboard and assistive-tech users can activate the button.
- Around line 2181-2184: The current parseApprovalInputLog function incorrectly
infers rejection by searching the entire content for "rejected"; instead parse
the decision from a decision/status prefix (e.g., a leading "Decision:" or
"Status:" line) using a regex anchored to the start or line-beginning and map
values like "reject"/"rejected" -> 'reject' and "approve"/"approved" ->
'approve'; keep the existing feedback extraction (feedbackMatch) but ensure you
only derive decision from the prefix, not from anywhere in the feedback text.

In `@apps/web/src/workflow-editor.css`:
- Around line 638-640: The selection rule for
.prompt-highlight-wrapper.is-editing .prompt-highlight-input::selection uses a
raw rgba value; replace it with the app's semantic token-based color composition
so theming follows tokens (e.g., use the appropriate CSS token
var(--token-primary-xxx) and compose opacity via color-mix() or an RGBA helper
token), keeping color: inherit; unchanged; update the background declaration to
use the token composition instead of rgba(92, 148, 255, 0.24).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec0eea8 and 992da28.

📒 Files selected for processing (2)
  • apps/web/src/app/workflow-editor.ts
  • apps/web/src/workflow-editor.css

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
apps/web/src/workflow-editor.css (1)

480-493: Hardcoded font-size: 10px on the aggregate badge.

The rest of the file consistently uses font tokens. Consider var(--Fonts-Body-Default-xxs) or the closest available token for the count badge, unless the design requires this exact size.

As per coding guidelines, apps/web/**/*.css should use typography variables/classes for font styling.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/workflow-editor.css` around lines 480 - 493, Replace the
hardcoded font-size in the .port-condition-aggregate rule with the appropriate
typography variable/token; specifically change font-size: 10px to use the
closest token (e.g., var(--Fonts-Body-Default-xxs) or the project's equivalent)
so the badge follows the typography system; update the .port-condition-aggregate
CSS rule to reference that variable and remove the px literal to comply with
apps/web/**/*.css guidelines.
apps/server/src/routes/workflows.ts (1)

17-54: DRY: persistResult duplicates the graph-extraction logic now in getEngineWorkflow.

Lines 21-25 in persistResult perform the same backward-compat getGraph / Reflect.get dance as the new getEngineWorkflow helper on lines 47-53. persistResult should delegate to getEngineWorkflow to avoid the duplication.

♻️ Proposed refactor
 async function persistResult(engine: WorkflowEngine, result: WorkflowRunResult) {
   try {
-    // Backward compatibility: fall back to reading the private graph field if the engine
-    // instance doesn't yet expose getGraph (e.g., cached build).
-    const engineAny = engine as WorkflowEngine & { getGraph?: () => WorkflowGraph };
-    const workflow =
-      typeof engineAny.getGraph === 'function'
-        ? engineAny.getGraph()
-        : (Reflect.get(engine, 'graph') as WorkflowGraph | undefined);
+    const workflow = getEngineWorkflow(engine);
 
     if (!workflow) {
       throw new Error('Workflow graph not available on engine instance');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/server/src/routes/workflows.ts` around lines 17 - 54, persistResult
duplicates the graph-extraction logic; remove the local getGraph/Reflect.get
block and call the existing getEngineWorkflow(engine) to obtain the
WorkflowGraph, then use that returned workflow (and throw the same error if
undefined) before constructing the WorkflowRunRecord and calling saveRunRecord;
update references to engineAny/getGraph in persistResult to use
getEngineWorkflow instead to keep behavior identical while eliminating
duplication.
apps/web/src/app/workflow-editor.ts (1)

1290-1322: Duplicate placement logic has a minor collision risk with existing nodes.

The duplicate is placed directly above (or below) the source node without checking whether another node already occupies that position. For a "chill" review this is fine to defer, but overlapping nodes could confuse users in dense canvases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/workflow-editor.ts` around lines 1290 - 1322,
duplicateAgentNode currently places the duplicate at a fixed above/below
position and can overlap existing nodes; update duplicateAgentNode to check
this.nodes for collisions before finalizing duplicateY (use existing nodes' x/y
and inferred heights via document.getElementById(node.id)?.offsetHeight or
node.data?.collapsed to determine bounds) and, if a collision is found,
iteratively shift the duplicate by duplicateSpacing (or below the colliding
node) until a non-overlapping position is found (respecting minWorldY), then
push the node (this.nodes), render (this.renderNode) and select it as before;
reference duplicateAgentNode, this.nodes, this.nextNodeId, duplicateSpacing,
duplicatedCollapsedHeight when locating code to modify.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/server/src/routes/workflows.ts`:
- Around line 17-54: persistResult duplicates the graph-extraction logic; remove
the local getGraph/Reflect.get block and call the existing
getEngineWorkflow(engine) to obtain the WorkflowGraph, then use that returned
workflow (and throw the same error if undefined) before constructing the
WorkflowRunRecord and calling saveRunRecord; update references to
engineAny/getGraph in persistResult to use getEngineWorkflow instead to keep
behavior identical while eliminating duplication.

In `@apps/web/src/app/workflow-editor.ts`:
- Around line 1290-1322: duplicateAgentNode currently places the duplicate at a
fixed above/below position and can overlap existing nodes; update
duplicateAgentNode to check this.nodes for collisions before finalizing
duplicateY (use existing nodes' x/y and inferred heights via
document.getElementById(node.id)?.offsetHeight or node.data?.collapsed to
determine bounds) and, if a collision is found, iteratively shift the duplicate
by duplicateSpacing (or below the colliding node) until a non-overlapping
position is found (respecting minWorldY), then push the node (this.nodes),
render (this.renderNode) and select it as before; reference duplicateAgentNode,
this.nodes, this.nextNodeId, duplicateSpacing, duplicatedCollapsedHeight when
locating code to modify.

In `@apps/web/src/workflow-editor.css`:
- Around line 480-493: Replace the hardcoded font-size in the
.port-condition-aggregate rule with the appropriate typography variable/token;
specifically change font-size: 10px to use the closest token (e.g.,
var(--Fonts-Body-Default-xxs) or the project's equivalent) so the badge follows
the typography system; update the .port-condition-aggregate CSS rule to
reference that variable and remove the px literal to comply with
apps/web/**/*.css guidelines.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 992da28 and f337698.

📒 Files selected for processing (5)
  • apps/server/src/routes/workflows.ts
  • apps/web/src/app/workflow-editor.ts
  • apps/web/src/workflow-editor.css
  • packages/types/src/index.d.ts
  • packages/types/src/index.ts

@matheusgalvao1 matheusgalvao1 merged commit 9a3f41e into main Feb 25, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant