feat(ui): standardized collapsible connector-setup widgets in chat + repaint lock (#14412)#14535
feat(ui): standardized collapsible connector-setup widgets in chat + repaint lock (#14412)#14535lalalune wants to merge 1 commit into
Conversation
…14412) Add a first-class connector-setup chat widget plus ONE standardized collapser shell reused across inline widgets, built on the existing registry-based widget system (no new framework): - ChatWidgetShell: shared chevron collapser — starts EXPANDED while a widget is incomplete, AUTO-COLLAPSES to a compact summary once complete/connected, re-expandable via a standardized chevron. Collapsed summary rows carry content-visibility:auto so off-screen collapsed widgets skip layout/paint. - ConnectorSetupWidget ([CONNECTOR:<id>] marker): minimal (required/unset) fields up front, everything else behind an Advanced dropdown. Field tiers derived from the plugin param schema (connector-field-tiers.ts). Secrets never render as plain in-chat inputs — the primary action routes to the connector's real setup / sensitive-request flow via sendAction. memo-wrapped so its internal state never repaints the transcript. - message-connector-parser.ts: parses the marker; the registry auto-wires it into both ChatView and the overlay renderer with no MessageContent edit. Tests: collapser contract (expanded-when-unconfigured, collapsed-on-connect, Advanced toggle, secure-setup routing), parser regions/schema, and a render-count repaint lock proving one widget's state change does not re-render sibling transcript rows. Matrix gate + WIDGET_MATRIX.md updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Closing this as incomplete rather than merging an inert connector setup path. The UI adds a |
|
[fable-review] Verdict: request changes — clean, well-tested substrate, but it must not close #14412 as-is. Verified for real (reproduced locally on the PR head): new+affected suite 29/29 green, parity contracts 27/27 green, exactly matching the PR body. Tests are real components with jsdom assertions, no mocks of units under test; parser edge cases (blank lines, keyless rows, missing name, no marker) covered. No fail-fast violations, no weak types, no scope creep, no blue / doctrine violations, zero Must fix:
Should fix (non-blocking):
Fix #1 (reword) + #2 (one small test) and this is mergeable as the substrate PR for the connector workstream. |
|
[fix-pass] Both must-fixes applied on Must-fix 1 — Must-fix 2 — transition tests, not just mount states. New
These are real behavioral assertions on Verification (real output): The PR is currently CLOSED; the branch carries the fixes and is ready if reopened as the substrate PR for the connector workstream. |
|
[fable-reverify] Verdict: approve (fix-pass verified) — both must-fixes are genuinely resolved; branch is merge-ready if the owner chooses to reopen. Must-fix 1 (scope honesty) — CONFIRMED. PR body now reads Must-fix 2 (shell transition tests) — CONFIRMED, independently reproduced. One state repair made during re-verify: the head branch Remaining (unchanged, by design — not blockers for this substrate PR):
|
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
What & why
The MVP direction is "settings live in chat," but there was no first-class connector-setup widget and no standardized collapsible widget shell. Chat widgets ate unbounded vertical space in the transcript. This adds, on the existing registry-based widget system (no new framework):
ChatWidgetShell— one shared chevron collapser every inline widget can wrap. Contract: starts expanded while incomplete, auto-collapses to a compact summary once complete/connected, re-expandable via a standardized chevron. A manual toggle after that wins untilcompletetransitions again. Collapsed summary rows carrycontent-visibility:autoso an off-screen collapsed widget skips layout/paint.connector-field-tiers.tsderives minimal (required/unset) vs advanced (set optionals) from the plugin/connector param schema (PluginParam[], the shapebuildPluginConfigUiSpecconsumes). Advanced fields sit behind aCollapsibledropdown.[CONNECTOR:<id> name="…"]…[/CONNECTOR]marker registered viaregisterInlineWidget. The registry auto-wires it into both ChatView (MessageContent) and the overlay (InlineWidgetText) with no edit to either. Secrets never render as plain in-chat inputs — each field is a labelled row and the primary action routes to the connector's real setup / sensitive-request flow viasendAction("connector:setup:<id>"). Collapses to a "Connected" summary once configured.memo-wrapped so its internal state (expand/collapse, Advanced toggle) updates in isolation and does not repaint the transcript. A new render-count perf lock proves this for a transcript of N connector widgets.WIDGET_MATRIX.mdupdated with the connector row + shell contract (coordinates with #14327).Coordination / rebase notes
inline-builtins.tsx.message-form-parser.ts,form-request.tsx, or the FORM schema — it adds a separate[CONNECTOR]marker + parser, so rebase against fix(ui): harden FORM state records for constructor fields (#14489) #14486 is trivial (no overlapping files).origin/develop.Verification (real output)
New + affected UI tests — all green (29/29)
connector-setup-widget.test.tsx— starts-expanded-when-unconfigured, starts-collapsed-on-connect (assertscontent-visibility:autoon the summary), re-expand via chevron, Advanced dropdown hidden until opened, secure-setup routing (asserts zeroinput[type=password]in-transcript).message-connector-parser.test.ts— region extraction,nameattribute,KEY|required|isSet|labelbody schema, blank/keyless-line handling.connector-widget.render-count.test.tsx— a transcript of 6 connector widgets; toggling ONE widget's Advanced dropdown re-renders no sibling row (per-rowrenderMessageContentcounter stays flat).inline-registry.test.tsx/inline-registry.matrix.test.tsx— exact-set + WIDGET_MATRIX gate extended with theconnectorbuiltin (10 matrix assertions pass).chat-transcript.render-count/.memoization) still green.Overlay/ChatView parity contracts still green (27/27)
Typecheck + lint scoped to touched files — clean
Note:
packages/uifull typecheck reports pre-existing errors in files this PR does not touch (button.tsx,spinner.tsx,calendar.tsx, settings/*), caused by the known worktree@types/reactduplication skew. Zero of those are in this PR's files.Evidence
[CONNECTOR:…]reply, not runnable headlessly in this worktree. Owner runs:bun run --cwd packages/app audit:appand reviewsaesthetic-audit-output/.[chat-widgets]workstream (#14364/#14461).Part of #14412
🤖 Generated with Claude Code