From d085cbca26d0012ad65f21b48f566070284454fc Mon Sep 17 00:00:00 2001 From: Dikshantpatil2077 Date: Fri, 9 Oct 2026 15:41:36 +0530 Subject: [PATCH] feat: add AR illustration and armchair components with animations --- app/app.css | 10 ++ app/components/auth/ar-illustration.tsx | 129 +++++++++++++++++++++++ app/components/auth/armchair.tsx | 43 ++++++++ app/components/auth/auth-brand-panel.tsx | 36 +++++++ app/components/logo-mark.tsx | 9 ++ app/routes/admin/login.tsx | 4 +- 6 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 app/components/auth/ar-illustration.tsx create mode 100644 app/components/auth/armchair.tsx create mode 100644 app/components/auth/auth-brand-panel.tsx create mode 100644 app/components/logo-mark.tsx diff --git a/app/app.css b/app/app.css index da21390..e29413d 100644 --- a/app/app.css +++ b/app/app.css @@ -58,3 +58,13 @@ model-viewer { color: rgb(156 163 175); /* gray-400 */ opacity: 1; } + +@keyframes float { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-12px); } +} + +@keyframes fade-up { + from { opacity: 0; transform: translateY(12px); } + to { opacity: 1; transform: translateY(0); } +} diff --git a/app/components/auth/ar-illustration.tsx b/app/components/auth/ar-illustration.tsx new file mode 100644 index 0000000..d038cf5 --- /dev/null +++ b/app/components/auth/ar-illustration.tsx @@ -0,0 +1,129 @@ +import { Armchair } from '~/components/auth/armchair'; + +export function ArIllustration() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* Phone body */} + + + + + {/* Wall / floor horizon */} + + + {/* Perspective floor seen through the camera */} + + {[240, 262, 290, 326, 372].map((y) => ( + + ))} + {[-260, -170, -90, -30, 30, 90, 170, 260].map((dx) => ( + + ))} + + + + + {/* Placement reticle */} + + + + + + + + + + {/* Camera scan brackets */} + + + + + + + + {/* AR badge */} + + AR + + {/* Shutter */} + + + + + {/* Notch */} + + + {/* Floating particles */} + {[ + { cx: 70, cy: 120, r: 3, d: '3s' }, + { cx: 330, cy: 90, r: 2, d: '4s' }, + { cx: 345, cy: 260, r: 3, d: '3.6s' }, + { cx: 55, cy: 300, r: 2, d: '4.4s' }, + { cx: 95, cy: 210, r: 1.5, d: '2.8s' }, + ].map((p) => ( + + + + ))} + + ); +} diff --git a/app/components/auth/armchair.tsx b/app/components/auth/armchair.tsx new file mode 100644 index 0000000..cc8ec78 --- /dev/null +++ b/app/components/auth/armchair.tsx @@ -0,0 +1,43 @@ +// SVG armchair drawn in the coordinate space of ; relies on its gradient/filter defs. +export function Armchair() { + return ( + + {/* Contact shadow */} + + + {/* Back legs */} + + + + {/* Backrest */} + + + + {/* Tufting */} + + {[[184, 210], [200, 206], [216, 210], [192, 230], [208, 230]].map(([cx, cy]) => ( + + ))} + + + + + + {/* Seat base */} + + {/* Seat cushion */} + + + + {/* Armrests */} + + + + + + {/* Front legs */} + + + + ); +} diff --git a/app/components/auth/auth-brand-panel.tsx b/app/components/auth/auth-brand-panel.tsx new file mode 100644 index 0000000..5ca808a --- /dev/null +++ b/app/components/auth/auth-brand-panel.tsx @@ -0,0 +1,36 @@ +import { LogoMark } from '~/components/logo-mark'; +import { ArIllustration } from '~/components/auth/ar-illustration'; + +export function AuthBrandPanel() { + return ( + + ); +} diff --git a/app/components/logo-mark.tsx b/app/components/logo-mark.tsx new file mode 100644 index 0000000..1236eca --- /dev/null +++ b/app/components/logo-mark.tsx @@ -0,0 +1,9 @@ +import { cn } from '~/lib/utils'; + +export function LogoMark({ className }: { className?: string }) { + return ( +
+ t. +
+ ); +} diff --git a/app/routes/admin/login.tsx b/app/routes/admin/login.tsx index acad791..7a391e8 100644 --- a/app/routes/admin/login.tsx +++ b/app/routes/admin/login.tsx @@ -2,7 +2,7 @@ import { useState, useEffect } from 'react'; import { useSubmit, useNavigation, useActionData, useNavigate, redirect } from 'react-router'; import type { Route } from './+types/login'; import { pb } from '~/lib/pocketbase'; -`import { Lock, Mail, Eye, EyeOff, Loader2, ArrowRight, AlertCircle } from 'lucide-react'; +import { Lock, Mail, Eye, EyeOff, Loader2, ArrowRight, AlertCircle } from 'lucide-react'; import { Input } from '~/components/ui/input'; import { Button } from '~/components/ui/button'; import { Label } from '~/components/ui/label'; @@ -176,7 +176,7 @@ export default function Login() { name="password" autoComplete="current-password" required - className={`${fieldInput} pr-12`} + className={fieldInput + ' pr-12'} placeholder="Enter your password" value={password} onChange={(e) => {