// LoginCard composition — pairs email + password inputs with an // optional OAuth row. The card is stylistically opinionated (max // width, centred, raised) so apps don't reinvent the same shell. // // Submit handling stays with the consumer (form action / onSubmit). // The component just renders the surface. import type { FormHTMLAttributes, ReactNode } from 'react' import { Button } from '../primitives/button' import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from '../primitives/card' import { Input } from '../primitives/input' import { Label } from '../primitives/label' import { cn } from '../cn' interface OAuthProvider { readonly id: string readonly label: string } /** User-facing strings — pass catalog values to localize. Defaults are * English so the card works unconfigured. */ export interface LoginCardLabels { /** Email field label. Default `'Email'`. */ readonly email?: string /** Email input placeholder. Default `'you@company.com'`. */ readonly emailPlaceholder?: string /** Password field label. Default `'Password'`. */ readonly password?: string /** "Forgot password?" link text (shown when `forgotHref` is set). * Default `'Forgot?'`. */ readonly forgot?: string /** OAuth divider caption. Default `'or continue with'`. */ readonly oauthDivider?: string /** Sign-up footer prompt (shown when `signUpHref` is set). * Default `'New here?'`. */ readonly signUpPrompt?: string /** Sign-up footer link text. Default `'Create an account'`. */ readonly signUp?: string } const DEFAULT_LOGIN_LABELS: Required = { email: 'Email', emailPlaceholder: 'you@company.com', password: 'Password', forgot: 'Forgot?', oauthDivider: 'or continue with', signUpPrompt: 'New here?', signUp: 'Create an account', } interface LoginCardProps extends Omit, 'children'> { readonly title?: string readonly description?: string readonly eyebrow?: string readonly submitLabel?: string readonly oauthProviders?: ReadonlyArray readonly onOAuth?: (providerId: string) => void readonly signUpHref?: string readonly forgotHref?: string readonly className?: string /** Override the card's own chrome strings. Defaults are English. */ readonly labels?: LoginCardLabels } export const LoginCard = ({ title = 'Welcome back', description = 'Sign in to your account to continue.', eyebrow, submitLabel = 'Sign in', oauthProviders, onOAuth, signUpHref, forgotHref, className, labels, ...formProps }: LoginCardProps): ReactNode => { const t = { ...DEFAULT_LOGIN_LABELS, ...labels } return (
{eyebrow ? (
{eyebrow}
) : null} {title} {description}
{forgotHref ? ( {t.forgot} ) : null}
{oauthProviders && oauthProviders.length > 0 ? ( <>
{t.oauthDivider}
{oauthProviders.map((p) => ( ))}
) : null} {signUpHref ? ( {t.signUpPrompt} {t.signUp} ) : null}
) }