Skip to content

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

Draft
dbacomputer wants to merge 8 commits into
mainfrom
hitl-prototype
Draft

feat(apollo-react): add LockableValueField HITL prototype#893
dbacomputer wants to merge 8 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 08, 2026, 12:08:17 PM
apollo-docs 🟢 Ready Preview, Logs Jul 08, 2026, 12:08:17 PM
apollo-landing 🟢 Ready Preview, Logs Jul 08, 2026, 12:08:17 PM
apollo-vertex 🟢 Ready Preview, Logs Jul 08, 2026, 12:08:17 PM

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Dependency License Review

  • 1948 package(s) scanned
  • ✅ No license issues found
  • ⚠️ 2 package(s) excluded (see details below)
License distribution
License Packages
MIT 1718
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% 43.82 MB 57.31 MB ±0
@uipath/apollo-react 34.3% 3.9% (5/129) 7.28 MB 27.68 MB +9.9 KB
@uipath/apollo-wind 40.3% 398.9 KB 2.60 MB +4.0 KB
@uipath/ap-chat 85.8% 43.41 MB 55.85 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;
}
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.
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).
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,
…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.
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
… 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.
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
dbacomputer and others added 2 commits July 15, 2026 10:15
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>
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))}
/>
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