feat: Rich UI widgets for Agent sidebar#4792
Conversation
|
👋 Commands for maintainers:
|
10c56a1 to
b104ab6
Compare
|
@AleksandarCole tell bender to never do this |
|
@shiroyasha all addressed. I find the es-lint one a bit weird though. The problematic Robot says:
Sounds strange to me that we would need to modify these imported components to fit the eslint policy, is this ok approach? |
|
No that is super weird. Eslint is not (should not) check libraries. I see two options how we could have got this message: 1/ Bender is halucinating |
8a382cd to
a9e9a75
Compare
- Parser for :::type blocks (buttons, confirm, chart, collapse, steps, success/error) - Widget components: ButtonsWidget, ConfirmWidget, ChartWidget, CollapseWidget, StepsWidget, BannerWidget - RichMessage component replaces AgentMarkdown with full widget support - Storybook stories for all widgets - Button/confirm clicks auto-send as user messages - Added recharts dependency for data visualization
- Added shadcn chart + card components - ChartWidget now uses ChartContainer, ChartTooltip, ChartLegend - Added dedicated chart stories (7 variants with realistic data) - Proper theming via CSS variables, matches design system
- MermaidWidget renders flowcharts, sequence diagrams, state diagrams - Parser extracts ```mermaid code blocks as mermaid segments - Storybook stories: canvas flowchart, deploy pipeline, sequence diagram, state diagram, topology - Graceful error handling for invalid mermaid syntax
- Switched from neutral to base theme with custom themeVariables - Violet primary nodes, cyan secondary, amber tertiary - Slate lines and text, matching app design system - Added rounded container with subtle border/background
All mermaid diagram types with realistic SuperPlane data
- Added table Tailwind classes: borders, header bg, hover rows, compact padding - Stories: SimpleTable (node list), RunHistoryTable, NodeComparisonTable
- Even rows get subtle slate background - Hover highlights in violet tint for easier row tracking
- Buttons now render as a card with violet header (question) and option list - Each option has a letter badge (A, B, C...) for quick reference - Parser extracts non-list lines as prompt text - New syntax: prompt text goes above list items inside :::buttons block
- CodeBlockWidget uses Monaco editor (same as rest of app) - Language header bar with copy and expand buttons - Copy button: clipboard with checkmark feedback - Expand button: opens fullscreen Dialog modal with line numbers - Replaces plain pre/code blocks via ReactMarkdown components override - Auto-height based on line count (max 250px inline, 60vh modal) - Stories: YAML, Bash, JSON code blocks
Agent responses from DB sometimes have leading spaces on every line. Updated regexes to allow optional whitespace before ::: and ``` markers.
js-yaml exports load(), not parse(). The parser was silently catching the error and returning fallback configs with no data.
- Expand button (top-right, shows on hover) opens fullscreen dialog - Mouse wheel to zoom (0.2x to 5x) - Click and drag to pan - Zoom +/−/Reset controls in toolbar - SVG rendered without max-width constraint in modal for full detail
- Charts: rounded border + light slate background - Tables: matching light background - Steps: same card wrapper - Visually separates rich elements from surrounding text
Gray-on-gray was hard to distinguish. Switched to: - bg-white for contrast against slate-100 message bubble - border-violet-200 for brand color accent - shadow-sm for subtle depth
Both were too narrow for comfortable reading
shadcn Dialog default caps at sm:max-w-lg. size=large removes that, allowing our w-[90vw] h-[85vh] to take effect.
- Changed h-[85vh] to max-h-[85vh] so modals shrink to fit - Code modal: Monaco height based on line count (200px min, 70vh max) - Mermaid modal: reduced min-height to 40vh
Uses useQuery with shared 'agent-run-chips' key — one fetch for all chips on the page. Falls back to existing canvas runs cache first. Chips immediately show correct status colors without needing the Runs tab open.
Agent provides [Title](run:UUID~status) — chip just renders it. Removed hover card, query hooks, cache lookups. Much simpler.
Agents can now reference canvas nodes using markdown syntax: [label](node:node-id) NodeChip features: - Purple badge for triggers, blue for actions - Shows integration icon + node label - Click to select node, open sidebar, and zoom to node on canvas - Hover card displays full ComponentBase preview - Falls back gracefully for missing nodes Wired into RichMessage alongside RunChip. Supports node: protocol in markdown links. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
AgentSidebar renders outside ReactFlowProvider context. Use URL navigation only for node selection (?sidebar=1&node=id).
- Uses SuperplaneComponentsNode (API type) not BlockData (React Flow type) - Hover card: header with icon/name/component, config summary, connection count, error display - Config summary extracts key field per component type (URL for http, expression for if, etc.) - whitespace-nowrap on chip to prevent text wrapping - Removed ComponentBase/Trigger imports that required incompatible data shapes
Maps http→Globe, wait→Clock, webhook→Webhook, start→Play, if→Split, filter→Filter, ssh→Terminal, approval→Hand, merge→Merge, schedule→Clock. Falls back to integration icon (getHeaderIconSrc) for vendor components.
Uses custom DOM event 'agent:focus-node' to bridge the gap between AgentSidebar (outside ReactFlowProvider) and CanvasPage (inside it). Chip dispatches event → canvas page listens → fitView + select node.
- Revert storybook allowedHosts (dev-only config, shouldn't ship) - Fix parser.test.ts: parseAgentMessage → parseAgentContent - Rewrite NodeChip stories with correct API types (no trigger/action sub-objects) - Remove ReactFlow/ReactFlowProvider imports from stories - Slim down widgets/index.ts barrel exports
- Click anywhere on diagram opens the modal (removed expand button) - Default zoom 250%, reset returns to 250% - Hover border change for click affordance
Wraps tables in overflow-x-auto div so wide tables scroll instead of overflowing the chat bubble.
- Fix useCallback called conditionally (move before early return) - Remove unused 'i' parameter in map - Fix @storybook/react → @storybook/react-vite imports - Fix edges possibly undefined in NodeChip - Fix parser tests (buttons prompt field, collapse syntax) - Remove unused card.tsx and widgets/index.ts barrel (knip) - Run Prettier on all changed files
Transitive dep of mermaid via d3-delaunay. Public domain, compatible with Apache-2.0.
- ChartWidget: percent ?? 0 for possibly undefined pie label - NodeChip: getConfigSummary refactored from switch to map (reduces complexity) - NodeChip: eslint-disable for remaining UI complexity
Extract getChipStyle() and NodeIconInline() from NodeChip. Removes eslint-disable comment that was flagged as 'unknown'.
complexity: 233→235, max-statements: 75→76, total: 710→713
- Refactored parseAgentContent: extracted state machine (ParserState, processLine, flushMarkdown, flushBlock) to reduce max-statements - Restored original baseline (710 total, 233 complexity) - Updated baseline minimally: +2 total (712), +2 complexity (235) for shadcn chart.tsx auto-generated code - Extracted focusNodeById from CanvasContent to avoid adding complexity
Added eslint-disable-next-line for 2 complexity warnings in shadcn's auto-generated chart.tsx (ChartTooltipContent, ChartLegendContent). Baseline restored to original (710 total, 233 complexity).
Extracted renderTooltipLabel, resolveTooltipLabelValue, TooltipPayloadRow, TooltipIndicator, resolvePayloadKey, resolveIndicatorColor, formatPayloadValue from shadcn's ChartTooltipContent. No eslint-disable comments needed. Budget: 710/710 (unchanged from main).
RechartsPrimitive.Payload/TooltipPayloadEntry not reliably exported across recharts versions. Use NonNullable<...payload>[number] instead.
9ff7d61 to
f0cbd63
Compare
Signed-off-by: Pedro F. Leao <pedroforestileao@gmail.com>
Signed-off-by: Pedro F. Leao <pedroforestileao@gmail.com>
What
Rich interactive widgets for the Agent sidebar chat. The agent outputs special syntax in markdown; the frontend parses and renders them as interactive UI components.
Widgets
:::buttons:::confirm:::chart```lang```mermaid:::collapse:::steps:::success/:::error[title](run:UUID~status)[name](node:id)Key Changes
New files (widgets/)
parser.ts— splits markdown into segments: regular text,:::blocks, mermaid fencesRichMessage.tsx— replaces old AgentMarkdown, renders each segment with appropriate widgetButtonsWidget.tsx,ConfirmWidget.tsx,ChartWidget.tsx,CodeBlockWidget.tsx,CollapseWidget.tsx,MermaidWidget.tsx,StepsWidget.tsx,BannerWidget.tsxRunChip.tsx— colored run reference pills (green/red/blue/gray by status)NodeChip.tsx— node reference pills with Lucide icons, hover card with config summary, click zooms canvasModified files
AgentSidebar/index.tsx— tool message grouping, RichMessage integration, canvasId/orgId threadingui/CanvasPage/index.tsx—agent:focus-nodecustom event listener for node chip zoom.eslint-budget-baseline.json— updated for new codeNew dependencies
recharts— chart rendering (via shadcn/ui wrapper)mermaid— diagram rendering@radix-ui/react-hover-card— hover cards for node chipsNew shadcn/ui components
chart.tsx— ChartContainer, ChartTooltip, ChartLegendhover-card.tsx— HoverCard with Radix primitivesOther
scripts/license_finder.yml— approvedrobust-predicates(The Unlicense, mermaid transitive dep)Agent Integration
The agent uses a custom Anthropic skill (
rich-ui-widgets) for syntax reference. System prompt has usage guidelines for when to apply each widget. Run/node chips userun:andnode:URL protocols preserved via customurlTransformin ReactMarkdown.Preview
Storybook: https://storybook.bender.efodconsulting.com/