Skip to content

feat(apollo-wind): add ConnectionPicker - #1246

Open
andreea-ene wants to merge 1 commit into
mainfrom
feat/connection-picker
Open

andreea-ene wants to merge 1 commit into
mainfrom
feat/connection-picker

Conversation

@andreea-ene

@andreea-ene andreea-ene commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Replaces #1212, which was opened from a fork so the required checks couldn't run.

Targets main. This PR is a single commit that contains ResourcePicker as well as ConnectionPicker, so it can merge on its own. #1244 carries the same ResourcePicker without the additions below.

Adds ConnectionPicker, a field and popover for choosing the connection an activity runs with.

Why a separate component

ConnectionPicker is built on ResourcePicker rather than being a variant of it. The search, folders, keyboard model, empty states and footer are shared. What a connection adds is its own domain: a health, repair and edit actions, a message under the field and a schema refresh. As a variant prop, most of that would be props that only mean something for connections.

ResourcePicker additions

Generic extension points, useful to any picker built on it:

  • subtitle: a second line under a row's label
  • keywords: extra search terms for detail a row does not print
  • itemActions(item) => ResourceItemAction[]: a row's actions (id, label, optional text, icon, tone, onSelect). The row shows them as pointer shortcuts, revealed under the cursor; clicking one does not commit the row. They are hidden from assistive technology and never focusable, since a listbox option is atomic. Shift+Enter on the row under the cursor opens them as a real menu beside the row (actionsMenuLabel, default "Actions for …"): ArrowUp/ArrowDown move, Enter runs an action, Escape returns to the search, and Tab/Shift+Tab move on from the row
  • onTabOut: called when Tab leaves a row's actions menu with nothing after the list inside an embedded ResourcePickerContent; ResourcePicker uses it to close its popover and move on from the field
  • status: an error or warning state on the field, with aria-invalid for errors, plus aria-describedby for the consumer's message

The list is a single listbox, the one the search's aria-controls names, holding only role="group" elements and options. Group headings are labels, not buttons: clicking an open heading collapses it, ArrowLeft on a row collapses its group, and a collapsed group stays as one option ("Shared, collapsed", set by collapsedGroupLabel) that Enter, ArrowRight or a click reopens. The arrows only fold groups while the search is empty. Other ResourcePicker changes made in review: noMatchText(query) for the no-results message; a controlled query without onQueryChange makes the search readOnly and lets Escape dismiss; the clear control shows for any set value, even one not found in groups.

The field's classes are exported as resourcePickerTriggerClassName so pickers built on it match. The trailing padding now also applies in the Future themes, where future:px-4 used to override it and let the value run under the clear control. The row icon slot grows from 14px to 16px so image logos keep their detail.

ConnectionPicker

  • Health. A connection is connected, warning (usable but degraded, such as missing scopes) or broken. Rows show it as a second line. The field shows it as its leading dot, its border and, when unhealthy, a message underneath with the first sentence of statusReason (the whole reason on hover).
  • Order. Broken connections sort to the end of their folder. They stay choosable and repairable, but the list does not open on dead ends.
  • Naming. Rows and the field show the account, falling back to the connection name: a node bound to the wrong account is the mistake worth catching. The name stays searchable.
  • Logos. logo takes an image URL for the connector, such as the third-party SVGs in @uipath/apollo-ui-icons. icon remains for a glyph.
  • Actions. onFix adds Fix to broken rows, and to the message under the field once a broken or warning connection is chosen, so it must handle both. onEdit adds Edit to every row. onAddConnection adds a footer link, and with no connections and no value the field itself starts a new one (a value with no matching connection stays visible and clearable). onRefreshSchema adds a field menu while a connection is chosen, showing progress until its promise settles.
  • Validation. error puts the field in its error state with the message underneath, taking the place of the health message.
  • Localisation. strings (ConnectionPickerStrings, defaults in DEFAULT_CONNECTION_PICKER_STRINGS) covers every string without a prop of its own: health labels, fallback reasons, Fix/Edit, the footer link, the list name, the field menu, and ResourcePicker's noMatchText, collapsedGroupLabel and actionsMenuLabel.

Row actions are pointer shortcuts in the row and a Shift+Enter menu from the keyboard. Fix is also offered under the field once a broken or warning connection is chosen.

Screenshots

Every health, with row actions under the cursor A chosen connection, with the schema menu
Connection picker open on Outlook connections in two folders, rows showing Connected, Missing scopes and Broken, with Fix and Edit on the broken row under the pointer Connection picker with jane.doe chosen on a cyan tint, a green dot in the field and a more menu at its trailing edge
Another connector Future Light
Connection picker listing Slack connections with Slack logos The Outlook list in the Future Light theme

Field states: broken, missing scopes, required and no connections.

Field with a red dot and border, and Token expired with a Fix link underneath Field with an amber dot and border, and Missing scopes: Mail.Send with a Fix link underneath
Empty field with a red border and Connection is required underneath Field reading Add connection with a plus icon

Stories

Components/Core/Connection Picker: Default, WithValue, Broken, MissingScopes, Slack, Required, NoConnections, SelectOnly, Disabled.

Checks

Run locally:

Check Result
biome format pass, 405 files
biome check (changed files) pass
tsc --noEmit pass
vitest run (connection-picker, resource-picker) 134 passed
npm run build pass

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Dependency License Review

  • ✅ 1947 package(s) scanned
  • ✅ No license issues found
  • ⚠️ 2 package(s) excluded (see details below)
License distribution
License Packages
MIT 1713
ISC 91
Apache-2.0 56
BSD-3-Clause 28
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.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

@andreea-ene andreea-ene added the size:XXL 1,000+ changed lines. label Sep 30, 2026
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from 895f2ce to 72a9cd2 Compare October 1, 2026 12:03
@andreea-ene
andreea-ene force-pushed the feat/resource-picker branch from c0e0590 to 847ee0c Compare October 1, 2026 12:43
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from 72a9cd2 to 23c4179 Compare October 1, 2026 12:45
@andreea-ene
andreea-ene requested a balanced review from Copilot October 5, 2026 12:01
@andreea-ene
andreea-ene marked this pull request as draft October 5, 2026 12:01
@andreea-ene
andreea-ene force-pushed the feat/resource-picker branch from 4a1d8a3 to aa0695e Compare October 5, 2026 12:03

This comment was marked as outdated.

@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from 5b21e54 to a581ace Compare October 5, 2026 12:26
@andreea-ene
andreea-ene marked this pull request as ready for review October 5, 2026 12:40

@dbacomputer dbacomputer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the changes against feat/resource-picker, including the earlier review fixes. The 63 existing ConnectionPicker/ResourcePicker tests pass locally. Two additional interaction regressions reproduced in targeted tests are noted inline; I recommend fixing these before approval.

@andreea-ene
andreea-ene marked this pull request as draft October 6, 2026 09:56
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from a581ace to b9aea5c Compare October 6, 2026 09:58
@andreea-ene
andreea-ene force-pushed the feat/resource-picker branch from aa0695e to 22d7212 Compare October 6, 2026 09:59
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from b9aea5c to 5b75539 Compare October 6, 2026 10:45
@andreea-ene
andreea-ene force-pushed the feat/resource-picker branch from 22d7212 to a041670 Compare October 6, 2026 10:47
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from 5b75539 to 8edf3af Compare October 6, 2026 10:48
@andreea-ene
andreea-ene force-pushed the feat/resource-picker branch from a041670 to d822ff7 Compare October 6, 2026 10:53
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from 8edf3af to f123a1d Compare October 6, 2026 10:55
@andreea-ene
andreea-ene force-pushed the feat/resource-picker branch from d822ff7 to ce4e3af Compare October 6, 2026 10:57
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from f123a1d to ae9db56 Compare October 6, 2026 11:30
@andreea-ene
andreea-ene marked this pull request as ready for review October 6, 2026 12:33
@andreea-ene
andreea-ene force-pushed the feat/resource-picker branch from ce4e3af to 97bfb4e Compare October 6, 2026 15:48
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from ae9db56 to 3ca22c4 Compare October 6, 2026 15:49
@andreea-ene
andreea-ene force-pushed the feat/resource-picker branch from 38b54c7 to 6557097 Compare October 6, 2026 15:59

This comment was marked as outdated.

Copilot AI balanced review requested due to automatic review settings October 9, 2026 10:43
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from 868aa0c to be62bea Compare October 9, 2026 10:43
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from be62bea to 3694d67 Compare October 9, 2026 10:45

This comment was marked as outdated.

Copilot AI balanced review requested due to automatic review settings October 9, 2026 10:47

This comment was marked as outdated.

Copilot AI balanced review requested due to automatic review settings October 12, 2026 11:26
@andreea-ene
andreea-ene force-pushed the feat/connection-picker branch from 3694d67 to 2936fde Compare October 12, 2026 11:26

This comment was marked as outdated.

@uipathepixa-dogfood

uipathepixa-dogfood Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Epixa-Dogfood Review

Review unavailable: required_pr_review_evidence_unavailable

Not reviewed: packages/apollo-wind/docs/LOCALIZATION_GUIDE.md, packages/apollo-wind/src/components/ui/connection-picker/components/connection-actions-menu.tsx, packages/apollo-wind/src/components/ui/connection-picker/components/connection-status.tsx +19 more

What this PR does

The pull request author describes the intended change as follows: feat(apollo-wind): add ConnectionPicker

This review did not reuse a local review of this change. Set up Epixa local review.

Full review: 34f53a1 0 findings

This comment was marked as outdated.

This comment was marked as outdated.

This comment was marked as outdated.

This comment was marked as outdated.

This comment was marked as outdated.

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.

🟡 Changes recommended

Two focus and value-announcement accessibility gaps remain in the new picker flows.

2 open findings
1 resolved since last review

🧠 Review effort: Balanced

Comment thread packages/apollo-wind/src/components/ui/resource-picker/resource-picker.tsx Outdated

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.

🟡 Changes recommended

Focus loss, incomplete localization, and inconsistent empty-error handling remain unresolved.

2 open findings
2 resolved since last review

🧠 Review effort: Balanced

Comment thread packages/apollo-wind/src/components/ui/connection-picker/connection-picker.tsx Outdated
Comment thread packages/apollo-wind/src/components/ui/connection-picker/types.ts

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.

🟡 Changes recommended

Selection semantics, focus traversal, and one localization path remain incorrect.

4 open findings

🧠 Review effort: Balanced

Comment thread packages/apollo-wind/src/components/ui/resource-picker/focus.ts Outdated

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.

🟡 Changes recommended

Pointer row actions can unexpectedly remove focus from the picker search and interrupt keyboard navigation.

1 open finding
4 resolved since last review

🧠 Review effort: Balanced

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.

🔵 Needs a closer look

The large custom keyboard, focus, and accessibility surface warrants final human validation despite comprehensive tests.

2 open findings
1 resolved since last review

🧠 Review effort: Balanced

Comment thread packages/apollo-wind/docs/LOCALIZATION_GUIDE.md Outdated

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.

🔵 Needs a closer look

The custom keyboard, focus, portal, and accessibility interactions warrant final browser-based human validation despite strong automated coverage.

0 open findings

2 resolved since last review

🧠 Review effort: Balanced

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.

🟡 Changes recommended

Pointer-driven group toggles blur the search control and break subsequent keyboard navigation.

1 open finding

🧠 Review effort: Balanced

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.

🟡 Changes recommended

Group pointer interactions can drop search focus, and actions-menu Tab-out can restore focus backward.

3 open findings

🧠 Review effort: Balanced

Comment on lines +772 to +777
onCloseAutoFocus={(event) => {
if (!tabbingOut.current) return;
tabbingOut.current = false;
const field = fieldRef.current;
if (field && focusBeside(field, false)) event.preventDefault();
}}

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.

🟡 Changes recommended

Row-action menus can retain stale resources, and forward Tab can incorrectly restore focus to the picker trigger.

2 open findings
2 resolved since last review

🧠 Review effort: Balanced

Comment on lines +195 to +200
/** The row whose actions menu is open, opened from the keyboard. */
const [actionsMenu, setActionsMenu] = useState<{
item: ResourceItem;
actions: ResourceItemAction[];
anchor: HTMLElement;
} | null>(null);

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.

🟡 Changes recommended

Focus-management defects and selection during disabled close transitions remain unresolved.

5 open findings

🧠 Review effort: Balanced

// else is left where it is.
useLayoutEffect(() => {
const button = addButtonRef.current;
if (!addOnly || !focusWithin.current || !button) return;
data-slot="resource-row-actions-menu"
align="end"
sideOffset={2}
className="w-auto min-w-36 p-1"
Comment on lines +800 to +803
onSelect={(item: ResourceItem) => {
onSelect(item);
setOpen(false);
}}
ResourcePicker is a field and popover for choosing one record from a
grouped list. It is generic over what it lists: a group is a heading
with rows under it, and a row is an id, a label and an optional icon,
so the same control serves Data Fabric entities, queues, storage
buckets or anything else with that shape.

Rows commit on click, so there is no Cancel and Select pair: one
resource is one decision. The footer's two slots hold the ways out of
the picker instead, which keeps product routes out of the component.
Rows can also carry a subtitle, with a text form joined into their
accessible name, search keywords they do not print, and trailing
actions revealed under the cursor. The field has an error/warning
status, and its trigger classes are exported so pickers built on it
read as a pair.

Built on Command and Popover, following VariablePicker, with the file
layout FolderPicker uses. Selection is carried by a tick and a brand
tint, kept apart from the neutral fill that marks the cursor:
`surface-selected` and `surface-hover` resolve to the same value in
every theme.

ConnectionPicker builds on it to choose the connection an activity runs
with, adding what only a connection has:

- health on every row and on the field, as its leading dot, its border
  and a message underneath. A warning is named by its own reason's
  headline, falling back to "Needs attention"
- broken connections sorted to the end of their folder
- Fix on broken rows and under the field, Edit on every row and in the
  field menu, so both are reachable from the keyboard
- an Add connection footer link, and with no connections at all the
  field itself starts one
- a field menu to refresh the chosen connection's schema, showing
  progress while the returned promise is pending
- an `error` message for validation, and the field's id and ARIA
  labelling forwarded to either trigger

Rows and the field show the account, falling back to the connection
name, since a node bound to the wrong account is the mistake worth
catching. The name stays searchable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

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.

This branch was successfully deployed

4 active deployments
preview/apollo-docs — 096f2774 Deployed Oct 19, 2026 by github-actions[bot]
preview/apollo-design — 096f2774 Deployed Oct 19, 2026 by github-actions[bot]
preview/apollo-landing — 096f2774 Deployed Oct 19, 2026 by github-actions[bot]
preview/apollo-vertex — 096f2774 Deployed Oct 19, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg:apollo-wind size:XXL 1,000+ changed lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants