Skip to content
buttery

v1.0.0

Source on GitHub

Version 1.0.0

IdentifierField

One field for an email address or a phone number, which tells them apart as they're typed and formats a phone number as it goes.

import { IdentifierField } from "@butteryui/react";

Demo

When to use it

Use it for

  • The first step of a passwordless sign-in or sign-up, as AuthFlow draws it
  • Anywhere either an email address or a phone number will do, such as where to send a receipt

Not for

  • Only an email address: use TextField with type email
  • A whole sign-in screen: use AuthFlow

Examples

Gift note

Both looks: the outlined field for who's buying, and a soft one for who the bag is a gift for.

Left unfinished

Nothing's said while it's typed; leave it unfinished and it says what it needs.

Receipt form

Where a café sends a receipt: an email or a phone, with a box to keep it for next time.

Remembered

A field the app fills with the email it remembers, and empties when someone wants another.

Signing in as rosa@halfmoon.coffee.

Send a code

An email or a phone number, formatted as it's typed, with a button that waits until it's whole.

We'll send a code to sign you in.

Variants and states

As it's typed

A phone number formatted as it goes, an email address left as written, and one that couldn't be used.

One a code couldn't go to: Too many codes sent. Try again in a minute.

Too many codes sent. Try again in a minute.

Props

IdentifierField

PropTypeDefaultDescription
labelstring"Email or phone number"What the field asks for. Defaults to "Email or phone number".
valuestringThe text, a phone number as formatted. Pair with onValueChange to control it.
defaultValuestringThe starting text when uncontrolled.
onValueChange((value: string) => void)Called with the text on every change, a phone number formatted as it's shown.
passkeybooleanfalseOffers saved passkeys too, with autocomplete="username webauthn". Defaults to false.
errorReactNodeWhat's wrong, from outside the field, such as a code that couldn't be sent. Shown in place of its own message.
invalidMessagestringWhat it says once it's left with something that isn't an email address or a phone number.
hintReactNodeA hint under the label, such as the format expected.
variant"outline" | "soft""outline""outline" (the default), a 1px control-border edge on bg-surface, or "soft", a bg-control fill whose edge shows only on hover and while it has focus, for a field on a card or in a toolbar.
iconStartComponentType<IconComponentProps>An icon at the start of the box, such as Mail from lucide-react. Decorative.
iconEndComponentType<IconComponentProps>An icon at the end of the box. Decorative.
announceErrorbooleantrueWhether a new error is read out as it appears. Defaults to true; turn it off when an error summary that takes focus reads the errors instead.

It also takes Omit<ComponentPropsWithRef<"input">, "size" | "value" | "defaultValue" | "children" | "type" | "inputMode" | "autoComplete">.

Accessibility

A labelled text input ("Email or phone number" by default). It asks for the keyboard and the autofill that match what's typed: email, tel, or username until it can tell, and "username webauthn" with passkey to offer saved passkeys. It says nothing while it's typed in; once it's left with something that can't be used, the error describes it and is read out with the field's name.

KeysWhat they do
Letters, numbers and symbolsType them in, a phone number formatted as it goes
EnterSubmits the form it's in

Motion

It doesn't move.

With reduced motion: Nothing changes.

Layout

It fills its container's width at --bt-h-cta (48px) with 16px text, so phones don't zoom in. The error sits under the box and wraps.