Phone field as custom elements
@telixon/web-components has three parts. <telixon-phone-field>
turns the <input> inside it into a phone field the form submits and validates like a native
field. The user sees a formatted number while the form submits it in E.164. The input stays in the page, where your
labels, styles, and autofill apply to it. <telixon-region-picker>
adds the flag and a searchable list of regions. <telixon-flag> shows the
flag of a region. All three are custom elements built on @telixon/web-sdk. They run
in every current browser and inside the markup of any framework.
Install
Section titled “Install”npm install @telixon/web-componentspnpm add @telixon/web-componentsyarn add @telixon/web-componentsbun add @telixon/web-componentsThe package depends on @telixon/core and @telixon/web-sdk and re-exports both. One import covers
every element, function, and type.
The stylesheet
Section titled “The stylesheet”@telixon/web-components/flags/flags.css paints the flags, on the page and inside the picker. Import
it once, from the page’s stylesheet or from the entry module of a bundled application:
@import '@telixon/web-components/flags/flags.css';Define the elements
Section titled “Define the elements”One call defines the three elements. On a server-rendered page it belongs in the client entry, as
defineTelixonElements describes:
import { defineTelixonElements } from '@telixon/web-components';
defineTelixonElements();A phone field
Section titled “A phone field”A phone field with a region picker inside a form. Type a number, pick a region, and save:
The demo runs the three files below. The markup is a form with the field around the input. The stylesheet lays the field out. The script defines the elements and reads the value. The example is a Vite project, which resolves the package from the module script. A page without a bundler loads the package through an import map, as the frameworks guide shows.
<!doctype html><html lang="en"> <head> <meta charset="utf-8" /> <title>Phone field</title> <link rel="stylesheet" href="/src/static/styles.css" /> <script type="module" src="/src/static/main.ts"></script> </head> <body> <form id="contact"> <label for="phone-input">Phone</label> <telixon-phone-field name="phone" default-region="US" calling-code-in-input="false" auto-placeholder required> <telixon-region-picker></telixon-region-picker> <input id="phone-input" type="tel" autocomplete="tel" /> </telixon-phone-field> <button>Save</button> <p>Value: <output id="value">null</output></p> <p>Submitted: <output id="submitted">none</output></p> </form> </body></html>#contact { display: grid; gap: 0.75rem; max-width: 24rem;}
#contact telixon-phone-field { display: flex; gap: 0.5rem;}
#contact input { flex: 1; padding: 0.5em 0.75em; border: 1px solid #c4c7c5; border-radius: 0.375rem; background: transparent; color: inherit; font: inherit;}
#contact telixon-phone-field:state(user-invalid) input { border-color: #e5484d;}
#contact button { justify-self: start; padding: 0.5em 1em; border: 1px solid #c4c7c5; border-radius: 0.375rem; background: transparent; color: inherit; font: inherit; cursor: pointer;}
#contact p { margin: 0;}import { defineTelixonElements } from '@telixon/web-components';import '@telixon/web-components/flags/flags.css';
defineTelixonElements();
const form = document.querySelector<HTMLFormElement>('#contact');const field = document.querySelector('telixon-phone-field');const value = document.querySelector<HTMLOutputElement>('#value');const submitted = document.querySelector<HTMLOutputElement>('#submitted');if (form === null || field === null || value === null || submitted === null) throw new Error('The page lacks the form or its outputs.');
field.addEventListener('telixon-change', (event) => { value.value = String(event.detail.value);});
form.addEventListener('submit', (event) => { event.preventDefault(); submitted.value = String(new FormData(form).get('phone'));});The same field runs on StackBlitz, on its own, in React 19, or in Vue 3.
At first the picker shows the United States flag with +1 and the field shows the placeholder
201-555-0123. After typing 4155550132 the field shows 415-555-0132 while the value reads
+14155550132. Save submits phone=+14155550132. A partial number keeps the value at null and
blocks the submission with This number is too short. anchored at the input. Clear the field, pick
the United Kingdom, and type 2071838750. The field then shows 20 7183 8750 with the value
+442071838750.
The field loads the engine the first time it connects, which the engine-loading state marks.
Until then the input is a plain input. An application that wants the engine earlier calls
ensureEngineReady, which the package re-exports, before the field appears.
- Phone field in a form explains the attributes, the value, the validation, and the states.
- Country picker for a phone field covers the picker, its templates, and its styles.
- The elements in React, Vue, and Angular puts the same field into each framework’s markup.
- Server rendering and hydration covers the server entry and what a hydrated page sees.
Browser support
Section titled “Browser support”The elements need form-associated custom elements, custom states, and the Popover API. Custom states and the popover set the floor:
| Browser | Version |
|---|---|
| Chrome | 125 |
| Edge | 125 |
| Firefox | 126 |
| Safari | 17.4 |
| iOS Safari | 18.3 |