Text7 checks

FormEmail

Email with typo hints, domain checks and code verification.

Example

Demo code 123456. amina@kijani.co.ke is taken.

Installation
bunx --bun shadcn@latest add @fieldkit/form-email

Needs the @fieldkit registry. Add it once

Usage
  1. 1

    Add the field to your schema

    schema.ts
    import { z } from "zod"import { emailField } from "@/lib/field-schemas"
    export const schema = z.object({  email: emailField({ blockDisposable: true }),})
  2. 2

    Render it inside a Form

    The name prop matches the schema key.

    example-form.tsx
    import { Form } from "@/components/form/form"import { FormEmail } from "@/components/form/form-email"import { FormSubmit } from "@/components/form/form-submit"import { FieldGroup } from "@/components/ui/field"import { schema } from "./schema"
    export function ExampleForm() {  return (    <Form      schema={schema}      defaultValues={{ email: "" }}      onSubmit={save}    >      <FieldGroup>        <FormEmail name="email" />        <FormSubmit>Save</FormSubmit>      </FieldGroup>    </Form>  )}
Checks
Valid formatdefaultEnter a valid email address
Typo suggestionssuggestDid you mean amina@gmail.com?
No disposable domainsblockDisposableUse a permanent email address
No free providersblockFreeUse your work email
Domain accepts mailcheckDomain={fn}This domain cannot receive email
Not already registeredisFree={fn}This email already has an account
Code verificationverify={{ send, check }}That code is wrong. Check it or resend.
On the server

Parse the same schema again on the server, and repeat the network checks there.

Terminal
const values = await signupSchema.parseAsync(await request.json())
if (!(await isEmailFree(values.email))) {  throw new FormSubmitError({ fields: { email: "This email already has an account" } })}
Best practices
  • Verify with a code instead of asking for the email twice
  • Lowercase the domain, keep the local part as typed
  • Run network checks on blur, debounced 400 ms, never per keystroke
  • Show typo fixes as a hint the user accepts, never auto-correct
  • Parse the same schema on the server
Try these values
Terminal
emailField({ blockDisposable: true })
InputResultOutput
" Amina@Kijani.co.ke "Valid"amina@kijani.co.ke"
"amina@"Invalid
Enter a valid email address
"amina@mailinator.com"Invalid
Use a permanent email address
""Invalid
Enter a valid email address
API reference

FormEmail

verify{ send, check }Sends a 6-digit code and checks it. Submit waits until it is confirmed.
isFree(email) => Promise<boolean>Returns true when no account uses the email. Runs on blur and submit, debounced 400 ms.
checkDomain(domain) => Promise<boolean>Check the domain can receive mail.

Field frame

namestringKey in the schema. Also picks the preset label and autocomplete.
labelReact.ReactNodeOverrides the preset label. Pass null to hide it.
descriptionReact.ReactNodeHint under the control.
requiredbooleanOverrides the asterisk read from the schema.
fieldPropsFormFieldPropsProps for the wrapping Field, such as className.

Search docs

Find a component, input or example