feat(02-01): brand auth pages with gradient bg, wordmark, and Alert errors
- LoginPage: pastel gradient background (saving/bill/investment light shades) - LoginPage: gradient text wordmark with data-testid='wordmark' - LoginPage: shadcn Alert destructive with AlertCircle icon for error display - RegisterPage: mirrors LoginPage branding treatment exactly - Both pages: Card shadow-lg for visual lift against gradient - All 6 AUTH tests pass (AUTH-01 through AUTH-04)
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { AlertCircle } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||
import { palette } from '@/lib/palette'
|
||||
import type { AuthContext } from '@/hooks/useAuth'
|
||||
|
||||
interface Props {
|
||||
@@ -31,15 +34,36 @@ export function LoginPage({ auth: { login }, onToggle }: Props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-background">
|
||||
<Card className="w-full max-w-md">
|
||||
<div
|
||||
className="flex min-h-screen items-center justify-center"
|
||||
style={{
|
||||
background: `linear-gradient(135deg, ${palette.saving.light}, ${palette.bill.light}, ${palette.investment.light})`,
|
||||
}}
|
||||
>
|
||||
<Card className="w-full max-w-md shadow-lg">
|
||||
<CardHeader>
|
||||
<CardTitle>{t('auth.login')}</CardTitle>
|
||||
<CardDescription>{t('app.title')}</CardDescription>
|
||||
<span
|
||||
data-testid="wordmark"
|
||||
className="text-2xl font-bold tracking-tight"
|
||||
style={{
|
||||
background: `linear-gradient(to right, oklch(0.50 0.12 260), oklch(0.50 0.12 320))`,
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
backgroundClip: 'text',
|
||||
}}
|
||||
>
|
||||
{t('app.title')}
|
||||
</span>
|
||||
</CardHeader>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
{error && <p className="text-sm text-destructive">{error}</p>}
|
||||
{error && (
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>{error}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<Input
|
||||
type="email"
|
||||
placeholder={t('auth.email')}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { AlertCircle } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||
import { palette } from '@/lib/palette'
|
||||
import type { AuthContext } from '@/hooks/useAuth'
|
||||
|
||||
interface Props {
|
||||
@@ -32,15 +35,36 @@ export function RegisterPage({ auth: { register }, onToggle }: Props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-background">
|
||||
<Card className="w-full max-w-md">
|
||||
<div
|
||||
className="flex min-h-screen items-center justify-center"
|
||||
style={{
|
||||
background: `linear-gradient(135deg, ${palette.saving.light}, ${palette.bill.light}, ${palette.investment.light})`,
|
||||
}}
|
||||
>
|
||||
<Card className="w-full max-w-md shadow-lg">
|
||||
<CardHeader>
|
||||
<CardTitle>{t('auth.register')}</CardTitle>
|
||||
<CardDescription>{t('app.title')}</CardDescription>
|
||||
<span
|
||||
data-testid="wordmark"
|
||||
className="text-2xl font-bold tracking-tight"
|
||||
style={{
|
||||
background: `linear-gradient(to right, oklch(0.50 0.12 260), oklch(0.50 0.12 320))`,
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
backgroundClip: 'text',
|
||||
}}
|
||||
>
|
||||
{t('app.title')}
|
||||
</span>
|
||||
</CardHeader>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
{error && <p className="text-sm text-destructive">{error}</p>}
|
||||
{error && (
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>{error}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<Input
|
||||
placeholder={t('auth.displayName')}
|
||||
value={displayName}
|
||||
|
||||
Reference in New Issue
Block a user