Skip to main content
phoneField returns a Text field that stores a phone number as typed. Every save checks that the value looks like a phone number, the admin panel shows it as a link that starts a call, and agents and generated types are told what the text means. You don’t name any components or write a validator.
The result is a plain text field, so it works anywhere a field does, including inside groups, arrays, tabs and blocks.

Config options

A phone field holds one number, so hasMany, minRows and maxRows are not accepted. TypeScript rejects them, and setting any of them from JavaScript fails at startup with an error naming the field:

Accepted numbers

Every save checks the value, whether it comes from the admin panel, the REST API, GraphQL, the Local API or an agent. A phone number:
  • contains only digits, spaces, -, ., ( and ), plus an optional + as the first character
  • has from 7 to 15 digits
There are no country rules, and numbers aren’t converted to an international format. These values are rejected: call me, 123 (too few digits), 555-1234 x12 (letters), 44+20 7946 0958 (+ not first) and ++44 20 7946 0958. A rejected value fails with:
An empty value skips the check; set required to reject it.

Admin options

Phone fields support the standard field admin options, plus the Text field’s input options: FrogBot marks the field as a phone number in admin.custom.frogbot.kind. Your own admin.custom keys, and other keys under admin.custom.frogbot, are kept.

Display and editing

A number with exactly 10 digits and no + shows as (XXX) XXX-XXXX. Any other number shows as typed. The shown number is a tel: link built from the digits and any leading +, so clicking it opens the device’s phone app. Links work in the List, on Board cards and in Calendar events. Clicking a link on a card opens only the link, not the card. In the List’s first column, which already links to the document, the number shows as text inside the document link. An empty value shows nothing: no placeholder and no dash. A stored value that isn’t an accepted number, for example one saved before the field became a phone field, shows as plain text and is never turned into a link. If a phone field is the first List column, a row with an empty value has no link to open the document from that column. In the document view, an editable phone field uses the normal text input and shows the number as typed. When the field is read-only, because of admin.readOnly, because it is virtual, or because the user may not update it, the document view shows the formatted number as text with no input.

Stored value

Numbers are stored exactly as typed, including spaces and punctuation. The REST API, GraphQL and the Local API return the stored text, and the generated TypeScript type is the same as a Text field’s, such as phone?: string | null. Filters and sorting use the stored text.

Agents and generated types

A phone field describes itself to agents using FrogBot’s MCP tools and in generated types:
With a string admin.description, or a translated one with an en entry, the phone text is added after it in parentheses. The admin panel still shows only your description.
A function admin.description isn’t copied, so the phone text stands alone. The text is English only. Generated types show the text as a comment above the property, and virtual fields don’t appear in MCP tool inputs. To change the text, add your own jsonSchema entry. It runs after the phone field’s entry, so it can adjust or replace the description:

Formatting in your code

formatPhone and getPhoneHref are the helpers phone fields use. Import them from frogbot/fields, which is safe to use in browser code:
Both take the same argument: formatPhone returns (XXX) XXX-XXXX for an accepted number with exactly 10 digits and no +, any other text as given, and '' for a value that isn’t a string. getPhoneHref returns the tel: link for an accepted number, or undefined for an empty or rejected value. frogbot/fields also exports the FormatPhoneArgs type.

Custom components

The phone cell and read-only display are PhoneCell and PhoneField from @frogbotai/ui/admin. PhoneField renders the normal text input when the field is editable. Your own admin.components.Cell or admin.components.Field replaces them, and other components such as Label, Description, Error, beforeInput and afterInput work as they do on a Text field. A custom Cell can draw the standard link inside its own markup with FieldCell, as shown for Money fields. As with any custom Cell, it appears only in the List view. Board cards and Calendar events keep the standard link.