--- name: ticket18-picker-delivered-devfrontend description: memory note ticket18-picker-delivered-devfrontend metadata: type: project --- # Lot B / #18 — TicketPicker livré (DevFrontend) Branche `feature/ticket-picker-popup` (base develop d97abb1). `vitest` **vert** : 53 fichiers / 515 tests, dont 8 nouveaux (`TicketPicker.test.tsx`) + 29 `tickets.test.tsx` inchangés (valide la non-régression du listing après extraction). `tsc --noEmit` clean. ## Fichiers - **Créés** : `shared/ui/zIndex.ts`, `features/tickets/TicketFacetsBar.tsx`, `features/tickets/useTicketSearch.ts`, `features/tickets/TicketPicker.tsx`, `features/tickets/TicketPicker.test.tsx`. - **Modifiés** : `shared/index.ts` (export zIndex), `features/tickets/index.ts` (barrel), `features/tickets/TicketsPanel.tsx` (consomme `TicketFacetsBar`). ## Écarts de contrat à trancher (signalés à Main) 1. **Emplacement TicketPicker** : placé sous `features/tickets/`, PAS `shared/ui`, car il dépend du domaine ticket + gateways DI (shared/ui = design system pur). Conforme à tous les autres overlays (SprintManager, MemoryEditor…). Seul `zIndex.ts` (niveau design-system) est dans shared/ui. 2. **`TicketPickerResult.id`/`number`** : `ticket_list`/`TicketSummary` ne portent NI `id` NI `number`. Résolus par un `ticket_read` unique **à la sélection** (`useTicketSearch.resolve`). `number` serait dérivable du ref mais `id` exige la lecture. → contrat `{ref,id,number,title,status,priority}` respecté sans nouveau endpoint. Écart backend candidat : ajouter id/number au summary (dette basse). 3. **`zIndex.ts` provisoire** : lot A (#16) introduit le canonique en parallèle. Valeurs alignées sur l'échelle figée (menuDropdown=40, floatingWindow=50, floatingWindowNested=60, toast=70). **À réconcilier au merge** (garder un seul module). Picker monté à `floatingWindowNested=60`. ## Notes d'impl - G3-bis respecté : `cursor` traité en token opaque (jamais construit/incrémenté ; relayé verbatim via `loadMore`). - `excludeRefs` filtré client-side après réception de page. - `useTicketSearch` léger (pas de groupement sprint, pas de souscription events, debounce 200ms) — ne réutilise pas `useTickets`. - `TicketFacetsBar` = recherche + facettes statut/priorité (labels aria préservés : `search tickets`, `filter status …`, `filter priority …`, `clear filters`). Le select assignee reste dans `TicketsPanel` (hors périmètre picker). - Focus-trap inline (Tab cycling + Escape + restore focus) car aucun util partagé n'existe ; G5 respecté (montage niveau chrome par le consommateur #17/#19). - `selectionMode:"multi"` câblé de façon extensible (footer réservé) mais non actif en V1. QA repasse derrière. Consommateurs #17 (link) et #19 (sprint) importent `TicketPicker` depuis `@/features/tickets`.