use-contact-picker
Let the user share contacts with the Contact Picker API.
| Package | @vizejs/composable/use-contact-picker |
| Own the source | vize lib pull composable:use-contact-picker |
| Runtime exports | useContactPicker |
| Gzip budget | 1536 B |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/composable
Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.
import { useContactPicker } from "@vizejs/composable/use-contact-picker";
Try it
Invite people from contacts
Let the reader pick contacts from the device instead of typing addresses.
What to observe: On Android Chrome, Pick contacts opens the contact list. Elsewhere the example asks the reader to type addresses.
Request only the properties you need; getProperties() lists those the device supports. Every example renders a neutral message until it mounts, so server and client markup match, and then explains what to do when the browser lacks the API.
Compare the initial and interacted states


Copy the example
Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.
<script setup lang="ts">
import { ref } from "vue";
import { useContactPicker } from "@vizejs/composable/use-contact-picker";
import { useMounted } from "@vizejs/composable/use-mounted";
const mounted = useMounted();
const { supported, select } = useContactPicker();
const invited = ref<string[]>([]);
async function invite() {
const result = await select(["name", "email"], { multiple: true });
if (result.status !== "selected") return;
invited.value = result.contacts.map(
(contact) => contact.name?.[0] ?? contact.email?.[0] ?? "Unknown",
);
}
</script>
<template>
<div class="composable-example">
<p>Invite people from the device's contacts instead of typing their addresses.</p>
<button type="button" :disabled="!mounted || !supported" @click="invite">Pick contacts</button>
<output aria-live="polite">{{
!mounted
? "Checking browser support…"
: !supported
? "The Contact Picker is not available; type the addresses instead."
: invited.length
? `Inviting ${invited.join(", ")}`
: "Ready to pick contacts."
}}</output>
</div>
</template>
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
useContactPicker |
capability | experimental | deterministic-fallback | caller-managed | none | web, desktop | window |
— |
API
useContactPicker
Let the user share contacts with the Contact Picker API. select(["name", "email"]) resolves to contacts typed with exactly those keys (missing values become empty arrays). Dismissing the picker resolves with an empty list. The composable holds no resources, so nothing needs cleanup. Server rendering: nothing is requested, supported and pending are false. Inside a component supported turns true only after mounting, so hydration renders this server state first.
function useContactPicker(options: UseContactPickerOptions = {}): ContactPickerControls
const picker = useContactPicker();
const result = await picker.select(["name", "tel"], { multiple: true });
Types
ContactAddressLike
Postal address returned for the address property.
| Member | Type | Description |
|---|---|---|
addressLine? |
readonly string[] |
Street address lines. |
city? |
string |
City. |
region? |
string |
Region or state. |
postalCode? |
string |
Postal code. |
country? |
string |
ISO 3166 country code. |
ContactInfo
Every value the picker can return, keyed by property.
| Member | Type | Description |
|---|---|---|
address |
readonly ContactAddressLike[] |
Postal addresses. |
email |
readonly string[] |
Email addresses. |
icon |
readonly Blob[] |
Avatar images. |
name |
readonly string[] |
Names. |
tel |
readonly string[] |
Phone numbers. |
ContactsManagerLike
Minimal navigator.contacts (ContactsManager).
| Member | Type | Description |
|---|---|---|
getProperties |
() => Promise<readonly string[]> |
Properties this platform supports. |
select |
(properties: ContactProperty[], options?: { multiple?: boolean }) => Promise<readonly Partial<ContactInfo>[]> |
Open the picker (needs user activation). |
UseContactPickerOptions
Options for useContactPicker.
| Member | Type | Description |
|---|---|---|
contacts? |
MaybeRefOrGetter<ContactsManagerLike | null | undefined> |
Contacts manager for alternate runtimes and tests. |
ContactSelectOptions
Options of ContactPickerControls.select.
| Member | Type | Description |
|---|---|---|
multiple? |
boolean |
Allow picking several contacts. |
ContactPickerControls
Reactive state and actions returned by useContactPicker.
| Member | Type | Description |
|---|---|---|
supported |
ComputedRef<boolean> |
Whether the Contact Picker API is available. |
pending |
Readonly<Ref<boolean>> |
Whether the picker is open. |
error |
Readonly<ShallowRef<unknown>> |
Most recent failure, cleared on success. |
getProperties |
() => Promise<ContactProperty[]> |
Properties the platform supports. |
select |
<const Property extends ContactProperty>( properties: readonly Property[], options?: ContactSelectOptions, ) => Promise<ContactPickerResult<Property>> |
Open the contact picker. |