feat(apollo-react): add ExpressionEditor field type for NodeManifestPanel#793
Open
1980computer wants to merge 19 commits into
Open
feat(apollo-react): add ExpressionEditor field type for NodeManifestPanel#7931980computer wants to merge 19 commits into
1980computer wants to merge 19 commits into
Conversation
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>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Dependency License Review
License distribution
Excluded packages
|
- 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>
ee7c2f6 to
da95c64
Compare
af82409 to
8ef5f19
Compare
- 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>
8ef5f19 to
9577354
Compare
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>
da95c64 to
bd8104b
Compare
f2ade91 to
ab5303c
Compare
c6a7eab to
cfc1b2f
Compare
Base automatically changed from
add-properties-panel-form-manifest
to
ia-and-panel-nodes
June 11, 2026 14:15
60208e7 to
479392b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an
ExpressionEditorcustom field type for use withNodeManifestPanelviaMetadataForm'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 propertype: 'custom'field, backed by Monaco/CodeMirror.What this will add
ExpressionEditor— custom MetadataForm field component registered via the plugin systemexprmode (JavaScript/TypeScript) andjsonmode (JSON template)ExpressionEditorstory added to Node Property PanelDepends on
Not yet included
{x}bind button — Phase 2🤖 Generated with Claude Code