Skip to content

feat(apollo-react): add ExpressionEditor field type for NodeManifestPanel#793

Open
1980computer wants to merge 19 commits into
mainfrom
add-expression-editor
Open

feat(apollo-react): add ExpressionEditor field type for NodeManifestPanel#793
1980computer wants to merge 19 commits into
mainfrom
add-expression-editor

Conversation

@1980computer

Copy link
Copy Markdown
Collaborator

Summary

Adds an ExpressionEditor custom field type for use with NodeManifestPanel via MetadataForm's plugin/custom component system.

Previously implemented as a standalone ExpressionField.tsx (removed in #760 during the FormSchema migration). This PR re-introduces expression editing as a proper type: 'custom' field, backed by Monaco/CodeMirror.

What this will add

  • ExpressionEditor — custom MetadataForm field component registered via the plugin system
  • Supports expr mode (JavaScript/TypeScript) and json mode (JSON template)
  • Mode switcher pill (Expr / JSON)
  • Integrates with Monaco/CodeMirror editors already in use in flow-workbench
  • ExpressionEditor story added to Node Property Panel

Depends on

Not yet included

  • Variable binding / {x} bind button — Phase 2

🤖 Generated with Claude Code

1980computer and others added 8 commits June 5, 2026 06:55
New docked main-UI panel for editing node parameters. Takes a
PropertiesManifest with a parameters array and renders a tab-based form
with Parameters / Error handling / Advanced tabs.

- NodeManifestPanel — renders manifest-driven parameter form
- ParameterField — supports text, number, boolean (toggle), and select types
- ExpressionField — mode switcher between literal and expression input
- Stories: HttpRequest, HumanTask, AiAgent, NoParameters, Interactive

Phase 1 is UI only. Variable binding ({x} bind button and variable picker)
ships in Phase 2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracts the Probe debug card from flow-workbench into a reusable
apollo-react canvas component.

ProbeCard is a fully controlled, floating debug card that anchors to a
canvas node via a dashed connector. It exposes watch expressions with
type-coloured value trees, an iteration cycler for loop nodes, and
drag/resize/keyboard interactions.

Architecture:
- UI-only — callers own position, size, watch list, and persistence
- Fully controlled via callbacks (onDrag, onResize, onAddWatch, etc.)
- Canvas pan/zoom forwarding via onCanvasPan / onCanvasZoom
- All chrome uses Apollo semantic tokens (surface-raised, border-subtle,
  foreground-muted, foreground-accent, etc.)
- Memoised to skip re-renders when only the viewport pans/zooms

Exports from @uipath/apollo-react/canvas:
  ProbeCard, ProbeCardProps, WatchResult, IterationControl, ResizeEdges

Story added to Canvas > Components > Panels > Node Flyout Panel > Probe:
- Real BaseCanvas with a uipath.agent anchor node
- ProbeOverlay child component reads node position + viewport transform
  from the ReactFlow store so the card and connector track correctly
  during pan and zoom
- "Add probe" button simulates the context-menu trigger

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a new pill-trigger + popover control for configuring canvas panel
visibility, behavior (auto-hide / always-persist), default layout, and
saved presets. Pixel-matched to the flow-prototype reference using
apollo-wind Future design tokens. Pure Tailwind, no Emotion.

Story registered under Canvas/Components/Controls/CanvasPropertiesPanel
with Default, States, and WithPresets variants.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrates NodePropertiesPanel and all field components (CheckboxField,
NumberField, SelectField, TextField) from @emotion/styled to Tailwind CSS.
Deletes NodePropertiesPanel.styles.ts. Story title updated to "Node Flyout
Panel" to distinguish it from the new main-UI panel variant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Co-locates all panel stories under Canvas > Components > Panels with
  explicit storySort order
- Renames CollapseConfig story to reflect updated component name
- Removes orphaned NodeInspector story (old Components/Panels path)
- Updates NodePropertiesPanel story to Node Flyout Panel with co-located
  variants

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds NodePropertyTrigger — a pill-trigger + portal popover for configuring
canvas panel visibility, behaviour, default layout, and saved presets.

- Fully controlled: behavior, layout, panels, presets, behaviorOptions, and
  layoutOptions are all props; no internal opinion on values or labels
- behaviorOptions / layoutOptions props let consumers supply their own labels
  (defaults to Auto hide / Always persist and Right / Bottom / Split)
- className prop for consumer positioning overrides
- Popover positioned via containerRef on the pill root — right-aligns and
  gaps correctly from the full pill, not just the sliders button
- Outside-click guard uses containerRef and correctly excludes the portalled
  menu so item callbacks always fire before close
- All new types exported from canvas/controls barrel
- Renames NodePropertyPanel → NodePropertyTrigger throughout; story labels
  genericised to Button 1/2/3 across Default, States, and WithPresets
- storySort updated; States story dead-state bug fixed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix Biome format failure in apps/storybook preview.tsx storySort array
- NodePropertiesPanel.tsx: replace border-[var(--canvas-border-de-emp,...)]
  with border-(--canvas-border-de-emp) to match the canvas CSS-var utility
  pattern used elsewhere (e.g. FloatingCanvasPanel, ButtonHandle)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tadataForm

Addresses coworker feedback on PR #760:

- Inherit manifest from registry: removes `manifest` prop; component calls
  useNodeManifest(nodeType) internally and reads manifest.form (FormSchema)
- Use existing MetadataForm/FormSchema system: deletes ParameterField.tsx,
  ExpressionField.tsx, PropertiesManifest, and ParameterDefinition types;
  renders <MetadataForm schema={manifest.form} /> directly
- Tabs as consumer concern: removes hardcoded TABS constant; MultiStepFormSchema
  steps become tabs automatically — consumer defines step titles and fields
- Adds px-6 pb-6 pt-2 padding wrapper and actions:[] to suppress default
  Submit button (panel is a live onChange form, not a wizard)
- Stories updated to use NodeRegistryProvider + FormSchema with steps for tabs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (PT)
apollo-design 🟢 Ready Preview, Logs Jun 10, 2026, 05:08:26 PM
apollo-docs 🟢 Ready Preview, Logs Jun 10, 2026, 05:08:26 PM
apollo-landing 🟢 Ready Preview, Logs Jun 10, 2026, 05:08:26 PM
apollo-ui-react 🟢 Ready Preview, Logs Jun 10, 2026, 05:08:26 PM
apollo-vertex 🟢 Ready Preview, Logs Jun 10, 2026, 05:08:26 PM

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Dependency License Review

  • 1902 package(s) scanned
  • ✅ No license issues found
  • ⚠️ 2 package(s) excluded (see details below)
License distribution
License Packages
MIT 1672
ISC 89
Apache-2.0 55
BSD-3-Clause 27
BSD-2-Clause 23
BlueOak-1.0.0 8
MPL-2.0 4
MIT-0 3
CC0-1.0 3
MIT OR Apache-2.0 2
(MIT OR Apache-2.0) 2
Unlicense 2
LGPL-3.0-or-later 1
Python-2.0 1
CC-BY-4.0 1
(MPL-2.0 OR Apache-2.0) 1
Unknown 1
Artistic-2.0 1
(WTFPL OR MIT) 1
(BSD-2-Clause OR MIT OR Apache-2.0) 1
CC-BY-3.0 1
0BSD 1
(MIT OR CC0-1.0) 1
MIT AND ISC 1
Excluded packages
Package Version License Reason
@img/sharp-libvips-linux-x64 1.2.4 LGPL-3.0-or-later LGPL pre-built binary, not linked
khroma 2.1.0 Unknown MIT per GitHub repo, missing license field in package.json

@1980computer 1980computer marked this pull request as ready for review June 8, 2026 17:28
1980computer and others added 4 commits June 8, 2026 11:42
- ProbeCard: add biome-ignore for noNoninteractiveTabindex and
  useSemanticElements — tabIndex is intentional on a composite interactive
  widget that requires keyboard focus for Delete/Backspace shortcuts
- useDragSession: replace eslint-disable with biome-ignore for
  useExhaustiveDependencies — handlers are read via stable ref

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NodeManifestPanel:
- Close button: add title + aria-label so screen readers announce it

NodePropertyTrigger:
- Guard e.target instanceof Element before calling .closest()
- role="menu" + aria-label on portalled popover
- aria-label + aria-haspopup="menu" + aria-expanded on trigger button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ng surface token

Panel background is bg-surface-raised (zinc-900), matching NodePropertyTrigger.
MetadataForm inputs use future:bg-surface-raised internally — same token, no
contrast. Wrapping MetadataForm with --surface-raised: var(--surface-overlay)
remaps the variable in scope so inputs render on zinc-800 (surface-overlay),
visibly lighter than the zinc-900 panel background.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… NodeManifestPanel

MetadataForm labels inherit text-foreground (white) by default, matching the
primary text weight and creating no visual hierarchy over field values.

Adds [&_label]:text-foreground-muted to the existing MetadataForm scope
wrapper so all field labels render at zinc-400 — consistent with the
canvas design system convention for subordinate label text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@1980computer 1980computer force-pushed the add-expression-editor branch from ee7c2f6 to da95c64 Compare June 10, 2026 20:20
@1980computer 1980computer force-pushed the add-properties-panel-form-manifest branch 2 times, most recently from af82409 to 8ef5f19 Compare June 10, 2026 22:25
1980computer and others added 2 commits June 10, 2026 16:00
- NodePropertyTrigger: extract MENU_ESTIMATED_HEIGHT/MENU_GAP/MENU_Z_INDEX
  constants, add (string & {}) to extensible union types, add uncontrolled
  fallback state (internalBehavior/internalLayout), close on scroll/resize,
  role=menuitemcheckbox + aria-checked on panels, role=menuitemradio +
  aria-checked on behavior/layout options, aria-label on delete button
- Fields: replace invalid theme() fallback with border-(--canvas-border)
  and focus:border-(--canvas-primary) in TextField, SelectField, NumberField
- NodeManifestPanel: reset activeStep on nodeType change, remove actions:[]
  so onSubmit is reachable, add empty-state for steps.length === 0, make
  onSubmit type async-compatible (void | Promise<void>)
- ProbeCard: guard preventDefault() with handler checks in onWheel,
  add [value] dep array to useLatestRef, remove stray eslint-disable
  comment from useDragSession
- Stories: replace eslint-disable comments with biome-ignore equivalents
- Tests: add 8 unit tests for NodeManifestPanel covering title bar,
  close callback, identity row, empty state, flat form, multi-step
  tabs, and nodeType change tab reset

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Component name now matches the Storybook display title
"Node Property Panel". The "Manifest" suffix was an implementation
detail (reads from the node registry manifest) rather than a
meaningful user-facing name.

- Rename folder: NodeManifestPanel/ → NodePropertyPanel/
- Rename all four files to NodePropertyPanel.*
- Rename exported symbol: NodeManifestPanel → NodePropertyPanel
- Rename props type: NodeManifestPanelProps → NodePropertyPanelProps
- Update barrel export in canvas/components/index.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@1980computer 1980computer force-pushed the add-properties-panel-form-manifest branch from 8ef5f19 to 9577354 Compare June 10, 2026 23:01
1980computer and others added 5 commits June 10, 2026 16:36
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- NodePropertyTrigger: init internalBehavior from behaviorOptions[0]
- NodePropertyPanel: derive mode from form.mode in multi-step path
- ProbeCard: merge two consecutive JSDoc blocks into one

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Probe story belongs to a separate PR — removing it to keep this PR focused.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r story

Restores ExpressionField as a standalone component adapted for the new
FormSchema architecture (no dependency on deleted ParameterDefinition types).

Phase 1: read-only display with Expr / JSON mode toggle, undo/redo chrome,
AI assist button, Insert variable affordance, and syntax-highlighted code
via CodeBlock.

Phase 2: live editing via Monaco/CodeMirror, variable binding ({x} pill),
real-time validation, and IntelliSense.

- ExpressionField exported from NodeManifestPanel barrel
- Expression Editor story added to Node Property Panel, rendered inside the
  panel frame matching the HttpRequest / HumanTask story format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@1980computer 1980computer force-pushed the add-expression-editor branch from da95c64 to bd8104b Compare June 11, 2026 00:03
@CalinaCristian CalinaCristian force-pushed the add-properties-panel-form-manifest branch 2 times, most recently from f2ade91 to ab5303c Compare June 11, 2026 10:55
@CalinaCristian CalinaCristian force-pushed the add-properties-panel-form-manifest branch 2 times, most recently from c6a7eab to cfc1b2f Compare June 11, 2026 12:43
Base automatically changed from add-properties-panel-form-manifest to ia-and-panel-nodes June 11, 2026 14:15
Base automatically changed from ia-and-panel-nodes to main June 12, 2026 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant