Product picker
The one way to attach catalog products (deal, dialer, meeting, order — D2), with free-text items that do not create a product (P7). App component ProductPicker (apps/web/src/components/ProductPicker.tsx): the same composition as Entity picker over the canonical Record select — products as <EntityRef type="product" removable> tokens, "Přidat" opens RecordSelect in adding mode.
Status: beta (AD 3 Oct 2026). The former duplicate shell (AddRefMenu) is gone (point C, 1 Oct 2026): panel, rows, states, keyboard and focus are Record select's. Canon after the DoD — stories, baseline, audit.
When to use
- Products attached to a record: deal items, dialer, meeting, order lines.
- A line that must not create a catalog product — free text (
allowFreeText, default on). - One product (
multi={false}): a pick replaces the previous token and closes the panel.
When not to use
- People, companies, deals — Entity picker.
- A rail row — Rail picker.
- Quantities and prices — the line-item editor; this only picks the product.
Anatomy
- Optional
.acrm-field>.acrm-field-label(withlabel), then.eref-field: tokens viaEntityRefPreview(catalog product opens/produkty/:id; free text is a plain token) +.eref-add>button.add-ref. - Panel:
RecordSelectwithanchorRef,keepOpen={multi},filter={false},onQueryChange(debounce 180 ms),minWidth={340}. - Empty query = top products by usage (
GET /products/top, P6); from 2 characters fulltext (GET /products/search). - Row: product mark (
entityType: 'product'), name,sub= category · status for draft / in-review products (admin + manager, P8). Already-added products are filtered out. - Free text: Record select footer row "Použít text „…“" (
onCreate, iconwriting), offered only when the query matches no found or already-added product by name. - States: loading only without data in hand; error "Produkty se nepodařilo načíst." with retry; empty catalog "Katalog zatím nemá žádné produkty".
Best practices
Do
- Keep top products as the empty-query state — the fast path for repeat picks.
- Use
multi={false}for a one-to-one relation instead of trimming tokens in the caller.
Don't
- A separate product dropdown per screen — D2 made this the single picker.
- Prices, stock or descriptions in rows — name, category, status only.
- Offer free text when an existing product has the same name (duplicate line without catalog link).
Content
- "Přidat" (
addLabel); search placeholder "Hledat produkt…" (placeholder). - Free-text row "Použít text „…“".
- Status in
subfromPRODUCT_STATUS("koncept", "ke schválení").
Related
entity-picker— the same composition for records.record-select— the panel (adding mode, server search, footer create row).entity-ref(variant removable) — the tokens.- Stories: Components / Record reference field — Default · States · Composition (
DS.RecordRefField, acrm !4502).
Source: docs/select/product-picker.usage.md · GitLab