Amplify UI

PhoneNumberField

PhoneNumberField allows users to input phone numbers.

Demo

Usage

Import the PhoneNumberField component and provide a label for accessibility/usability as well as a defaultDialCode which will auto-populate the dial code select field.

import { PhoneNumberField } from '@aws-amplify/ui-react';

export const DefaultPhoneNumberFieldExample = () => (
  <PhoneNumberField label="Phone Number" defaultDialCode="+1" />
);

Dial Code Select Properties

All countryCode fields are being deprecated in favor of the new dialCode fields. If you still have instances of defaultCountryCode, countryCodeList, countryCodeName, countryCodeLabel, and onCountryCodeChange then please update these to the new dialCode props listed below.

The dial code selector can be customized by setting several properties when using the PhoneNumberField primitive. The custom properties specific to the dial code selector are the following:

  • defaultDialCode (required): The default dial code that will be selected upon render
  • dialCodeList: An array of dial codes (strings) used as options in the dial code selector
  • dialCodeName: A name used when handling form submission for the dial code selector
  • dialCodeLabel: A hidden accessible label for the dial code selector
  • onDialCodeChange: A custom change handler for the dial code selector
  • If both defaultDialCode, dialCodeList, dialCodeName, dialCodeLabel, and onDialCodeChange and the corresponding countryCode prop are provided, then the value in the dialCode prop will be preferred.
import { PhoneNumberField } from '@aws-amplify/ui-react';

export const DialCodeSelectExample = () => (
  <PhoneNumberField
    label="Phone Number"
    defaultDialCode="+7"
    dialCodeList={['+1', '+44', '+52', '+86', '+91']}
    dialCodeName="dial_code"
    dialCodeLabel="Dial Code"
    onDialCodeChange={(e) => alert(`Dial Code changed to: ${e.target.value}`)}
  />
);

Autocomplete - supporting password managers

Use the autoComplete prop to tell the browser how to populate the PhoneNumberField. By default, the PhoneNumberField primitive uses tel-national as the autoComplete property for the text field and tel-country-code as the autoComplete property for the dial code selector.

If the PhoneNumberField primitive is intended to be used in a form that is compatible with most password managers, the autoComplete property should be set to username (see Password Form Styles that Chromium Understands).

import { Flex, PhoneNumberField, Button } from '@aws-amplify/ui-react';

export const AutoCompleteExample = () => {
  const handleSubmit = (event) => {
    event.preventDefault();
    alert(
      `Phone number submitted with form: ${event.target.phone_number.value}`
    );
  };

  return (
    <Flex as="form" direction="column" gap="1rem" onSubmit={handleSubmit}>
      <PhoneNumberField
        autoComplete="username"
        label="Phone Number"
        name="phone_number"
        defaultDialCode="+1"
      />
      <Button type="submit">Sign In</Button>
    </Flex>
  );
};

Accessibility / Label behavior

import { PhoneNumberField } from '@aws-amplify/ui-react';

export const AccessibilityExample = () => (
  <PhoneNumberField
    label="Phone Number"
    labelHidden={true}
    defaultDialCode="+1"
    placeholder="Phone Number"
    dialCodeLabel="Dial code"
  />
);

Sizes

PhoneNumberField sizes are designed to match the styling of other form field components such as Buttons. There are three sizes: 'small', (default), and 'large'.

import { PhoneNumberField, Flex, Button } from '@aws-amplify/ui-react';

export const SizeExample = () => (
  <Flex direction="column" gap="1rem">
    <Flex>
      <PhoneNumberField
        defaultDialCode="+1"
        label="Small"
        size="small"
        labelHidden
      />
      <Button size="small">Small</Button>
    </Flex>
    <Flex>
      <PhoneNumberField defaultDialCode="+1" label="Default" labelHidden />
      <Button>Default</Button>
    </Flex>
    <Flex>
      <PhoneNumberField
        defaultDialCode="+1"
        label="Large"
        size="large"
        labelHidden
      />
      <Button size="large">Large</Button>
    </Flex>
  </Flex>
);

Variations

There are two variation styles available: default and quiet.

import { PhoneNumberField, Flex } from '@aws-amplify/ui-react';

export const VariationExample = () => (
  <Flex direction="column">
    <PhoneNumberField defaultDialCode="+1" label="Default" />
    <PhoneNumberField defaultDialCode="+1" label="Quiet" variation="quiet" />
  </Flex>
);

Descriptive text

To provide additional descriptive text of the field's requirements, use the descriptiveText prop. To customize the descriptive text, you may pass a Text component as the prop's value.

This is basic descriptive text

This is customized descriptive text

import { PhoneNumberField, Text } from '@aws-amplify/ui-react';

export const DescriptiveTextExample = () => (
  <>
    <PhoneNumberField
      defaultDialCode="+1"
      label="Phone Number"
      descriptiveText="This is basic descriptive text"
    />
    <PhoneNumberField
      defaultDialCode="+1"
      label="Phone Number"
      descriptiveText={
        <Text
          color="rebeccapurple"
          fontStyle="normal"
          fontSize="1.2rem"
          as="span"
        >
          This is customized descriptive text
        </Text>
      }
    />
  </>
);

States

The available PhoneNumberField states include isDisabled and isReadOnly. A disabled field will be not be focusable, mutable, or submitted with form data. A readonly field cannot be edited by the user.

You can't submit me

You can't edit me

import { PhoneNumberField, Flex } from '@aws-amplify/ui-react';

export const StatesExample = () => (
  <Flex direction="column" gap="2rem">
    <PhoneNumberField
      defaultDialCode="+1"
      label="Disabled"
      isDisabled={true}
      descriptiveText="You can't submit me"
    />
    <PhoneNumberField
      defaultDialCode="+1"
      label="Readonly"
      isReadOnly={true}
      descriptiveText="You can't edit me"
    />
  </Flex>
);

Required field

Use the isRequired prop to specify a required field. If a user attempts to submit a field that is both required and empty, they will be prompted to fill out the field.

import { PhoneNumberField, Flex, Button } from '@aws-amplify/ui-react';

export const RequiredFieldExample = () => {
  const handleSubmit = (event) => {
    event.preventDefault();
    alert(
      `Phone number submitted with form: ${event.target.phone_number.value}`
    );
  };

  return (
    <Flex as="form" direction="column" onSubmit={handleSubmit}>
      <PhoneNumberField
        defaultDialCode="+1"
        label="Phone Number"
        name="phone_number"
        isRequired={true}
      />
      <Button type="submit" width="10rem">
        Submit
      </Button>
    </Flex>
  );
};

There is no default styling for required form fields. Customize the label or descriptiveText to instruct the user of the required field.

Required

import { PhoneNumberField, Flex, Button, Text } from '@aws-amplify/ui-react';

export const RequiredFieldStyledExample = () => {
  const handleSubmit = (event) => {
    event.preventDefault();
    alert(
      `Primary phone number: ${event.target.primary_phone.value} \nSecondary phone number: ${event.target.secondary_phone.value}`
    );
  };

  return (
    <Flex as="form" direction="column" onSubmit={handleSubmit}>
      <PhoneNumberField
        defaultDialCode="+1"
        label="Primary phone number"
        name="primary_phone"
        descriptiveText={
          <Text as="span" fontSize="0.8rem" color="red" fontStyle="italic">
            Required
          </Text>
        }
        isRequired={true}
      />
      <PhoneNumberField
        defaultDialCode="+1"
        label={
          <Text>
            Secondary phone number
            <Text as="span" fontSize="0.8rem" color="red" padding="0.25rem">
              (required)
            </Text>
          </Text>
        }
        name="secondary_phone"
        isRequired={true}
      />
      <Button type="submit">Submit</Button>
    </Flex>
  );
};

Validation error

Use the hasError and errorMessage fields to mark a PhoneNumberField as having a validation error.

Not a valid phone number! 😱

import { PhoneNumberField } from '@aws-amplify/ui-react';

export const ValidationErrorExample = () => (
  <PhoneNumberField
    defaultDialCode="+1"
    label="Phone number"
    defaultValue="1234"
    hasError={true}
    errorMessage="Not a valid phone number! 😱"
  />
);

Forward refs

The standard ref prop will forward to the underlying input element, and the dialCodeRef prop forwards to the dial code select element.

The following is a contrived example demonstrating use of the ref and dialCodeRef props:

`inputRef` value:

import { PhoneNumberField, Flex, Text } from '@aws-amplify/ui-react';
import * as React from 'react';

export const RefsExample = () => {
  const inputRef = React.useRef(null);
  const dialCodeRef = React.useRef(null);

  const [inputRefValue, setInputRefValue] = React.useState('');

  const onBlur = () => {
    dialCodeRef.current.focus();
    setInputRefValue(inputRef.current.value);
  };

  return (
    <Flex direction="column">
      <PhoneNumberField
        ref={inputRef}
        dialCodeRef={dialCodeRef}
        label="Phone number"
        defaultDialCode="+1"
        onBlur={onBlur}
      />
      <Text>`inputRef` value: {inputRefValue}</Text>
    </Flex>
  );
};

Standard HTML attributes

The PhoneNumberField will accept any of the standard HTML attributes that a <input> element accepts. Standard <input> attributes can be found in the MDN Documentation

<PhoneNumberField label="Phone Number" name="phone"/>

CSS Styling

Theme

You can customize the appearance of all PhoneNumberField components in your application with a Theme.

PhoneNumberField Theme Source

import { ThemeProvider, PhoneNumberField } from '@aws-amplify/ui-react';

const theme = {
  name: 'phonenumber-theme',
  tokens: {
    components: {
      phonenumberfield: {
        //these design tokens will apply to both the select and input that are part of the phonenumber field
        color: { value: '{colors.blue.60}' },
        fontSize: { value: '{fontSizes.large}' },
        borderColor: { value: '{colors.neutral.80}' },
        _focus: {
          borderColor: { value: '{colors.neutral.100}' },
        },
      },
    },
  },
};

export const PhoneNumberFieldThemeExample = () => (
  <ThemeProvider theme={theme} colorMode="light">
    <PhoneNumberField
      label="Themed field"
      defaultDialCode="+1"
      labelHidden={true}
    />
  </ThemeProvider>
);

Target classes

ClassDescription
amplify-countrycodeselectClass applied to the Dial Code Select within the PhoneNumberField primitive
amplify-dialcodeselectClass applied to the Dial Code Select within the PhoneNumberField primitive
amplify-phonenumberfieldTop level element that wraps the PhoneNumberField primitive
  • --amplify-components-phonenumberfield-border-color
  • --amplify-components-phonenumberfield-color
  • --amplify-components-phonenumberfield-focus-border-color
  • --amplify-components-phonenumberfield-font-size

Global styling

To override styling on all PhoneNumberField primitives, you can set the Amplify CSS variables with the built-in .amplify-phonenumberfield and .amplify-dialcodeselect class.

/* styles.css */
.amplify-phonenumberfield,
.amplify-dialcodeselect {
  --amplify-components-fieldcontrol-border-color: rebeccapurple;
}

Local styling

To override styling on a specific PhoneNumberField, you can use a class selector or style props.

Using a class selector:

/* styles.css */
.custom-phonenumberfield-class .amplify-phonenumberfield,
.custom-phonenumberfield-class .amplify-dialcodeselect {
  border-radius: 0;
}

Using style props:

All style props will be applied to the Flex wrapper of the PhoneNumberField. To style the input of the PhoneNumberField, you can pass a inputStyles prop with the style props you want to apply to the input.

import { PhoneNumberField, Text, useTheme } from '@aws-amplify/ui-react';

export const StylePropsExample = () => {
  const { tokens } = useTheme();

  return (
    <>
      <PhoneNumberField
        defaultDialCode="+1"
        label={
          <Text fontWeight="bold" fontSize={tokens.fontSizes.large}>
            Phone Number:
          </Text>
        }
        padding="xl"
        border={`1px solid ${tokens.colors.primary[60]}`}
      />
      <PhoneNumberField
        defaultDialCode="+1"
        label="Phone number"
        inputStyles={{
          backgroundColor: 'primary.10',
        }}
      />
    </>
  );
};

Amplify open source software, documentation and community are supported by Amazon Web Services.

© 2024 Amazon Web Services, Inc. and its affiliates. All rights reserved. View the site terms and privacy policy.

Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.