Skip to content

LoginForm

Sign in with email + password on the evolve-feature-form pattern. Self-contained: runs useLogin, maps server errors by code (AuthenticationError → form-level, ValidationError → per-field), and delegates session-setting to AuthProvider's onAuthenticated seam.

import { LoginForm } from "@evolve-storefront/feature-auth/login-form";

Renders inside AuthProvider.

Preview

DefaultOpen in Storybook ↗

Usage

// Runs the login mutation; AuthProvider's onAuthenticated sets the session.
<LoginForm onLoggedIn={() => router.push("/account")} />;

Props

PropTypeDescription
defaultValues?{ email?: string | undefined; }
validationBehavior?"aria" | "native"

Default "aria": mark fields via ARIA rather than blocking native submit. The form is then noValidate, so an input's own constraint (type="email") never stops the submit with a browser tooltip that the field's error does not match.

onLoggedIn?((customer: AuthCustomer) => void)

Called with the customer on success (alongside the provider's session seam).

Any other props go to the root element, like on a plain HTML element.

Change the layout

Pass children to LoginForm to arrange its parts yourself. Every part is exported from @evolve-storefront/feature-auth/login-form.

LoginFormViewThe email and password fields, validated against LoginFormSchema.
PropTypeDescription
onValidSubmit(values: { email: string; password: string; }) => void

Called with the values once they pass the schema.

validationBehavior?"aria" | "native"

Default "aria": mark fields via ARIA rather than blocking native submit. The form is then noValidate, so an input's own constraint (type="email") never stops the submit with a browser tooltip that the field's error does not match.

defaultValues?{ email?: string | undefined; }
isPending?boolean
error?string | null

Shown above the submit button, such as wrong credentials.

serverErrors?FormValidationErrors

Any other props go to the root element, like on a plain HTML element.

Examples

With ErrorWrong credentials: the server refuses the login and the form says so above the submit button.
// An AuthenticationError renders as the form-level alert; nothing to wire.
<LoginForm onLoggedIn={() => router.push("/account")} />;
Open in Storybook ↗
PrefilleddefaultValues prefills the email, e.g.
<LoginForm
defaultValues={{ email: searchParams.get("email") ?? "" }}
onLoggedIn={() => router.push("/account")}
/>;
Open in Storybook ↗