Repository navigation
feat(apollo-wind): add ResourcePicker - #1244
andreea-ene wants to merge 1 commit into
Conversation
|
Apollo Coded App preview deployments are ready.
|
Dependency License Review
License distribution
Excluded packages
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The implementation has unresolved accessibility structure, labeling, disabled-trigger, and adornment-layout issues.
Review effort: Balanced
Findings: 5
Open (5)
What changed in this PR
Adds a generic grouped resource picker to apollo-wind, including searchable content, collapsible groups, selection, clearing, and footer actions.
Changes:
- Adds
ResourcePickerand standaloneResourcePickerContent. - Adds supporting rows, headers, footer, and empty states.
- Adds Storybook examples, tests, and public exports.
| File | Description |
|---|---|
src/index.ts |
Exports picker API. |
resource-picker/types.ts |
Defines public types and filtering. |
resource-picker/resource-picker.tsx |
Implements picker behavior and UI. |
resource-picker/resource-picker.test.tsx |
Tests interaction and filtering. |
resource-picker/resource-picker.stories.tsx |
Documents usage and variants. |
resource-picker/index.ts |
Provides module exports. |
components/resource-row.tsx |
Renders selectable rows. |
components/resource-picker-footer.tsx |
Renders footer slots. |
components/resource-picker-empty-state.tsx |
Renders empty messages. |
components/resource-picker-empty-state.test.tsx |
Tests empty-state wording. |
components/resource-group-header.tsx |
Renders collapsible headers. |
components/ui/index.ts |
Re-exports the picker module. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Storybook visual diffBaseline is the deployed main Storybook, so changes merged to main after this branch was last updated can also appear here. Logs Updated (PT): Oct 08, 2026, 04:11:34 AM |
📊 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 |
c0e0590 to
847ee0c
Compare
4a1d8a3 to
aa0695e
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Keyboard handling can select unintended resources or dismiss the picker before clearing its search, and long descriptions can hide row labels.
Review effort: Balanced
Findings: 5
Open (5)
Constrain and shrink descriptions to prevent label overflow · New Prevent command keyboard handling from hijacking control activation · New Keep popover open when Escape clears a nonempty search · New Include selected resource in the trigger’s accessible description Avoid remounting content when value changes while open
aa0695e to
22d7212
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
A disabled picker can remain open and allow resource selection.
Review effort: Balanced
Findings: 1
Open (1)
Resolved since last review (5)
Keep popover open when Escape clears a nonempty search Prevent command keyboard handling from hijacking control activation Constrain and shrink descriptions to prevent label overflow Include selected resource in the trigger’s accessible description Avoid remounting content when value changes while open
22d7212 to
a041670
Compare
509ee2c to
e6394fc
Compare
e6394fc to
ebb848f
Compare
87d7b51 to
59d6cc2
Compare
59d6cc2 to
d0ffe2b
Compare
Pull request was converted to draft
d0ffe2b to
c50fc4a
Compare
c50fc4a to
65a222a
Compare
A field and popover for choosing one record from a grouped list. The component 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. The domain lives in the data a consumer passes. 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. Built on Command and Popover, following VariablePicker, with the file layout FolderPicker uses. Ids must be unique across groups; labels need not be, since the same name can appear under two folders. 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, so a selected fill built on them would be indistinguishable from the row under the pointer. Co-Authored-By: Claude Opus 5.5 <[email protected]>

Adds
ResourcePicker, a field and popover for choosing one record from a grouped list.The picker 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. The domain lives in the data a consumer passes, not in the component. Picking a person is the deliberate exception: people carry avatars and a resolved reference of their own, so they belong to a dedicated people picker.
Design decisions
Rows commit on click. One resource is one decision, so there is no Cancel and Select pair, which would add a second click to a choice that is already unambiguous. The footer's two slots hold the ways out of the picker instead, such as a link to create a new record. Passing them as slots keeps product routes out of the design system.
Selection is cyan, hover is neutral. The chosen row takes a tick, the brand tint (
brand-subtle) and an accent label, and keeps them under the cursor. The neutralsurface-overlayfill means cursor position and nothing else.surface-selectedis not used for selection because it resolves to the same value assurface-hoverin every theme, so the two states would be indistinguishable.Ids must be unique across groups, labels need not be. The same name can appear under two folders, so the id carries the path.
Structure
Built on
CommandandPopover, followingVariablePicker, with the file layoutFolderPickeruses:types.tsfor the consumer-facing API and acomponents/folder for the row, group header, footer and empty state. The empty state is its own component with its own test, since an empty picker and a search that matched nothing are different things and must not collapse into one message.The search is Apollo's own
CommandInputrather than a bespoke field.Stories
Components/Core/Resource Picker: Default, WithDescriptions, CollapsedGroup, WithValue, NotClearable, Disabled, EmptyStates, ContentOnly.Screenshots
Selection in Future Light: the tint follows the theme's brand token.
Empty states: an empty picker and a search that matched nothing say different things.
Checks
Run locally:
biome formatbiome checktsc --noEmitvitest run(resource-picker)npm run buildNote:
src/components/forms/form-plugins.test.tsxfails 26 tests onmainas well, unrelated to this branch.🤖 Generated with Claude Code