Skip to content

feat(apollo-wind): add reusable variable picker - #1020

Open
dbacomputer wants to merge 7 commits into
mainfrom
codex/add-insert-variable-popover-output-panel
Open

feat(apollo-wind): add reusable variable picker#1020
dbacomputer wants to merge 7 commits into
mainfrom
codex/add-insert-variable-popover-output-panel

Conversation

@dbacomputer

@dbacomputer dbacomputer commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

What this adds

Reusable Insert Variable component

  • adds a searchable, hierarchical VariablePicker to Apollo Wind
  • supports nested variables, type badges, keyboard navigation, controlled state, and custom triggers
  • exports VariablePicker and VariablePickerItem for consumers
  • documents the component under Apollo Wind → UiPath, directly after Lockable Value Field
Screenshot 2026-08-06 at 8 37 03 AM

Add Variable tree action

  • adds a hover-state Add variable action alongside Wrap value and Copy value
  • clicking Add variable creates an editable sibling row (field2, field3, etc.), expands its parent, and focuses the blank value
  • keeps up to three actions inline; when a row has four or more, all actions move into a single ••• menu
  • adds functional Delete variable examples as the fourth action
  • keeps the ••• trigger visible while open and positions the menu beside the cursor with the first action immediately accessible
  • applies the overflow rule to the shared tree action renderer, not only the Storybook example
Screenshot 2026-08-06 at 8 37 33 AM

Aligned Node Property Panel examples

  • enables Insert Variable across the applicable full, compact, inline, quick-form, and inventory panel examples
  • aligns the standalone Input / Output tree styling and actions with the three-column Input / Output example
  • preserves consumer ownership of insertion: selecting a variable returns the item, while the editor decides where to insert its value
Screenshot 2026-08-06 at 8 37 20 AM

Validation

  • Apollo Wind and Apollo React TypeScript checks
  • Biome checks for all touched files
  • VariablePicker tests: 3 passing
  • LockableValueField and VariablePicker tests: 58 passing
  • NodeIOView tests: 55 passing
  • Apollo Wind production build
  • live Storybook verification of picker insertion, editable row creation, deletion, three-action and overflow states, cursor-aligned menus, tooltips, and sidebar placement

Copilot AI review requested due to automatic review settings August 5, 2026 21:30
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Apollo Coded App preview deployments are running.

Project Status Preview Updated (PT)
apollo-design Deploying... Logs Aug 06, 2026, 08:40:26 AM
apollo-docs Deploying... Logs Aug 06, 2026, 08:40:26 AM
apollo-landing Deploying... Logs Aug 06, 2026, 08:40:26 AM
apollo-vertex Deploying... Logs Aug 06, 2026, 08:40:26 AM

@github-actions github-actions Bot added the size:XL 500-999 changed lines. label Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Dependency License Review

  • 1950 package(s) scanned
  • ✅ No license issues found
  • ⚠️ 2 package(s) excluded (see details below)
License distribution
License Packages
MIT 1720
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.3.2 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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a reusable VariablePicker component in apollo-wind (searchable hierarchical variable insertion UI) and wires it into existing variable-insertion surfaces (LockableValueField + apollo-react canvas editors/stories), while also refining some canvas alignment guide rendering and Storybook sidebar ordering.

Changes:

  • Added and publicly exported VariablePicker (+ tests + Storybook docs) in @uipath/apollo-wind.
  • Integrated the picker into LockableValueField and apollo-react ExpressionField / NodePropertyPanel stories to standardize insertion UX.
  • Updated alignment guide rendering to show all matching anchors at the snapped position, plus Storybook ordering adjustments.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/apollo-wind/src/index.ts Exports VariablePicker and its public types from the package entrypoint.
packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx Implements the new hierarchical/searchable picker component.
packages/apollo-wind/src/components/ui/variable-picker/variable-picker.test.tsx Adds unit tests for open/selection/search/empty-state behavior.
packages/apollo-wind/src/components/ui/variable-picker/variable-picker.stories.tsx Adds Storybook documentation + usage examples (custom trigger, controlled, disabled, empty).
packages/apollo-wind/src/components/ui/variable-picker/index.ts Barrel export for the new component and types.
packages/apollo-wind/src/components/ui/lockable-value-field/lockable-value-field.test.tsx Updates the insertion test to match the picker’s option role.
packages/apollo-wind/src/components/ui/lockable-value-field/components/field-header.tsx Replaces the dropdown-based insert UI with VariablePicker.
packages/apollo-wind/.storybook/preview.tsx Adjusts Storybook sort order to place Variable Picker after Lockable Value Field.
packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx Uses VariablePicker in editor toolbars and aligns IO tree row actions (wrap/copy/add-variable/toasts).
packages/apollo-react/src/canvas/components/NodePropertyPanel/ExpressionField.tsx Adds variable picker support via new variables / onInsertVariable props.
packages/apollo-react/src/canvas/components/AlignmentGuides/useAlignmentGuides.ts Updates guide rendering to show all exact matches at the snapped position.
packages/apollo-react/src/canvas/components/AlignmentGuides/useAlignmentGuides.test.ts Updates/adds tests for multiple guide rendering and unique IDs.
packages/apollo-react/src/canvas/components/AlignmentGuides/AlignmentGuides.stories.tsx Tweaks multiselect story interactions (shift-click selection behavior).
apps/storybook/.storybook/preview.tsx Mirrors Storybook sort order adjustments in the root Storybook app.
Suppressed comments (1)

packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx:1889

  • JSON.stringify(value) is evaluated before clipboard.writeText(...) and can throw (e.g., circular structures, BigInt). That would crash the Storybook interaction. Consider guarding the stringify and falling back to String(value) on failure.
  const copyValue = (node: OutputNode) => {
    const value = editedValues[node.path] ?? node.value;
    navigator.clipboard
      ?.writeText(typeof value === 'string' ? value : JSON.stringify(value))
      ?.then(() => {

Comment thread apps/storybook/.storybook/preview.tsx
Comment thread packages/apollo-wind/.storybook/preview.tsx
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

📊 Coverage + size by package

Per-package coverage and bundle size on this PR. New-line coverage = of the source lines this PR adds or changes, the % hit by tests.

Package Coverage New-line coverage Packed (gzip) Unpacked vs main
@uipath/apollo-core
@uipath/apollo-react — (no coverage report)
@uipath/apollo-wind — (no coverage report)
@uipath/ap-chat

"Coverage" is each package's own coverage.include scope (e.g. apollo-core instruments only scripts/). "Packed"/"Unpacked" come from npm pack --dry-run and only cover built packages — "—" means not measured this run (package not affected / not built). "vs main" is the packed (gzipped) delta against the last successful main build (the package-sizes artifact from the Release workflow); "—" there means no main baseline was available this run. The baseline is main's latest build, not this PR's exact merge-base, so it includes any drift since the branch diverged. Packages with no vitest config are omitted.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Storybook visual diff

⚠️ Visual changes detected: 15 changed, 5 added (of 333 compared, 313 unchanged). View report

Baseline is the deployed main Storybook, so changes merged to main after this branch was last updated can also appear here. Logs

Updated (PT): Aug 06, 2026, 08:07:44 AM

Copilot AI review requested due to automatic review settings August 6, 2026 14:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Suppressed comments (3)

packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx:166

  • expandedIds is only initialized from items once. If items is empty initially (e.g., async load) or later replaced, opening the picker can show everything collapsed because the default-expanded group is never re-derived from the latest items. Consider re-seeding expansion when the popover opens if the current expanded IDs don’t match the current root items.
  const setOpen = (nextOpen: boolean) => {
    if (controlledOpen === undefined) setUncontrolledOpen(nextOpen);
    if (!nextOpen) setQuery('');
    onOpenChange?.(nextOpen);
  };

packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx:1302

  • This file contains (em dash with spaces) in Storybook content, which is disallowed by repo convention (see CLAUDE.md:5-13). Please replace it with a period/colon/comma.
// Inline expression inputs — one per case, no code editor panel.

packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx:69

  • Using toLocaleLowerCase() for search normalization can cause surprising matches in some locales (it’s locale-sensitive). For consistent search behavior across environments, prefer toLowerCase() here.
function matchesItem(item: VariablePickerItem, query: string): boolean {
  if (!query) return true;
  const normalizedQuery = query.toLocaleLowerCase();
  return (
    item.label.toLocaleLowerCase().includes(normalizedQuery) ||

Copilot AI review requested due to automatic review settings August 6, 2026 14:46
@github-actions github-actions Bot added size:XXL 1,000+ changed lines. and removed size:XL 500-999 changed lines. labels Aug 6, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Suppressed comments (4)

packages/apollo-wind/.storybook/preview.tsx:87

  • The Storybook storySort.order structure looks malformed here: UiPath is listed as a standalone entry and the following array of children is not nested under it. This can cause Storybook to treat the child list as a separate top-level group instead of ordering under UiPath.
            'Overlays',
            'UiPath',
            [
              'Lockable Value Field',
              'Variable Picker',

packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx:166

  • expandedIds is initialized from items only on the first render. If items is initially empty (common for async data) and later populated, opening the picker won't expand the first group as intended. Consider seeding expandedIds the first time the popover opens when it’s still empty.
  const setOpen = (nextOpen: boolean) => {
    if (controlledOpen === undefined) setUncontrolledOpen(nextOpen);
    if (!nextOpen) setQuery('');
    onOpenChange?.(nextOpen);
  };

apps/storybook/.storybook/preview.tsx:172

  • The Storybook storySort.order structure appears malformed: UiPath is a standalone entry and the subsequent array of story names is not nested beneath it. Storybook ordering expects nested arrays like ['UiPath', [...]] for hierarchical groups.
              'Overlays',
              'UiPath',
              [
                'Lockable Value Field',
                'Variable Picker',

packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx:67

  • Using toLocaleLowerCase() for search matching makes results locale-dependent (e.g., Turkish locale casing) and can yield inconsistent filtering across environments. Prefer deterministic toLowerCase() for UI search normalization.
  const normalizedQuery = query.toLocaleLowerCase();
  return (
    item.label.toLocaleLowerCase().includes(normalizedQuery) ||
    item.value?.toLocaleLowerCase().includes(normalizedQuery) === true ||
    item.children?.some((child) => matchesItem(child, query)) === true

Copilot AI review requested due to automatic review settings August 6, 2026 15:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (2)

packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx:1304

  • Story files should avoid using em dashes () in documentation copy. Replace this em dash with punctuation that matches the repo guideline (e.g. a period or colon).
// ============================================================================
// Input Editor
// Inline expression inputs — one per case, no code editor panel.
// ============================================================================

packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx:69

  • matchesItem uses toLocaleLowerCase(), which makes search behavior locale-dependent (e.g. Turkish-I edge cases). For deterministic, locale-agnostic matching, prefer toLowerCase() for both the query and item fields.
function matchesItem(item: VariablePickerItem, query: string): boolean {
  if (!query) return true;
  const normalizedQuery = query.toLocaleLowerCase();
  return (
    item.label.toLocaleLowerCase().includes(normalizedQuery) ||
    item.value?.toLocaleLowerCase().includes(normalizedQuery) === true ||
    item.children?.some((child) => matchesItem(child, query)) === true
  );

Copilot AI review requested due to automatic review settings August 6, 2026 15:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (4)

packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx:1303

  • Avoid using em dashes in Storybook stories content/comments so the docs copy stays consistent with repo conventions.
// Inline expression inputs — one per case, no code editor panel.

packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx:4686

  • The doc comment above useFileNodeActions no longer matches the behavior after adding the Add variable action (non-file rows now return actions; read-only file rows return Add variable). It also uses em dashes, which we avoid in Storybook docs text.
 */
function useFileNodeActions(): {
  nodeActions: NodeActionsResolver;
  preview: PreviewedFile | null;
  clearPreview: () => void;

packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx:69

  • matchesItem uses toLocaleLowerCase(), which can produce locale-dependent casing behavior. For search matching, toLowerCase() is typically more predictable and consistent across environments.
  const normalizedQuery = query.toLocaleLowerCase();
  return (
    item.label.toLocaleLowerCase().includes(normalizedQuery) ||
    item.value?.toLocaleLowerCase().includes(normalizedQuery) === true ||
    item.children?.some((child) => matchesItem(child, query)) === true

packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx:98

  • CommandItem renders a cmdk option (role="option"), and aria-expanded is not a valid ARIA state for that role. Consider using a data-* attribute for styling, or switching to true tree semantics if you need expanded/collapsed announcements.
            aria-expanded={hasChildren ? expanded : undefined}

Copilot AI review requested due to automatic review settings August 6, 2026 15:34

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx:1303

  • Story source comment uses an em dash (" — "). The repo guideline for .stories.tsx content avoids em dashes because the source is user-visible in Storybook docs; please replace with a period/colon instead.
// Inline expression inputs — one per case, no code editor panel.

Copilot AI review requested due to automatic review settings August 6, 2026 15:43
@dbacomputer
dbacomputer force-pushed the codex/add-insert-variable-popover-output-panel branch from 4dfc99f to fec447e Compare August 6, 2026 15:43
@dbacomputer
dbacomputer marked this pull request as ready for review August 6, 2026 15:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (2)

packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx:51

  • children is passed as the PopoverTrigger child with asChild, which requires a single React element. Typing this as ReactNode allows strings/fragments/arrays that will crash at runtime when Radix tries to clone the child. Narrow the type so invalid triggers are caught by TypeScript.
  children?: ReactNode;

packages/apollo-wind/src/components/ui/variable-picker/variable-picker.tsx:95

  • cmdk uses the CommandItem value as the item's identity for selection/active state. Building it from label/value can collide even when id is unique, which can cause incorrect highlighting/selection when two variables share the same label or path segment. Use the guaranteed-unique id instead.
            value={`${item.label} ${item.value ?? ''}`}

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.

2 participants