CS-10380: Fetch type picker options from _federated-types endpoint#4171
CS-10380: Fetch type picker options from _federated-types endpoint#4171
Conversation
Instead of deriving type picker options from search results and recent cards, fetch all available types from the _federated-types endpoint so the picker is populated with all types across selected realms regardless of search state. Types with the same display_name but different code_refs appear as one picker option, but all associated code_refs are used when filtering search results. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Preview deployments |
Host Test Results 1 files ± 0 1 suites ±0 3h 40m 7s ⏱️ + 1h 25m 43s Results for commit 8c39a7d. ± Comparison against base commit 20a185a. This pull request removes 3 and adds 7 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
- Add built-in infinite scroll and loading indicators to the boxel-ui Picker component (isLoading, isLoadingMore, hasMore, onLoadMore args) - Full overlay loading covers options area during initial/search fetch, bottom spinner shows during load-more pagination - Simplify TypePicker by removing custom afterOptionsComponent, infiniteScroll modifier, and pickerExtra - now passes args directly - Split _typeSummariesLoading into _isLoadingTypes and _isLoadingMoreTypes for distinct loading states - Update tests for pagination (waitFor specific types) and type count Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
boxel/packages/host/app/components/card-search/panel.gts
Lines 327 to 331 in b645670
When the picker is using server-side search, this branch drops any previously selected type whose label is not present in the currently returned option set, so selecting Pet and then searching for Person clears Pet as soon as the filtered response arrives. That makes multi-select across different search terms impossible and unexpectedly reverts users back toward Any Type without an explicit deselect action.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!codeRefsByDisplayName.has(name)) { | ||
| codeRefsByDisplayName.set(name, []); | ||
| } | ||
| codeRefsByDisplayName.get(name)!.push(codeRef); |
There was a problem hiding this comment.
Merge type code refs beyond the current paged slice
The typeCodeRefs map is built only from _typeSummariesData, which is fetched in 25-item pages, so a selected display name can end up mapped to only the code refs from already-loaded pages. In multi-realm or large-type sets, cards whose same display name appears on later pages get filtered out incorrectly because their code refs were never added to this map.
Useful? React with 👍 / 👎.
|
I don’t know what best practice is for this kind of thing, I assume pagination is a reason but I find it confusing that I scroll to the bottom and see “WelcomeToBoxel” as the last item, then loading, then it’s still the last item, what were the new ones? And then after enough of that, “YouTube Thumbnail Composer” becomes the last item. Is it possible to trigger the load of them all instead of needing to scroll to the bottom? There may be constraints here I’m unaware of, it just seems confusing. |
There was a problem hiding this comment.
Pull request overview
This PR updates the card search “Type” filter to fetch options from the realm server’s /_federated-types endpoint (with server-side search + pagination) instead of deriving types from search results/recent cards, and moves the loading + infinite-scroll UX into the shared boxel-ui Picker.
Changes:
- Add
isLoading/isLoadingMore/hasMore/onLoadMore+ server-search support toboxel-uiPicker, including built-in loading UI and scroll-based pagination triggers. - Implement type summaries fetching in host card-search panel via
realmServer.fetchCardTypeSummaries()with search + pagination, and filter search results by resolved type code refs. - Update operator-mode UI tests to reflect realm-derived type options and the new loading/pagination behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/boxel-ui/addon/src/components/picker/index.gts | Adds loading + infinite-scroll behavior and server-search toggles to the shared Picker. |
| packages/host/app/components/type-picker/index.gts | Wires TypePicker to Picker’s new server-search/loading/pagination args. |
| packages/host/app/components/card-search/panel.gts | Fetches and dedupes federated type summaries; manages loading states and pagination. |
| packages/host/app/components/card-search/search-content.gts | Changes type filtering to use code refs (via internalKeyFor) rather than display-name strings. |
| packages/host/app/components/card-search/search-bar.gts | Threads new type loading/search/pagination args into TypePicker. |
| packages/host/app/services/realm-server.ts | Adds fetchCardTypeSummaries() that queries /_federated-types. |
| packages/host/tests/helpers/realm-server-mock/routes.ts | Adds mock /_federated-types endpoint for host tests. |
| packages/host/tests/integration/components/operator-mode-ui-test.gts | Updates expectations and waits for realm-derived type options. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When the server paginates by code_ref but the client deduplicates by displayName, a page of 25 code_refs can yield 0 new visible picker options. This adds a while loop that automatically fetches the next page until new visible items appear or the last page is reached. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@backspace Thanks for the feedback! The confusing behavior you saw was caused by two issues:
In the latest commit I've fixed both:
Why we still need pagination: The type list can be very large (hundreds of types across multiple realms). Loading them all upfront would mean a slower initial render and a large payload on first open of the type picker. Incremental pagination (25 at a time) keeps the picker responsive. With the server-side sort fix, the UX should now feel natural — scroll down, see 25 more types in alphabetical order. *) You cannot try this in the preview because we need to deploy the server-side sorting. Screen.Recording.2026-03-30.at.12.26.13.mov |
new visible options due to display-name deduplication), the first scroll-to-bottom now fetches all remaining types at once. Initial load still fetches only the first page (25 items) to keep it fast. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Remove client-side type deduplication, add code_ref tooltip, fix pagination - Stop deduplicating type picker entries by displayName. Each code_ref is now its own picker option, so pagination works naturally (25 items per page = 25 visible items, no more fetch-all workaround). - Add tooltip (using BoxelTooltip) on type picker options showing the code_ref so users can distinguish same-named types from different modules. - Fix pagination to be truly incremental: loadMoreTypes now fetches the next page and appends results instead of fetching all remaining at once. - Sort types by displayName server-side before paginating so page boundaries are stable and load-more appends in correct alphabetical order. - Remove typeCodeRefs plumbing (no longer needed since picker option IDs are now the code_refs directly). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
db01b90 to
590965b
Compare
|
Looks like types are not loading as expected from AI Assistant "+" > "Attach a Card" context |
|
Height of picker is changing when loading spinner appears. It should be stable. |
|
Bug:
Expected behavior: Show the latest paginated load of all types |
- Replace PickerAfterOptions with minimal PickerLoadingOverlay (initial load only) - Move infinite scroll sentinel + loading spinner inline in the Picker template - Fix types not loading from AI Assistant "Attach a Card" by skipping client-side filtering when baseFilter is a root type (CardDef/FieldDef) - Auto-select constrained types when baseFilter specifies a specific type (e.g., Author) instead of defaulting to "Any Type" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Hide root types (CardDef, FieldDef, BaseDef) from type picker options - Disable "Any Type" when baseFilter constrains to a specific type - Add disabled state to PickerOption with visual styling (opacity + no interaction) - Skip client-side search result filtering for non-root baseFilter types to avoid excluding subtypes (e.g. BoomPet when filtering by Pet) - Keep client-side filtering for root type baseFilter (CardDef) so type selection in "Attach a Card" modal still works - Fix search clearing bug by directly performing fetch task - Add microtask yield to avoid autotracking assertion on empty search - Add tests for type picker with baseFilter, auto-select, disabled Any Type, search clearing, and attach card type selection flow - Remove pauseTest() debugging leftover Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…unt, and add tests Recursively fetch additional pages when clearing the type search if selected types aren't in the first page of results. Use the API's meta.page.total for the "Any Type (N)" count instead of the client-side options length. Added tests for both behaviors with a reduced PAGE_SIZE. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes in latest commits1. Simplified loading spinner (picker component)Replaced the 2. Fixed types not loading from AI Assistant "Attach a Card"Root cause: When "Attach a Card" is clicked, the Fix: Skip client-side type filtering when the only refs in the baseFilter are root types ( 3. Auto-select type when baseFilter constrains to a specific typeWhen the baseFilter constrains to a specific type (e.g., Author for a 4. Root types hidden from type pickerCardDef, FieldDef, and BaseDef are now filtered out from type picker options — users should never see these internal meta types as selectable options. 5. "Any Type" disabled when baseFilter constrains to specific typeWhen the card catalog is opened from a For root type baseFilters (CardDef — e.g., "Attach a Card"), "Any Type" remains enabled so users can still select specific types to filter results. 6. Search result filtering moved to server-side queryType filtering of search results is now done server-side via 7. Search clearing bug fix — selected types preserved across pagesDirectly performing the fetch task in 8. "Any Type (N)" total count fixThe total count shown in "Any Type (N)" now uses 9. Tests added
|
ece938e to
8c39a7d
Compare






Screen.Recording.2026-03-16.at.13.11.49.mov
Summary
_federated-typesendpoint instead of deriving them from search resultsTypePickerinto the boxel-uiPickercomponentChanges
packages/boxel-ui/addon/src/components/picker/index.gtsisLoading,isLoadingMore,hasMore,onLoadMoreargs to PickerPickerAfterOptionscomponent with full overlay loading for initial/search and bottom spinner for load-morerequestAnimationFramedropdownClassadds--loadingmodifier for z-index layering (search input stays above overlay)packages/host/app/components/type-picker/index.gts@isLoading,@isLoadingMore,@hasMore,@onLoadMoredirectly to Pickerpackages/host/app/components/card-search/panel.gtsfetchTypeSummariesrestartable task callingrealmServer.fetchCardTypeSummaries()_isLoadingTypes(initial/search) and_isLoadingMoreTypes(pagination)_typeCodeRefsmap tracks multiple code refs per display name for accurate search filteringpackages/host/app/components/card-search/search-bar.gtsisLoadingTypesarg, passed through to TypePickerTests
waitForfor paginated type options in operator-mode UI testsTest plan
packages/hostintegration tests for operator-mode UI🤖 Generated with Claude Code