Skip to content

feat(apollo-react): add LockableValueField HITL prototype#893

Closed
dbacomputer wants to merge 12 commits into
mainfrom
hitl-prototype
Closed

feat(apollo-react): add LockableValueField HITL prototype#893
dbacomputer wants to merge 12 commits into
mainfrom
hitl-prototype

Conversation

@dbacomputer

@dbacomputer dbacomputer commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Prototype for a Quick Approve HITL panel demonstrating quick-form building and review inside the Property Panel experience, built on the InputGroup primitive from #890.

  • LockableValueField — a reusable field that can be locked to read-only and typed as one of several field types (String, Integer, Date, Boolean, Single select, Multiselect, File):

    • Left lock icon → popover with Unlocked / Locked. Locked fields render as plain read-only text (not a disabled control) across every field type, showing "String value" / "Write a string expression" as placeholder text depending on Fixed vs Expression mode.
    • Right type icon → popover with Fixed value / Expression, styling the value as code in Expression mode.
    • Compact container support: a Required-field toggle that collapses to an icon + popover at narrow widths.
    • AI-assist popover (describe what you want → Generate) and an Insert-variable affordance.
  • "Form HITL" story — the quick-form builder page:

    • Panel header, tabs (Parameters / Branching / Error handling), delivery-channel multi-select, and assignment search, matching other panel stories.
    • Draggable, reorderable field list (@dnd-kit, same pattern as StageNode) with a DragOverlay + synced insertion-line indicator.
    • "+ Add field" / "Add button" popover (two flat actions — no submenu) positioned above the button row.
    • Inline-editable form buttons (Approve/Cancel/custom): click to rename, hover to reveal an edit icon that expands the button and opens a Type (Primary/Secondary) + Delete popover. Buttons are sized to match the input rows.
    • UI / JSON view toggle plus a "more options" menu (Preview, Get URL, Describe-the-form-you-want AI stub).
    • Upload icon with a hover-card describing accepted file types/size.
  • "Form HITL Review" story — a read-only reviewer view of the same form (Reject/Approve actions in the header), sharing the same field-rendering logic as the builder's Preview mode.

  • apollo-wind Switch — added a proper sm size matching shadcn/ui's actual "Small" switch spec (14×24 track, 12px thumb); default size is unchanged.

Notes for reviewers

  • This is a review prototype, not production-wired — no schema/backend integration yet, and the AI-assist / Describe-the-form-you-want / Get URL actions are UI-only stubs.
  • The requested user-round-arrow-left icon isn't in the installed lucide-react@0.577.0 (added in 1.20.0); used UserRoundCheck instead rather than bumping a shared dependency across a major version for one icon.
  • Drag-and-drop uses the @dnd-kit dependency already used by StageNode, following the same sensor + overlay convention.

Test plan

  • pnpm exec tsc --noEmit — clean
  • pnpm biome check — clean
  • pnpm vitest run (NodePropertyPanel, Switch) — all existing tests pass, no regressions
  • Manually verified in Storybook: lock/unlock read-only behavior across all field types, Fixed/Expression mode + placeholder text, Required toggle (full + compact), drag-reorder, Add field/Add button, inline button editing + Type/Delete popover, button sizing, UI/JSON/Preview toggle, more-options menu, upload hover-card, tab labels, Form HITL Review parity

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings July 7, 2026 15:56
@github-actions

github-actions Bot commented Jul 7, 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 Jul 22, 2026, 04:10:25 PM
apollo-docs 🟢 Ready Preview, Logs Jul 22, 2026, 04:10:25 PM
apollo-landing 🟢 Ready Preview, Logs Jul 22, 2026, 04:10:25 PM
apollo-vertex 🟢 Ready Preview, Logs Jul 22, 2026, 04:10:25 PM

@github-actions

github-actions Bot commented Jul 7, 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.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

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

Adds a HITL-oriented LockableValueField prototype to the NodePropertyPanel Storybook surface, demonstrating quick-form editing patterns (lock/read-only, fixed vs expression, AI assist affordance) and a draggable list of fields.

Changes:

  • Introduces LockableValueField (lock toggle + value-type switcher + AI/insert affordances) built on @uipath/apollo-wind’s InputGroup.
  • Adds a new “Lockable Field” Storybook story that renders a Quick Approve-style panel, including a draggable/reorderable list of lockable fields.
  • Exports LockableValueField and its types from the NodePropertyPanel barrel.

Reviewed changes

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

File Description
packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx Adds the “Lockable Field” prototype story, including DnD-based field reordering and panel UI.
packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx Adds the new LockableValueField component (lock + mode switch + AI/insert affordances) using apollo-wind primitives.
packages/apollo-react/src/canvas/components/NodePropertyPanel/index.ts Re-exports LockableValueField and related types from the NodePropertyPanel module.

Comment on lines +190 to +197
<InputGroupInput
id={id}
readOnly={locked}
value={value}
onChange={(e) => onValueChange?.(e.target.value)}
placeholder={FIELD_PLACEHOLDER[mode]}
className={mode === 'expression' ? 'font-mono' : undefined}
/>
Comment on lines +65 to +69
export function LockableValueField({
value = '',
onValueChange,
locked = true,
onLockedChange,
Comment on lines +2788 to +2791
>
<Plus size={12} />
Add case
</button>
@github-actions

github-actions Bot commented Jul 7, 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 9.0% — (76 untracked) 43.84 MB 57.45 MB ±0
@uipath/apollo-react 37.3% 39.2% (129/329) 7.41 MB 28.39 MB +9.3 KB
@uipath/apollo-wind 41.1% 100.0% (17/17) 403.6 KB 2.63 MB +4.4 KB
@uipath/ap-chat 85.8% 100.0% (4/4) 43.43 MB 55.93 MB ±0

"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.

Copilot AI review requested due to automatic review settings July 8, 2026 19:03
@github-actions github-actions Bot added size:XXL 1,000+ changed lines. and removed size:XL 500-999 changed lines. labels Jul 8, 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 5 out of 6 changed files in this pull request and generated 9 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment on lines +15 to +19
/* Storybook (apps/storybook/.storybook/preview.tsx) imports this file
* directly, making it the Tailwind entry point for the whole app — including
* apollo-react's canvas stories. Without this, utility classes unique to
* apollo-react (not already used somewhere in apollo-wind) silently produce
* no CSS, since they'd never be scanned otherwise. */
* apollo-react's canvas stories. Without this, utility classes unique to
* apollo-react (not already used somewhere in apollo-wind) silently produce
* no CSS, since they'd never be scanned otherwise. */
@source "../../../apollo-react/src/**/*.{js,jsx,ts,tsx}"; No newline at end of file
Comment on lines +219 to +223
{label ?? (
<Label htmlFor={id} className="text-xs font-medium text-foreground-muted">
{FIELD_LABEL[mode]}
{required && <span className="ml-0.5 text-destructive">*</span>}
</Label>
Comment on lines +408 to +416
{value ? (
new Date(value).toLocaleDateString(undefined, {
year: 'numeric',
month: 'long',
day: 'numeric',
})
) : (
<span className="text-muted-foreground">Pick a date</span>
)}
Comment on lines +392 to +396
id={id}
checked={value === 'true'}
onCheckedChange={(checked) => onValueChange?.(String(checked))}
disabled={locked}
/>
Comment on lines +2702 to +2715
const handleJsonChange = (value: string) => {
setJsonDraft(value);
try {
const parsed = JSON.parse(value);
if (!Array.isArray(parsed)) {
setJsonError('Expected a JSON array of fields.');
return;
}
setCases(parsed);
setJsonError(null);
} catch {
setJsonError('Invalid JSON.');
}
};
Comment on lines +8 to +13
export {
DEMO_SELECT_OPTIONS,
FIELD_TYPE_META,
LockableValueField,
parseListValue,
} from './LockableValueField';
* the direction a full code-editing surface would take. Select/multiselect
* options are demo placeholders; file uploads aren't persisted anywhere.
*/
export function LockableValueField({
Comment on lines +170 to +172
id?: string;
className?: string;
}
Copilot AI review requested due to automatic review settings July 14, 2026 23:36

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 7 out of 8 changed files in this pull request and generated 8 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment on lines +16 to +20
* directly, making it the Tailwind entry point for the whole app — including
* apollo-react's canvas stories. Without this, utility classes unique to
* apollo-react (not already used somewhere in apollo-wind) silently produce
* no CSS, since they'd never be scanned otherwise. */
@source "../../../apollo-react/src/**/*.{js,jsx,ts,tsx}"; No newline at end of file
Comment on lines +179 to +182
const FIELD_LABEL: Record<LockableValueFieldMode, string> = {
fixed: 'String value',
expression: 'Write a string expression',
};
Comment on lines +227 to +230
<Label htmlFor={id} className="text-xs font-medium text-foreground-muted">
{FIELD_LABEL[mode]}
{required && <span className="ml-0.5 text-destructive">*</span>}
</Label>
Comment on lines +396 to +400
<InputGroupButton
icon
size="3xs"
aria-label={locked ? 'Locked. Click to unlock.' : 'Unlocked. Click to lock.'}
>
Comment on lines +571 to +575
<InputGroupButton
icon
size="3xs"
aria-label={locked ? 'Locked. Click to unlock.' : 'Unlocked. Click to lock.'}
>
Comment on lines +3021 to +3027
const parsed = JSON.parse(value);
if (!Array.isArray(parsed)) {
setJsonError('Expected a JSON array of fields.');
return;
}
setCases(parsed);
setJsonError(null);
Comment on lines +8 to +13
export {
DEMO_SELECT_OPTIONS,
FIELD_TYPE_META,
LockableValueField,
parseListValue,
} from './LockableValueField';
Comment on lines +199 to +203
export function LockableValueField({
value = '',
onValueChange,
locked = true,
onLockedChange,
Copilot AI review requested due to automatic review settings July 15, 2026 00:16

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 7 out of 8 changed files in this pull request and generated 7 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment on lines +226 to +231
{label ?? (
<Label htmlFor={id} className="text-xs font-medium text-foreground-muted">
{FIELD_LABEL[mode]}
{required && <span className="ml-0.5 text-destructive">*</span>}
</Label>
)}
Comment on lines +396 to +402
<InputGroupButton
icon
size="3xs"
aria-label={locked ? 'Locked. Click to unlock.' : 'Unlocked. Click to lock.'}
>
{locked ? <Lock /> : <LockOpen />}
</InputGroupButton>
Comment on lines +511 to +515
<DropdownMenuTrigger asChild>
<InputGroupButton icon size="3xs" aria-label="Choose value type">
<typeMeta.icon />
</InputGroupButton>
</DropdownMenuTrigger>
Comment on lines +8 to +13
export {
DEMO_SELECT_OPTIONS,
FIELD_TYPE_META,
LockableValueField,
parseListValue,
} from './LockableValueField';
Comment on lines +188 to +194
<button
type="button"
className="flex h-8 items-center gap-2 rounded-lg bg-brand px-4 text-sm font-semibold text-foreground-on-accent transition hover:bg-brand-hover"
>
<CircleCheck size={14} />
Approve
</button>
Comment on lines +3069 to +3082
const handleJsonChange = (value: string) => {
setJsonDraft(value);
try {
const parsed = JSON.parse(value);
if (!Array.isArray(parsed)) {
setJsonError('Expected a JSON array of fields.');
return;
}
setCases(parsed);
setJsonError(null);
} catch {
setJsonError('Invalid JSON.');
}
};
Comment on lines +15 to +20
/* Storybook (apps/storybook/.storybook/preview.tsx) imports this file
* directly, making it the Tailwind entry point for the whole app — including
* apollo-react's canvas stories. Without this, utility classes unique to
* apollo-react (not already used somewhere in apollo-wind) silently produce
* no CSS, since they'd never be scanned otherwise. */
@source "../../../apollo-react/src/**/*.{js,jsx,ts,tsx}"; No newline at end of file
Copilot AI review requested due to automatic review settings July 15, 2026 17:00

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 7 out of 8 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment on lines +3229 to +3235
type="button"
onClick={() => {
navigator.clipboard.writeText(
`${window.location.origin}/forms/quick-approve`
);
setMoreMenuOpen(false);
}}
Comment on lines 1 to 15
export type { ExpressionFieldProps, ExpressionMode } from './ExpressionField';
export { ExpressionField } from './ExpressionField';
export type {
LockableFieldType,
LockableValueFieldMode,
LockableValueFieldProps,
} from './LockableValueField';
export {
DEMO_SELECT_OPTIONS,
FIELD_TYPE_META,
LockableValueField,
parseListValue,
} from './LockableValueField';
export { NodePropertyPanel } from './NodePropertyPanel';
export type { NodePropertyPanelProps } from './NodePropertyPanel.types';
Comment on lines +251 to +256
{label ?? (
<Label htmlFor={id} className="text-xs font-medium text-foreground-muted">
{FIELD_LABEL[mode]}
{required && <span className="ml-0.5 text-destructive">*</span>}
</Label>
)}
Comment on lines +251 to +253
{label ?? (
<Label htmlFor={id} className="text-xs font-medium text-foreground-muted">
{FIELD_LABEL[mode]}
Comment on lines +190 to +207
/**
* LockableValueField — a field that can be locked to read-only, typed as one
* of several data types, and (for scalar types) switched between a literal
* value and a JS expression.
*
* Prototype: the expression mode is styled as code (monospace) but does not
* yet carry real syntax highlighting or evaluation. See ExpressionField for
* the direction a full code-editing surface would take. Select/multiselect
* options are demo placeholders; file uploads aren't persisted anywhere.
*/
export function LockableValueField({
value = '',
onValueChange,
locked = true,
onLockedChange,
mode = 'fixed',
onModeChange,
fieldType = 'string',
Comment on lines +16 to +20
* directly, making it the Tailwind entry point for the whole app — including
* apollo-react's canvas stories. Without this, utility classes unique to
* apollo-react (not already used somewhere in apollo-wind) silently produce
* no CSS, since they'd never be scanned otherwise. */
@source "../../../apollo-react/src/**/*.{js,jsx,ts,tsx}"; No newline at end of file
Copilot AI review requested due to automatic review settings July 15, 2026 23:15

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 7 out of 8 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment on lines +231 to +237
const lockedDisplayValue =
fieldType === 'boolean'
? value === 'true'
? 'True'
: 'False'
: fieldType === 'date'
? value
Comment on lines +255 to +260
{label ?? (
<Label htmlFor={id} className="text-xs font-medium text-foreground-muted">
{FIELD_LABEL[mode]}
{required && <span className="ml-0.5 text-destructive">*</span>}
</Label>
)}
Comment on lines +506 to +510
<Switch
id={id}
checked={value === 'true'}
onCheckedChange={(checked) => onValueChange?.(String(checked))}
/>
Prototype for a Quick Approve panel demonstrating quick-form editing
inside the Property Panel experience.

- LockableValueField: a string field built on apollo-wind's InputGroup,
  with a lock/unlock popover (locked = read-only, not disabled) and a
  Fixed value / Expression type-switcher popover, plus an AI-assist
  popover (describe + generate) and an Insert-variable affordance.
- NodePropertyPanel "Lockable Field" story: a Quick Approve panel with
  a Delivery channel multi-select, an Assignment criteria search +
  dropdown, and a Quick form section (UI/JSON toggle) containing a
  draggable, deletable, re-orderable list of LockableValueField rows
  seeded with Invoice Number / Submission Date / Approved Amount.

Built entirely on existing apollo-wind primitives (InputGroup,
DropdownMenu, Popover, MultiSelect, Select, Card, ToggleGroup) and the
existing @dnd-kit dependency already used by StageNode, following this
file's established prototype conventions (PanelFrame, CasePanel-style
row chrome). No production wiring yet — this is a review prototype.
…build

Storybook imports apollo-wind's tailwind.css directly as its Tailwind
entry point, including for apollo-react's canvas stories, but the
@source glob only covered apollo-wind's own files. Utility classes
unique to apollo-react (e.g. container-query variants) silently
produced no CSS since they were never scanned.

Also pins @tailwindcss/vite to an exact version already cleared by the
pnpm minimumReleaseAge policy, keeping it aligned with the tailwindcss
core version resolved elsewhere in the workspace.
dbacomputer and others added 7 commits July 21, 2026 08:20
Iterates the HITL "Quick Approve" panel prototype for coworker
feedback:

- Field-type switching (string, integer, date, boolean, single/multi
  select, file) with per-type value controls and Fixed/Expression
  copy.
- Responsive header: field-type/AI-assist/insert-variable controls
  collapse to icon-only in narrow containers, plus a `compact` prop to
  force that layout for side-by-side comparison.
- Real tooltips on the icon-only header controls instead of native
  title attributes.
- Edit/Preview/JSON toggle for the Quick Form card, restyled to
  borderless square icon buttons matching the compact header controls.
- Showcase panel documenting the component with live Full view /
  Compact view examples.
… HITL prototype

Adds a Required/Not-required toggle (full-view switch, compact icon+popover
variant), an upload-triggering icon on the demo file card, a type-selector
dropdown behind "+ Add field" (including a new Button field type), and
Approve/Cancel form buttons editable inline. Replaces the field-reorder
insertion-line indicator with a DragOverlay + synced placeholder, mirroring
StageNode's existing dnd-kit pattern, since the prior indicator was visually
inconsistent during drag.

Also fixes apollo-wind's Switch "sm" size to match shadcn/ui's actual Small
spec (track 14x24, thumb 12px) and updates its tests accordingly, and fixes
a hover-visibility bug where a field's controls would fade out while their
own popover/dropdown was still open (Tooltip/Popover asChild data-state
collision fixed by keying off aria-expanded instead).
…ew switcher

Moves the form-button edit affordance (Type/Delete popover) inside the
button pill and makes it expand on hover instead of floating a
separate icon; wires the buttons into the Preview view so they
actually render there. Reworks the Quick form view row into a
standalone "more options" menu (Preview, Describe the form you want)
plus a connected UI/JSON segmented toggle, replacing the earlier
three-icon row for a cleaner layout. Also drops the header icon on
Form HITL Review to free up title space next to the Reject/Approve
actions.
… menu

Moves the "String value"/"Write a string expression" text to the
field's inside placeholder (it was incorrectly placed as the label
above the field) so it now shows consistently across all locked
field types, matching the LockableValueField showcase used as the
source of truth.

Simplifies the Add field/Add button popover down to two flat
actions (dropping the field-type submenu, since choosing a type
after adding wasn't needed), reorders it above the buttons row, and
resizes form buttons to match input height. Also renames the
builder tabs to Parameters / Branching / Error handling.
Empty commit to refresh the PR's Storybook preview deployment with
today's Form HITL changes for coworker review.
- Controls default to Show instead of Hide across the showcase and both
  Form HITL / Form HITL Review panels.
- Fixed/Expression trigger icon no longer varies by field type (was
  swapping to the per-type icon; now strictly Type vs Code2).
- Simplified the "more" menu to a single AI-generate action (dropped
  Preview and Get link) and removed the now-unused Preview/JSON views
  and the UI/JSON toggle from the Quick form builder.
- Added a header-synced close (X) action to LockableValueField via
  headerActions, wired to controlsVisibility, and fixed the same
  affordance on the left-panel field rows (previously hardcoded to
  row-hover regardless of the Show/Hide toggle).
- Swapped the Insert-variable glyph from a "{x}" text glyph to a Braces
  icon so it reads distinctly from the new close X.
- Added a showFieldActions prop to suppress the AI-assist/Insert-variable
  actions for read-only reviewer contexts, and used it on the Form HITL
  Review left panel so reviewers can't reconfigure fields they're only
  meant to approve.
- Renamed the lock toggle's Locked/Unlocked language to Read-only/Editable
  everywhere it appears (aria-labels, dropdown items, showcase copy).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…opy action

Coworker feedback (Dushyant/Prabhat) flagged that removing the JSON
toggle overfit on the Flow Canvas builder experience and cut against
QuickForms' schema-first design: JSON is what Case Management/Coded
Apps users and generation agents actually work from, and it's expected
to stay available at parity with the low-code builder (FormIO parity).

- Reintroduce the UI/JSON ToggleGroup in the Quick form header, wired
  to a formView state (edit/json only — Preview stays removed).
- JSON view shows the live field schema in a synced textarea; editing
  it round-trips back into the field list, and building fields in the
  UI updates the JSON live.
- Add a one-click copy icon (Copy/CircleCheck swap, matching the
  existing copyExpr pattern) for grabbing the schema.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 21, 2026 15:39
@dbacomputer
dbacomputer force-pushed the hitl-prototype branch 2 times, most recently from 0bd6d11 to f6df0cc Compare July 21, 2026 15:39

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 7 out of 8 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Comments suppressed due to low confidence (5)

packages/apollo-wind/src/styles/tailwind.css:20

  • Adding @source pointing at apollo-react/src makes apollo-wind’s internal build entry point depend on a sibling package and will pull apollo-react-only utilities into @uipath/apollo-wind/styles.css, increasing bundle size and coupling builds across packages. Prefer a Storybook-only Tailwind entry/config that adds the extra scan paths without changing apollo-wind’s library build input.
/* Storybook (apps/storybook/.storybook/preview.tsx) imports this file
 * directly, making it the Tailwind entry point for the whole app — including
 * apollo-react's canvas stories. Without this, utility classes unique to
 * apollo-react (not already used somewhere in apollo-wind) silently produce
 * no CSS, since they'd never be scanned otherwise. */
@source "../../../apollo-react/src/**/*.{js,jsx,ts,tsx}";

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:236

  • When fieldType === 'boolean' and value is empty, lockedDisplayValue currently becomes "False", which prevents the placeholder from showing and misrepresents an unset value. Treat unknown/empty values as empty string so the placeholder can appear.
    fieldType === 'boolean'
      ? value === 'true'
        ? 'True'
        : 'False'
      : fieldType === 'date'

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:259

  • The default label uses FIELD_LABEL[mode], but effectiveMode forces 'fixed' for types that don’t support expressions. If a consumer passes mode="expression" with a non-expression type, the label becomes misleading. Use effectiveMode for the default label.
        {label ?? (
          <Label htmlFor={id} className="text-xs font-medium text-foreground-muted">
            {FIELD_LABEL[mode]}
            {required && <span className="ml-0.5 text-destructive">*</span>}
          </Label>

packages/apollo-react/src/canvas/components/NodePropertyPanel/index.ts:12

  • DEMO_SELECT_OPTIONS is explicitly a demo placeholder (per the component doc comment) but is re-exported from the public NodePropertyPanel barrel, which effectively makes it part of the public API surface. Consider keeping it internal (or story-only) and only exporting the component/types (and optionally stable metadata like FIELD_TYPE_META).
export {
  DEMO_SELECT_OPTIONS,
  FIELD_TYPE_META,
  LockableValueField,
  parseListValue,

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:207

  • LockableValueField is a new exported canvas component, but there are no unit tests covering its core behaviors (locked vs unlocked rendering, mode switching, boolean/date rendering, etc.). Since this package already has Vitest coverage for NodePropertyPanel in the same directory, adding a focused test suite for this component would help prevent regressions.
export function LockableValueField({
  value = '',
  onValueChange,
  locked = true,
  onLockedChange,

Comment on lines 27 to 30
size: {
default: 'h-5 w-5 data-[state=checked]:translate-x-5',
sm: 'h-4 w-4 data-[state=checked]:translate-x-4',
sm: 'size-3 data-[state=checked]:translate-x-[calc(100%-2px)]',
},
Comment on lines +3207 to +3212
<TabsTrigger value="error-handling" className={TAB_TRIGGER_CLASS}>
Branching
</TabsTrigger>
<TabsTrigger value="advanced" className={TAB_TRIGGER_CLASS}>
Error handling
</TabsTrigger>
Comment on lines +3488 to +3489
<TabsContent value="error-handling" className="mt-0" />
<TabsContent value="advanced" className="mt-0" />
Comment on lines +3543 to +3548
<TabsTrigger value="error-handling" className={TAB_TRIGGER_CLASS}>
Branching
</TabsTrigger>
<TabsTrigger value="advanced" className={TAB_TRIGGER_CLASS}>
Error handling
</TabsTrigger>
Comment on lines +3602 to +3603
<TabsContent value="error-handling" className="mt-0" />
<TabsContent value="advanced" className="mt-0" />
"@storybook/react": "^10.4.1",
"@storybook/react-vite": "^10.4.1",
"@tailwindcss/vite": "^4.2.2",
"@tailwindcss/vite": "4.3.0",
… type icons

Coworker feedback round:
- Add field now adds a string field directly on click instead of
  opening a popover menu.
- Add button moved out of that menu into its own ghost + icon button,
  placed to the right of the Approve/Cancel row.
- New buttons default to the label "Button" instead of "New button".
- The Editable/Read-only lock toggle no longer opens a dropdown --
  clicking the icon flips the state directly, with a tooltip naming
  the current state instead of the old submenu subtext.
- String's field-type icon switched to ALargeSmall (Aa) so it no
  longer collides with the Fixed/Expression toggle's Type (T) icon
  when a field is a string in Fixed mode.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 22, 2026 18:45

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 7 out of 8 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Comments suppressed due to low confidence (7)

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:258

  • The default label uses mode even when the selected fieldType does not support expressions. This contradicts the prop contract (“Ignored for types that don't support expressions”) and can display “Write a string expression” while the field is forced into fixed mode.
            {FIELD_LABEL[mode]}

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:236

  • Locked boolean fields currently render "False" when the value is empty/unset. That makes an unset value indistinguishable from an explicit false and also conflicts with the placeholder behavior used by the other types.
    fieldType === 'boolean'
      ? value === 'true'
        ? 'True'
        : 'False'

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:474

  • The boolean control inside InputGroup doesn't set data-slot="input-group-control", so InputGroup can't apply its focus ring/disabled styling (it keys off [data-slot=input-group-control] in apollo-wind's InputGroup).
              <Switch
                id={id}
                checked={value === 'true'}
                onCheckedChange={(checked) => onValueChange?.(String(checked))}
              />

packages/apollo-react/src/canvas/components/NodePropertyPanel/index.ts:13

  • DEMO_SELECT_OPTIONS is exported from the public barrel, which effectively makes a demo placeholder part of the package API surface. This is hard to support long-term and makes it easy for consumers to depend on non-production data.
export {
  DEMO_SELECT_OPTIONS,
  FIELD_TYPE_META,
  LockableValueField,
  parseListValue,
} from './LockableValueField';

packages/apollo-wind/src/styles/tailwind.css:20

  • Adding @source for apollo-react/src in apollo-wind’s internal Tailwind entry point will cause packages/apollo-wind’s build (build:css compiles dist/styles.css from this file) to include utility classes used only by apollo-react stories. That couples apollo-wind’s shipped CSS size/content to apollo-react changes and can significantly bloat the distributed styles.css. Prefer keeping this file scoped to apollo-wind and instead add a Storybook-only Tailwind entry (or additional @source in Storybook’s own CSS) for scanning apollo-react.
/* Storybook (apps/storybook/.storybook/preview.tsx) imports this file
 * directly, making it the Tailwind entry point for the whole app — including
 * apollo-react's canvas stories. Without this, utility classes unique to
 * apollo-react (not already used somewhere in apollo-wind) silently produce
 * no CSS, since they'd never be scanned otherwise. */
@source "../../../apollo-react/src/**/*.{js,jsx,ts,tsx}";

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

  • In the JSON editor, any JSON array is accepted and assigned directly to cases. If an element is missing required fields (e.g. id, title, fieldType) or has invalid values, the story can crash later when rendering (e.g. indexing FIELD_TYPE_META with an invalid fieldType).
      }
      setCases(parsed);
      setJsonError(null);

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:204

  • LockableValueField introduces non-trivial behavior (mode/type switching, locked read-only rendering, list parsing) but currently has no dedicated unit tests. Since this folder already has Vitest coverage for NodePropertyPanel, adding a small test suite here would help prevent regressions (e.g. effectiveMode behavior for non-expression field types, locked display values).
export function LockableValueField({

…rison

Swapped lucide's Lock/LockOpen for raw Material Symbols Outlined glyphs
(FILL 0, wght 400, GRAD 0, opsz 24) on the lock toggle, unmodified, so
we can judge the actual Material look side-by-side against the rest of
the lucide-based icon set before deciding whether to keep it, redraw it
in lucide's stroke style, or revert. Not a final decision either way --
waiting on feedback.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 22, 2026 23:04

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 7 out of 8 changed files in this pull request and generated 5 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Comments suppressed due to low confidence (8)

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:302

  • The default label is driven by mode, but for field types that don't support expressions effectiveMode forces 'fixed'. Using mode here can show an expression label even though the control is fixed-only.
            {FIELD_LABEL[mode]}

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:280

  • When locked and fieldType === 'boolean', an empty value currently renders as "False" (because anything other than the string "true" maps to False). This prevents the placeholder from ever showing for unset boolean values.
  const lockedDisplayValue =
    fieldType === 'boolean'
      ? value === 'true'
        ? 'True'
        : 'False'

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:288

  • For locked date fields, invalid date strings will render "Invalid Date" via toLocaleDateString. This can happen if value is user-edited (e.g. JSON view in the story) or comes from an unexpected source; treat invalid dates as empty so the placeholder can render.
      : fieldType === 'date'
        ? value
          ? new Date(value).toLocaleDateString(undefined, {
              year: 'numeric',
              month: 'long',
              day: 'numeric',
            })
          : ''

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:533

  • The date trigger formats new Date(value) directly. If value is not a valid ISO date, this will display "Invalid Date" instead of the placeholder.
                  {value ? (
                    new Date(value).toLocaleDateString(undefined, {
                      year: 'numeric',
                      month: 'long',
                      day: 'numeric',

packages/apollo-react/src/canvas/components/NodePropertyPanel/index.ts:12

  • The NodePropertyPanel barrel export currently re-exports DEMO_SELECT_OPTIONS, which further exposes demo-only data as part of the public canvas components API.
export {
  DEMO_SELECT_OPTIONS,
  FIELD_TYPE_META,
  LockableValueField,
  parseListValue,

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

  • In the JSON view, setCases(parsed) accepts any array shape. If a user edits JSON to omit id (or uses a non-number), drag-and-drop and rendering can break because useSortable expects stable ids.
  const handleJsonChange = (value: string) => {
    setJsonDraft(value);
    try {
      const parsed = JSON.parse(value);
      if (!Array.isArray(parsed)) {

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

  • The custom "Approve" <button> lacks the focus-visible styling that Button provides, so keyboard users won't get a visible focus indicator.
      <button
        type="button"
        className="flex h-8 items-center gap-2 rounded-lg bg-brand px-4 text-sm font-semibold text-foreground-on-accent transition hover:bg-brand-hover"
      >
        <CircleCheck size={14} />

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:248

  • LockableValueField introduces several non-trivial behaviors (mode coercion via effectiveMode, locked display formatting for boolean/date, multi-select JSON encoding, etc.) but currently has no unit tests alongside the existing NodePropertyPanel.test.tsx. Adding targeted tests would help prevent regressions as this prototype evolves.
export function LockableValueField({

<PopoverContent align="start" className="w-auto p-0">
<Calendar
mode="single"
selected={value ? new Date(value) : undefined}
Comment on lines +524 to +528
type="button"
id={id}
data-slot="input-group-control"
className="flex h-full flex-1 items-center text-left text-sm text-foreground outline-none"
>
Comment on lines +178 to +182
export const DEMO_SELECT_OPTIONS = [
{ label: 'Option 1', value: 'option-1' },
{ label: 'Option 2', value: 'option-2' },
{ label: 'Option 3', value: 'option-3' },
];
Comment on lines +3273 to +3278
<input
ref={fileInputRef}
type="file"
className="hidden"
onChange={() => {}}
/>
Comment on lines +478 to +482
<InputGroupButton
icon
size="3xs"
onClick={() => onLockedChange?.(!locked)}
aria-label={
…opy action

Swap the Form HITL JSON view's plain Textarea for the same Monaco
editor treatment used on the Input / Output panels (syntax
highlighting, same theme wiring, same rounded-card chrome), so the
schema view is visually consistent across both surfaces. Stays
editable (unlike Input/Output's read-only JSON tab) via a dedicated
JSON_EDITOR_OPTIONS variant.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 23, 2026 19:14

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 7 out of 8 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Comments suppressed due to low confidence (5)

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:305

  • For field types that don’t support expressions, mode is documented as ignored, but the default label still uses mode. This can show an “expression” label even though the control is forced to fixed. Use effectiveMode for the label to keep UI consistent with the actual rendered mode.
      <div className="flex items-center gap-1">
        {label ?? (
          <Label htmlFor={id} className="text-xs font-medium text-foreground-muted">
            {FIELD_LABEL[mode]}
            {required && <span className="ml-0.5 text-destructive">*</span>}
          </Label>
        )}

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:281

  • When the field is boolean and value is empty, the locked display currently renders “False”, which is misleading (it reads like a real value). Consider rendering an empty string when no value is set.
    fieldType === 'boolean'
      ? value === 'true'
        ? 'True'
        : 'False'
      : fieldType === 'date'

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

  • The logo upload hover-card says it accepts PNG/JPG/SVG, but the hidden file input doesn’t constrain file types. Add an accept attribute so the file picker matches the UI guidance.
                      <input
                        ref={fileInputRef}
                        type="file"
                        className="hidden"
                        onChange={() => {}}

packages/apollo-wind/src/styles/tailwind.css:20

  • src/styles/tailwind.css is used to build the published dist/styles.css (see build:css), so adding @source ../../../apollo-react/... will pull apollo-react’s utility usage into apollo-wind’s precompiled CSS. That increases CSS size and couples apollo-wind’s build output to a sibling workspace. Prefer keeping library @source limited to apollo-wind, and add a Storybook-only Tailwind entry (or move this extra @source into the Storybook app’s CSS entry) so it doesn’t affect published artifacts.
 * directly, making it the Tailwind entry point for the whole app — including
 * apollo-react's canvas stories. Without this, utility classes unique to
 * apollo-react (not already used somewhere in apollo-wind) silently produce
 * no CSS, since they'd never be scanned otherwise. */
@source "../../../apollo-react/src/**/*.{js,jsx,ts,tsx}";

packages/apollo-react/src/canvas/components/NodePropertyPanel/LockableValueField.tsx:252

  • LockableValueField is a new exported component under canvas/components/NodePropertyPanel, but there are no unit tests covering its locked/unlocked behavior, mode switching, and per-field-type rendering (boolean/date/select/multi-select/file). Since this package already has Vitest coverage for NodePropertyPanel, adding a focused test suite would help prevent regressions as the prototype evolves.
/**
 * LockableValueField — a field that can be locked to read-only, typed as one
 * of several data types, and (for scalar types) switched between a literal
 * value and a JS expression.
 *
 * Prototype: the expression mode is styled as code (monospace) but does not
 * yet carry real syntax highlighting or evaluation. See ExpressionField for
 * the direction a full code-editing surface would take. Select/multiselect
 * options are demo placeholders; file uploads aren't persisted anywhere.
 */
export function LockableValueField({
  value = '',
  onValueChange,
  locked = true,
  onLockedChange,

@dbacomputer

Copy link
Copy Markdown
Collaborator Author

Superseded by #960, which promotes this prototype's LockableValueField into a real, tested component in apollo-wind and wires the apollo-react Form HITL panel to consume it. Closing to avoid confusion.

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