Contact Selector
What It Is For
Lets a caller select and retain contact identifiers while the picker resolves names, handles search and distinguishes held inactive records. The console has a named ContactSelector, its multiple-selection counterpart and an older ContactPicker form wrapper. The named selector defaults to Quick Search and can open a lazy contact creation drawer. Entities’ current affiliation picker supplies a CRM source directly to the generic RecordPicker. The record captures these variants without inventing a separate organization-style contact control.
Where It Is Used
The reusable ContactSelector supports single and multiple contact fields; Entities currently uses the ContactPicker form variant and CRM-source RecordPicker in Organization 360’s Add Person dialog. Consumers must choose the source contract deliberately. ContactSelector is available to reusable form consumers, while current Entities contact forms use the older ContactPicker for contact-valued fields. Organization 360’s Add Person dialog uses RecordPicker with the CRM contact source. The source and prop differences must remain visible when those screens are wired to this design.
How It Behaves
ContactSelector wraps the shared picker with a labeled field, supplied help and errors. Without an override it uses the signed-in workspace’s Quick Search source. Held identifiers resolve separately from fresh search choices, allowing an inactive or archived held record to remain named. A permitted editable field can offer Add New Contact; successful creation remembers the option locally and selects it immediately. ContactMultiSelector uses the same field contract with chips and a complete replacement identifier list. These wrappers are separate from the older contact-form picker and the CRM-source picker supplied to Organization 360.
Its Contract
The source supplies search, resolution and recent identifiers; the caller supplies the held value and receives selection changes. The default Quick Search source does not fall back to a database when access or the index is unavailable. An explicit source can replace that transport. The older ContactPicker accepts an empty-string value and optional excluded identifier, returns only identifier text and filters locally over source results. Organization-side affiliation addition supplies a CRM contact source directly to the shared RecordPicker. These differences are observed contracts rather than a uniform implementation claim.
States
Empty: A placeholder and contact search trigger appear. Searching: The shared picker debounces reads and presents loading feedback. Held inactive: Resolution keeps the held identifier nameable with inactive wording. Refused or unavailable: The Quick Search source reports explicit access or environment errors; no database fallback is used. Read only: A static summary keeps its tooltip while omitting trigger, clearing and creation. Quick add: A lazy-loaded creation drawer keeps the new option locally until the search source catches up. Form variant: The older wrapper uses a locally matched result set and CRM-backed source rather than the default Quick Search contract.
Accessibility
Field labels, descriptions and errors are linked to the selector trigger; editable required fields have a visible marker and required semantics. The quick-add drawer receives a return-focus target. The form variant names Clear and relies on command/popover controls. Complete keyboard, tooltip and assistive-technology behavior remains unverified. Accessibility verification is an open obligation recorded in the component accessibility finding.
Open Design Questions
The recorded interaction is observed implementation, with proposed design intent. Component criteria need complete executable bindings and browser accessibility review. Screen owners must wire the registered components into their designs; this slice records usage without changing those screen contracts.