feat(apollo-react): add ModelPicker Material component#879
Conversation
Ports the LLM ModelPicker into the Material component set as ap-model-picker, unchanged in design and behavior: - controlled picker over LLM Gateway Discovery models with search, Category/Provider grouping (BYO always first), lifecycle chips, folder switcher, and a Use custom model footer CTA - per-product customization via props: filter, friendlyNameFor, customTagsFor badges, render slots - platform-aware hooks: BYO management gated on the AiTrustLayerByoLlm entitlement (fail closed) and Orchestrator folder fetching - WAI-ARIA listbox pattern with aria-activedescendant keyboard nav - CSS-variable theming with apollo-core token fallbacks, no ThemeProvider required - memoized rows + virtualization above 120 options (new dependency: @tanstack/react-virtual) Repo adaptations only: useSafeLingui instead of raw Lingui hooks (new PickerTranslator contract), vitest test suite (52 tests), biome formatting, a lingui catalog entry, and React 19 ref typings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
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 new Material (maintenance) ModelPicker component to @uipath/apollo-react, ported from apollo-design-system, including supporting hooks (Discovery fetch, platform entitlements/folders), primitives, and tests; updates i18n and dependencies accordingly.
Changes:
- Introduces
ap-model-picker/(component, primitives, hooks, utils/types, Storybook-ready docs) and exports it from the material components barrel. - Adds Vitest test coverage for the picker primitives, utils, and platform/discovery hooks.
- Adds
@tanstack/react-virtualand updates Lingui config + lockfile to support the new component and virtualization.
Reviewed changes
Copilot reviewed 39 out of 40 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Lockfile updates for @tanstack/react-virtual and dependency graph changes. |
| packages/apollo-react/package.json | Adds @tanstack/react-virtual dependency. |
| packages/apollo-react/lingui.config.ts | Registers a new Lingui catalog for the ModelPicker component. |
| packages/apollo-react/src/material/components/index.ts | Exports the new ap-model-picker module from the material components barrel. |
| packages/apollo-react/src/material/components/ap-model-picker/index.ts | Public barrel exports for ModelPicker, primitives, hooks, types, and utils. |
| packages/apollo-react/src/material/components/ap-model-picker/ModelPicker.tsx | Main controlled picker UI, grouping toggle, footer CTA, and wiring to hooks/primitives. |
| packages/apollo-react/src/material/components/ap-model-picker/ModelPicker.test.tsx | Component-level interaction and keyboard navigation tests. |
| packages/apollo-react/src/material/components/ap-model-picker/ModelTagChip.tsx | Semantic chip renderer for derived/custom model tags. |
| packages/apollo-react/src/material/components/ap-model-picker/README.md | Full usage guide and API reference for consumers. |
| packages/apollo-react/src/material/components/ap-model-picker/i18n.ts | Central message descriptors + translator contract for component i18n. |
| packages/apollo-react/src/material/components/ap-model-picker/types.ts | DTO/types for Discovery models, tags, groups, and request context. |
| packages/apollo-react/src/material/components/ap-model-picker/useDiscoveryModels.ts | Minimal fetch+state hook for LLM Gateway Discovery models. |
| packages/apollo-react/src/material/components/ap-model-picker/useModelPickerState.ts | State controller for open/query/grouping/selection/keyboard navigation. |
| packages/apollo-react/src/material/components/ap-model-picker/usePlatformAccess.ts | Minimal fetch+state hooks for folders and BYO entitlement checks. |
| packages/apollo-react/src/material/components/ap-model-picker/usePlatformAccess.test.tsx | Tests for folder fetch + entitlement check hook behavior. |
| packages/apollo-react/src/material/components/ap-model-picker/utils.ts | Model grouping, filtering, tag derivation, and substitution helpers. |
| packages/apollo-react/src/material/components/ap-model-picker/utils.test.ts | Unit tests for grouping/tag derivation/filtering/substitution helpers. |
| packages/apollo-react/src/material/components/ap-model-picker/primitives/FolderSwitcher.tsx | Folder scope UI (pill + popper menu). |
| packages/apollo-react/src/material/components/ap-model-picker/primitives/FolderSwitcher.test.tsx | Folder switcher interaction tests. |
| packages/apollo-react/src/material/components/ap-model-picker/primitives/GroupHeader.tsx | Group header row (static + collapsible modes). |
| packages/apollo-react/src/material/components/ap-model-picker/primitives/ModelOptionRow.tsx | Single option row rendering + default BYO actions. |
| packages/apollo-react/src/material/components/ap-model-picker/primitives/OptionList.tsx | Grouped and virtualized option list renderers + option DOM id helper. |
| packages/apollo-react/src/material/components/ap-model-picker/primitives/OptionList.test.tsx | Tests for grouped/virtual list rendering and behaviors. |
| packages/apollo-react/src/material/components/ap-model-picker/primitives/PickerPopup.tsx | Popper+Paper dropdown shell used by the picker. |
| packages/apollo-react/src/material/components/ap-model-picker/primitives/PickerSearchInput.tsx | Search input toolbar control with combobox ARIA wiring. |
| packages/apollo-react/src/material/components/ap-model-picker/primitives/PickerTrigger.tsx | Trigger button rendering selected/unknown/placeholder states + inline tags. |
| packages/apollo-react/src/material/components/ap-model-picker/locales/en.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/de.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/es.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/es-MX.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/fr.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/ja.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/ko.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/pt.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/pt-BR.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/ru.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/tr.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/zh-CN.json | New ModelPicker catalog (currently empty values). |
| packages/apollo-react/src/material/components/ap-model-picker/locales/zh-TW.json | New ModelPicker catalog (currently empty values). |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
📊 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 |
…MUI theme - guard the dev-only duplicate-folder warning with `typeof process` so Vite-served hosts (Storybook) don't hit `process is not defined` - bake the mini-chip variant styles into ModelTagChip via sx (CSS variables + Apollo light fallbacks) instead of relying on the Apollo MuiChip theme overrides — chips now honor the picker's no-ThemeProvider contract and render correctly in dark themes Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MenuItem inherited MUI's default (light) text color, which reads dark-on-dark in dark hosts without a ThemeProvider — same class of bug as the chip variants. Paint it from --color-foreground like the rest of the picker. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- fill en.json with English defaults so hosts that load the catalog don't render blank strings (matches ap-chat) - resolve host-filtered selections from the raw catalog so the trigger keeps showing the stored model (documented contract; new test) - deep-camelize Discovery DTO keys; nested PascalCase (ModelDetails, CostDetails, DeprecationDetails, ...) previously stayed raw - reset state and abort in-flight requests when useDiscoveryModels / useUserFolders / useCanManageByo are disabled mid-flight - guard formatDate against Invalid Date leaking into chip labels - useId() for picker DOM ids instead of a module counter - aria-haspopup="menu" on the folder switcher; role="button" on the collapsible group header Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Triage of the Copilot review — all findings addressed in a35aa17 except one dismissed with reasoning:
53/53 vitest, biome clean, 🤖 Generated with Claude Code |
Summary
Ports the LLM ModelPicker (LLM-3802) from
apollo-design-systeminto this repo aspackages/apollo-react/src/material/components/ap-model-picker/. The component is unchanged in design and behavior; only repo-toolchain adaptations were made.What it is
A fully controlled picker for LLM Gateway Discovery models: search, Category ⇆ Provider grouping (Custom Models/BYO always first, per-vendor sections ordered by lifecycle), lifecycle chips (Recommended/Preview/Deprecating/
Routes to …substitutions/Custom/Out-of-region), built-in folder switcher, and a "Use custom model" footer CTA. Per-product customization is all props (filter,friendlyNameFor,customTagsForbadges, render slots) — no forks.Platform-aware: given a
requestContext, the picker gates BYO management on theAiTrustLayerByoLlmentitlement itself (fail-closed) and fetches the user's Orchestrator folders (enableFolders). Recommended/Preview read straight off the Discovery DTO.A11y: WAI-ARIA listbox with
aria-activedescendantkeyboard navigation and live-region announcements. Theming: every color via--color-*CSS variables with@uipath/apollo-coretoken fallbacks — no ThemeProvider required. Performance: memoized rows + auto-virtualization above 120 visible options.Full production guide in the component
README.md.Repo adaptations (behavior-preserving)
useSafeLingui(never throws in providerless hosts); utils thread a structuralPickerTranslatorcontract that both realI18ninstances and the safe fallback satisfy. Catalog entry added tolingui.config.ts; catalogs extracted for all 13 locales.RefObject<T | null>typings inuseModelPickerState.biome checkclean); storybook copy scrubbed of em dashes per repo rule.@tanstack/react-virtual(headless virtualizer for the 500-model case).Note on MUI usage
This component is MUI 5-based, which is why it lands under
material/components(the maintenance namespace) rather thanapollo-wind. It ports an existing, shipped design 1:1; a Tailwind/apollo-wind rewrite would be a separate effort.Testing
vitest: 52/52 passing (src/material/components/ap-model-picker)biome check: cleanpnpm --filter @uipath/apollo-react build: succeeds, including declaration generationKnown issues found while integrating (pre-existing, not addressed here)
pnpm i18n:extractfails on a duplicate message id in ap-chat (autopilot-chat.error.multiple-fileshas two different default translations). I extracted scoped tosrc/material/components/ap-model-pickerto work around it.apollo-core'sbuild:fontsscript uses single-quoted globs, which breaks under Windows cmd.Replaces UiPath/apollo-design-system#5276.
🤖 Generated with Claude Code