feat(apollo-react): add LockableValueField HITL prototype#893
feat(apollo-react): add LockableValueField HITL prototype#893dbacomputer wants to merge 3 commits into
Conversation
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.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dependency License Review
License distribution
Excluded packages
|
There was a problem hiding this comment.
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’sInputGroup. - Adds a new “Lockable Field” Storybook story that renders a Quick Approve-style panel, including a draggable/reorderable list of lockable fields.
- Exports
LockableValueFieldand 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. |
| <InputGroupInput | ||
| id={id} | ||
| readOnly={locked} | ||
| value={value} | ||
| onChange={(e) => onValueChange?.(e.target.value)} | ||
| placeholder={FIELD_PLACEHOLDER[mode]} | ||
| className={mode === 'expression' ? 'font-mono' : undefined} | ||
| /> |
| export function LockableValueField({ | ||
| value = '', | ||
| onValueChange, | ||
| locked = true, | ||
| onLockedChange, |
| > | ||
| <Plus size={12} /> | ||
| Add case | ||
| </button> |
📊 Coverage + size by packagePer-package coverage and bundle size on this PR. New-line coverage = of the source lines this PR adds or changes, the % hit by tests.
"Coverage" is each package's own |
…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.
| /* 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 |
| {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> |
| {value ? ( | ||
| new Date(value).toLocaleDateString(undefined, { | ||
| year: 'numeric', | ||
| month: 'long', | ||
| day: 'numeric', | ||
| }) | ||
| ) : ( | ||
| <span className="text-muted-foreground">Pick a date</span> | ||
| )} |
| id={id} | ||
| checked={value === 'true'} | ||
| onCheckedChange={(checked) => onValueChange?.(String(checked))} | ||
| disabled={locked} | ||
| /> |
| 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.'); | ||
| } | ||
| }; |
| 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({ |
| id?: string; | ||
| className?: string; | ||
| } |
Summary
Prototype for a Quick Approve panel demonstrating quick-form editing inside the Property Panel experience — built on top of the
InputGroupprimitive from #890.LockableValueField— a string field with:Notes for reviewers
user-round-arrow-lefticon isn't in the installedlucide-react@0.577.0(added in1.20.0); usedUserRoundCheckinstead rather than bumping a shared dependency across a major version for one icon. Flagging in case a real icon upgrade is wanted later.@dnd-kitdependency already used byStageNode, following the same sensor setup convention.Test plan
pnpm exec tsc --noEmit— cleanpnpm biome check— cleanpnpm vitest run(NodePropertyPanel) — 9/9 existing tests pass, no regressions🤖 Generated with Claude Code