SPB Git forge

spb/ai-atlas

Public
41commits 1branches 0releases
4.6 MBsize
maindefault branch
12 days agolast push
HTML 77.2% TypeScript 10.5% Python 9.6% JavaScript 2.5%
1.4 KB · 27 lines tsx
Raw Blame History
1'use client';2import { useActionState } from 'react';3import { loginAction } from '@/lib/admin/actions';45/** Login form: posts the token to a server action; the token only ever travels in this request body and the httpOnly cookie. */6export function LoginForm({ hint }: { hint?: string | null }) {7  const [state, action, pending] = useActionState(loginAction, { error: null });8  return (9    <form action={action} className="mt-6 max-w-sm space-y-3">10      <label className="block">11        <span className="eyebrow block pb-1">Admin token</span>12        <input type="password" name="token" required autoComplete="off" autoFocus spellCheck={false} className="h-11 w-full border border-rule-strong bg-surface px-3 text-[16px] text-ink focus:border-accent focus:outline-none" />13      </label>14      <button type="submit" disabled={pending} className="inline-flex h-11 w-full items-center justify-center bg-ink px-4 text-sm font-medium text-canvas hover:opacity-90 disabled:opacity-60">15        {pending ? 'Checking…' : 'Sign in'}16      </button>17      {state?.error && (18        <p role="alert" className="text-sm text-danger">19          {state.error}20        </p>21      )}22      {!state?.error && hint && <p className="text-xs text-ink-3">{hint}</p>}23      <p className="text-xs text-ink-3">The token is validated against the API and kept in an httpOnly cookie for 12 hours. It is never sent to the browser.</p>24    </form>25  );26}27