VisorVisor
Blocks

Login Form

A login form block using Visor form components (Button, Input, Label, Card), with optional OAuth provider buttons.

Preview

With OAuth providers

Pass oauthProviders to render provider buttons above the credentials form, separated by a labeled divider. The block stays auth-agnostic — your onOAuthSignIn handler owns the actual sign-in call (e.g. supabase.auth.signInWithOAuth). Icons are caller-supplied; the block ships no provider assets.

OAuth-only

Set hideCredentials to drop the email/password fields and divider for OAuth-only flows.

Installation

npx visor add --block login-form

This copies files into your project:

  • blocks/login-form/login-form.tsx — the block component
  • blocks/login-form/login-form.module.css — the styles

Usage

import { LoginForm } from '@/blocks/login-form/login-form';

export default function LoginPage() {
  return <LoginForm />;
}

With OAuth

'use client';

import { GoogleLogo } from '@phosphor-icons/react';
import { createClient } from '@/lib/supabase/client';
import { LoginForm } from '@/blocks/login-form/login-form';

export default function LoginPage() {
  const supabase = createClient();
  return (
    <LoginForm
      oauthProviders={[
        {
          id: 'google',
          label: 'Continue with Google',
          icon: <GoogleLogo size={18} weight="bold" />,
        },
      ]}
      onOAuthSignIn={(provider) =>
        supabase.auth.signInWithOAuth({
          provider,
          options: { redirectTo: `${location.origin}/auth/callback` },
        })
      }
    />
  );
}

Props

PropTypeDefaultDescription
classNamestringMerged onto the root Card.
oauthProvidersOAuthProvider[]Providers rendered as outline buttons above the form. Omit for the plain email/password form.
onOAuthSignIn(id: string) => void | Promise<void>Called with the provider id on click. Returning a promise toggles a per-button loading state (disabled + aria-busy).
dividerLabelReactNode"or continue with"Label shown in the divider between OAuth and credentials.
errorstring | nullRendered in a destructive Alert above the form.
hideCredentialsbooleanfalseHide the email/password fields and submit button for OAuth-only flows.

OAuthProvider is { id: string; label: ReactNode; icon?: ReactNode }.

Composition

This block composes Visor primitives:

  • Card — Container with surface styling and border
  • Input — Theme-aware text inputs
  • Field / FieldLabel — Accessible form labels
  • Button — Primary action and OAuth provider buttons
  • Separator — Labeled divider between OAuth and credentials
  • Alert — Destructive error placard

About Blocks

Blocks are complete UI patterns made up of multiple Visor components. Unlike individual components, blocks represent larger, composed sections of UI — such as login forms, settings pages, or dashboard panels.

Blocks are copy-and-own, just like components. Install them into your project and customize freely.