diff --git a/package-lock.json b/package-lock.json
index 627ff3f..80c48f5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
"@tanstack/router-devtools": "^1.143.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
+ "framer-motion": "^12.23.26",
"lucide-react": "^0.562.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -3012,6 +3013,33 @@
"url": "https://github.com/sponsors/rawify"
}
},
+ "node_modules/framer-motion": {
+ "version": "12.23.26",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.26.tgz",
+ "integrity": "sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-dom": "^12.23.23",
+ "motion-utils": "^12.23.6",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -3614,6 +3642,21 @@
"node": "*"
}
},
+ "node_modules/motion-dom": {
+ "version": "12.23.23",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz",
+ "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-utils": "^12.23.6"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.23.6",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz",
+ "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==",
+ "license": "MIT"
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -4147,6 +4190,12 @@
"typescript": ">=4.8.4"
}
},
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/package.json b/package.json
index ee622ea..e113be4 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"@tanstack/router-devtools": "^1.143.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
+ "framer-motion": "^12.23.26",
"lucide-react": "^0.562.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
diff --git a/src/assets/images/README.md b/src/assets/images/README.md
new file mode 100644
index 0000000..a004014
--- /dev/null
+++ b/src/assets/images/README.md
@@ -0,0 +1,46 @@
+# Images Directory
+
+This directory contains all image assets for the AgenticIQ application, organized by category.
+
+## Folder Structure
+
+```
+images/
+├── logo/ # Brand logos and identity assets
+├── icons/ # UI icons and symbols
+├── auth/ # Authentication-related images (social login icons, etc.)
+├── backgrounds/ # Background images and decorative elements
+└── ui/ # General UI component images
+```
+
+## Usage Guidelines
+
+### Importing Images in Components
+
+```typescript
+// Example: Importing a logo
+import agenticiqLogo from '@/assets/images/logo/agenticiq-logo.png';
+
+// Example: Importing an icon
+import googleIcon from '@/assets/images/auth/google-icon.svg';
+```
+
+### File Naming Convention
+
+- Use **kebab-case** for all filenames (e.g., `agenticiq-logo.png`, `google-icon.svg`)
+- Be descriptive and avoid abbreviations
+- Include size/resolution suffix if multiple versions exist (e.g., `logo-256x256.png`)
+
+### Image Formats
+
+- **Logos**: PNG (with transparency) or SVG
+- **Icons**: SVG (preferred) or PNG
+- **Photos**: WebP (preferred) or JPG
+- **Backgrounds**: WebP or PNG
+
+### Optimization
+
+- Optimize images before adding them to this directory
+- Use appropriate formats for the use case
+- Consider responsive images for different screen densities
+
diff --git a/src/assets/images/auth/README.md b/src/assets/images/auth/README.md
new file mode 100644
index 0000000..5202b35
--- /dev/null
+++ b/src/assets/images/auth/README.md
@@ -0,0 +1,35 @@
+# Authentication Assets
+
+This directory contains images related to authentication and social login.
+
+## Files to Add
+
+### Social Login Icons
+- `google-icon.svg` - Google sign-in button icon
+- `azure-icon.svg` - Microsoft Azure sign-in button icon
+- `github-icon.svg` - GitHub sign-in icon (if needed)
+- `facebook-icon.svg` - Facebook sign-in icon (if needed)
+
+### Authentication UI
+- `auth-background.svg` - Background pattern for auth pages (if needed)
+- `lock-icon.svg` - Security/lock icon
+- `user-icon.svg` - User profile icon
+
+## Usage Example
+
+```typescript
+import googleIcon from '@/assets/images/auth/google-icon.svg';
+import azureIcon from '@/assets/images/auth/azure-icon.svg';
+
+
+
+ Sign In with Google
+
+```
+
+## Icon Specifications
+
+- **Size**: 24x24px or 32x32px for social login buttons
+- **Format**: SVG preferred for scalability
+- **Style**: Match brand guidelines for each provider
+
diff --git a/src/assets/images/backgrounds/README.md b/src/assets/images/backgrounds/README.md
new file mode 100644
index 0000000..d0ac55e
--- /dev/null
+++ b/src/assets/images/backgrounds/README.md
@@ -0,0 +1,32 @@
+# Background Assets
+
+This directory contains background images and decorative elements.
+
+## Files to Add
+
+### Decorative Elements
+- `gradient-blob-1.svg` - Decorative gradient shape (if needed as image)
+- `gradient-blob-2.svg` - Additional decorative element
+- `pattern-overlay.svg` - Pattern overlay (if needed)
+
+### Background Images
+- `auth-background.jpg` or `.webp` - Full background image for auth pages (if needed)
+- `dashboard-background.svg` - Dashboard background pattern
+
+## Usage Example
+
+```typescript
+import backgroundPattern from '@/assets/images/backgrounds/pattern-overlay.svg';
+
+
+```
+
+## Notes
+
+- Most decorative backgrounds are created with CSS gradients (as in login-page.tsx)
+- Only add image files if CSS gradients cannot achieve the desired effect
+- Optimize all background images for performance
+
diff --git a/src/assets/images/backgrounds/bottom-left-wave1 .svg b/src/assets/images/backgrounds/bottom-left-wave1 .svg
new file mode 100644
index 0000000..e97c83a
--- /dev/null
+++ b/src/assets/images/backgrounds/bottom-left-wave1 .svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/images/backgrounds/bottom-left-wave2.svg b/src/assets/images/backgrounds/bottom-left-wave2.svg
new file mode 100644
index 0000000..f0f20ed
--- /dev/null
+++ b/src/assets/images/backgrounds/bottom-left-wave2.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/images/backgrounds/logo-glow-bg.svg b/src/assets/images/backgrounds/logo-glow-bg.svg
new file mode 100644
index 0000000..41b1a9d
--- /dev/null
+++ b/src/assets/images/backgrounds/logo-glow-bg.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/images/backgrounds/top-right-glow.svg b/src/assets/images/backgrounds/top-right-glow.svg
new file mode 100644
index 0000000..eeda5f1
--- /dev/null
+++ b/src/assets/images/backgrounds/top-right-glow.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/images/icons/README.md b/src/assets/images/icons/README.md
new file mode 100644
index 0000000..d3fc77f
--- /dev/null
+++ b/src/assets/images/icons/README.md
@@ -0,0 +1,33 @@
+# Icon Assets
+
+This directory contains UI icons and symbols used throughout the application.
+
+## Files to Add
+
+### Navigation Icons
+- `home-icon.svg`
+- `dashboard-icon.svg`
+- `settings-icon.svg`
+
+### Action Icons
+- `eye-icon.svg` - Show/hide password
+- `eye-close-icon.svg` - Hide password
+- `search-icon.svg`
+- `plus-icon.svg`
+- `edit-icon.svg`
+- `delete-icon.svg`
+
+### Status Icons
+- `success-icon.svg`
+- `error-icon.svg`
+- `warning-icon.svg`
+- `info-icon.svg`
+
+## Usage Example
+
+```typescript
+import eyeIcon from '@/assets/images/icons/eye-icon.svg';
+
+
+```
+
diff --git a/src/assets/images/logo/AgenticIQLogo.svg b/src/assets/images/logo/AgenticIQLogo.svg
new file mode 100644
index 0000000..0199d43
--- /dev/null
+++ b/src/assets/images/logo/AgenticIQLogo.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/images/logo/README.md b/src/assets/images/logo/README.md
new file mode 100644
index 0000000..c00701d
--- /dev/null
+++ b/src/assets/images/logo/README.md
@@ -0,0 +1,27 @@
+# Logo Assets
+
+This directory contains brand logos and identity assets for AgenticIQ.
+
+## Files to Add
+
+### Primary Logo
+- `agenticiq-logo.png` or `agenticiq-logo.svg` - Main AgenticIQ logo
+- `agenticiq-logo-white.png` - White variant for dark backgrounds
+- `agenticiq-logo-dark.png` - Dark variant for light backgrounds
+
+### Logo Variants
+- `agenticiq-logo-horizontal.svg` - Horizontal layout variant
+- `agenticiq-logo-vertical.svg` - Vertical/stacked layout variant
+- `agenticiq-icon.svg` - Icon-only version (favicon, app icon)
+
+### Trademark Badge
+- `trademark-badge.svg` - TM badge component (if separate from logo)
+
+## Usage Example
+
+```typescript
+import agenticiqLogo from '@/assets/images/logo/agenticiq-logo.svg';
+
+
+```
+
diff --git a/src/assets/images/ui/README.md b/src/assets/images/ui/README.md
new file mode 100644
index 0000000..fab2f2d
--- /dev/null
+++ b/src/assets/images/ui/README.md
@@ -0,0 +1,31 @@
+# UI Component Assets
+
+This directory contains images used in UI components throughout the application.
+
+## Files to Add
+
+### Profile & User
+- `default-avatar.png` - Default user avatar placeholder
+- `profile-placeholder.svg` - Profile image placeholder
+
+### Dashboard Components
+- `metric-card-icon.svg` - Icon for metric cards
+- `empty-state-illustration.svg` - Empty state illustrations
+
+### General UI
+- `loading-spinner.svg` - Loading animation (if not CSS-based)
+- `error-illustration.svg` - Error state illustration
+- `success-illustration.svg` - Success state illustration
+
+## Usage Example
+
+```typescript
+import defaultAvatar from '@/assets/images/ui/default-avatar.png';
+
+
+```
+
diff --git a/src/components/auth/auth-button.tsx b/src/components/auth/auth-button.tsx
new file mode 100644
index 0000000..e1dc3c7
--- /dev/null
+++ b/src/components/auth/auth-button.tsx
@@ -0,0 +1,219 @@
+/**
+ * AuthButton Component
+ * @description Reusable button components for authentication forms.
+ * Includes primary action button and social login buttons.
+ * Follows AgenticIQ Enterprise Coding Guidelines v1.0
+ */
+
+import { type ButtonHTMLAttributes, type ReactNode } from 'react';
+
+/**
+ * Props for AuthButton component
+ */
+interface AuthButtonProps extends ButtonHTMLAttributes {
+ /** Button content */
+ children: ReactNode;
+ /** Loading state */
+ isLoading?: boolean;
+ /** Full width button */
+ fullWidth?: boolean;
+}
+
+/**
+ * Props for SocialButton component
+ */
+interface SocialButtonProps extends ButtonHTMLAttributes {
+ /** Button text */
+ children: ReactNode;
+ /** Icon element to show before text */
+ icon: ReactNode;
+}
+
+/**
+ * Props for TextButton component
+ */
+interface TextButtonProps extends ButtonHTMLAttributes {
+ /** Button text */
+ children: ReactNode;
+}
+
+/**
+ * Google icon for social login
+ * @returns {JSX.Element} Google SVG icon
+ */
+export function GoogleIcon(): JSX.Element {
+ return (
+
+
+
+
+
+
+ );
+}
+
+/**
+ * Azure icon for social login
+ * @returns {JSX.Element} Azure SVG icon
+ */
+export function AzureIcon(): JSX.Element {
+ return (
+
+
+
+
+
+
+ );
+}
+
+/**
+ * AuthButton component
+ * @description Primary action button with cyan/teal background.
+ * Used for main form submissions (Sign In, Sign Up, etc.).
+ * @param {AuthButtonProps} props - Component props
+ * @returns {JSX.Element} AuthButton element
+ */
+export function AuthButton({
+ children,
+ isLoading = false,
+ fullWidth = true,
+ disabled,
+ className = '',
+ ...buttonProps
+}: AuthButtonProps): JSX.Element {
+ return (
+
+ {isLoading ? (
+
+
+
+
+
+ Loading...
+
+ ) : (
+ children
+ )}
+
+ );
+}
+
+/**
+ * SocialButton component
+ * @description Social login button with white background.
+ * Used for Google, Azure, and other OAuth providers.
+ * @param {SocialButtonProps} props - Component props
+ * @returns {JSX.Element} SocialButton element
+ */
+export function SocialButton({
+ children,
+ icon,
+ className = '',
+ ...buttonProps
+}: SocialButtonProps): JSX.Element {
+ return (
+
+
+ {icon}
+
+ {children}
+
+ );
+}
+
+/**
+ * TextButton component
+ * @description Text-only button for secondary actions (e.g., "Forgot password?").
+ * @param {TextButtonProps} props - Component props
+ * @returns {JSX.Element} TextButton element
+ */
+export function TextButton({
+ children,
+ className = '',
+ ...buttonProps
+}: TextButtonProps): JSX.Element {
+ return (
+
+ {children}
+
+ );
+}
+
diff --git a/src/components/auth/auth-card.tsx b/src/components/auth/auth-card.tsx
new file mode 100644
index 0000000..3b67f77
--- /dev/null
+++ b/src/components/auth/auth-card.tsx
@@ -0,0 +1,108 @@
+/**
+ * AuthCard Component
+ * @description Reusable authentication card with gradient background.
+ * Can be used for Sign In, Sign Up, Forgot Password, and other auth screens.
+ * Follows AgenticIQ Enterprise Coding Guidelines v1.0
+ */
+
+import { type ReactNode } from 'react';
+
+/**
+ * Props for AuthCard component
+ */
+interface AuthCardProps {
+ /** Child elements to render inside the card */
+ children: ReactNode;
+ /** Additional CSS classes for customization */
+ className?: string;
+ /** Card variant - 'signin' has standard padding, 'register' has compact padding */
+ variant?: 'signin' | 'register';
+}
+
+/**
+ * Props for AuthCardHeader component
+ */
+interface AuthCardHeaderProps {
+ /** Main title text */
+ title: string;
+ /** Subtitle/description text */
+ subtitle?: string;
+}
+
+/**
+ * Props for AuthCardContent component
+ */
+interface AuthCardContentProps {
+ /** Child elements (form fields, etc.) */
+ children: ReactNode;
+ /** Additional CSS classes */
+ className?: string;
+}
+
+/**
+ * AuthCard component
+ * @description Main container with gradient background (teal to dark blue).
+ * Provides the card structure for authentication screens.
+ * No border to avoid dark line artifacts.
+ * @param {AuthCardProps} props - Component props
+ * @returns {JSX.Element} AuthCard element
+ */
+export function AuthCard({ children, className = '', variant = 'signin' }: AuthCardProps): JSX.Element {
+ const isRegister = variant === 'register';
+
+ return (
+
+ {children}
+
+ );
+}
+
+/**
+ * AuthCardHeader component
+ * @description Header section with title and optional subtitle.
+ * @param {AuthCardHeaderProps} props - Component props
+ * @returns {JSX.Element} AuthCardHeader element
+ */
+export function AuthCardHeader({ title, subtitle }: AuthCardHeaderProps): JSX.Element {
+ return (
+
+
+
+ {title}
+
+ {subtitle && (
+
+ {subtitle}
+
+ )}
+
+
+ );
+}
+
+/**
+ * AuthCardContent component
+ * @description Content section for form fields and actions.
+ * @param {AuthCardContentProps} props - Component props
+ * @returns {JSX.Element} AuthCardContent element
+ */
+export function AuthCardContent({ children, className = '' }: AuthCardContentProps): JSX.Element {
+ return (
+
+ {children}
+
+ );
+}
+
diff --git a/src/components/auth/auth-form-card.tsx b/src/components/auth/auth-form-card.tsx
new file mode 100644
index 0000000..97e14d0
--- /dev/null
+++ b/src/components/auth/auth-form-card.tsx
@@ -0,0 +1,311 @@
+/**
+ * AuthFormCard Component
+ * @description Unified authentication form with animated transitions between Sign In and Register.
+ * Uses framer-motion for smooth expand/collapse animations.
+ * Follows AgenticIQ Enterprise Coding Guidelines v1.0
+ */
+
+import { useState, type FormEvent } from 'react';
+import { motion, AnimatePresence } from 'framer-motion';
+import {
+ AuthCard,
+ AuthCardHeader,
+ AuthCardContent,
+ AuthInput,
+ AuthButton,
+ SocialButton,
+ TextButton,
+ GoogleIcon,
+ AzureIcon,
+} from './index';
+
+/**
+ * Auth form mode type
+ */
+type AuthMode = 'signin' | 'register';
+
+/**
+ * Props for AuthFormCard component
+ */
+interface AuthFormCardProps {
+ /** Initial mode (signin or register) */
+ initialMode?: AuthMode;
+ /** Callback when sign in is submitted */
+ onSignIn?: (email: string, password: string) => void;
+ /** Callback when register is submitted */
+ onRegister?: (data: RegisterData) => void;
+ /** Callback for Google sign in */
+ onGoogleAuth?: () => void;
+ /** Callback for Azure sign in */
+ onAzureAuth?: () => void;
+ /** Callback for forgot password */
+ onForgotPassword?: () => void;
+}
+
+/**
+ * Register form data interface
+ */
+interface RegisterData {
+ firstName: string;
+ lastName: string;
+ email: string;
+ password: string;
+}
+
+/**
+ * Spring transition for smooth physics-based animations
+ * Using 'as const' to ensure literal types for framer-motion
+ */
+const springTransition = {
+ type: 'spring' as const,
+ stiffness: 500,
+ damping: 30,
+ mass: 1,
+};
+
+/**
+ * Animation variants for the collapsible name fields row
+ */
+const nameFieldsVariants = {
+ hidden: {
+ height: 0,
+ opacity: 0,
+ marginBottom: 0,
+ transition: {
+ height: { ...springTransition, duration: 0.2 },
+ opacity: { duration: 0.1 },
+ marginBottom: { ...springTransition, duration: 0.2 },
+ },
+ },
+ visible: {
+ height: 'auto',
+ opacity: 1,
+ marginBottom: 16,
+ transition: {
+ height: { ...springTransition, duration: 0.2 },
+ opacity: { duration: 0.15, delay: 0.05 },
+ marginBottom: { ...springTransition, duration: 0.2 },
+ },
+ },
+};
+
+/**
+ * Animation variants for forgot password link
+ */
+const forgotPasswordVariants = {
+ hidden: {
+ height: 0,
+ opacity: 0,
+ marginTop: 0,
+ transition: {
+ height: { ...springTransition, duration: 0.15 },
+ opacity: { duration: 0.1 },
+ marginTop: { ...springTransition, duration: 0.15 },
+ },
+ },
+ visible: {
+ height: 'auto',
+ opacity: 1,
+ marginTop: 8,
+ transition: {
+ height: { ...springTransition, duration: 0.15 },
+ opacity: { duration: 0.15, delay: 0.05 },
+ marginTop: { ...springTransition, duration: 0.15 },
+ },
+ },
+};
+
+/**
+ * AuthFormCard component
+ * @description Unified authentication card with animated transitions between Sign In and Register modes.
+ * @param {AuthFormCardProps} props - Component props
+ * @returns {JSX.Element} AuthFormCard element
+ */
+export function AuthFormCard({
+ initialMode = 'signin',
+ onSignIn,
+ onRegister,
+ onGoogleAuth,
+ onAzureAuth,
+ onForgotPassword,
+}: AuthFormCardProps): JSX.Element {
+ const [mode, setMode] = useState(initialMode);
+ const isRegister = mode === 'register';
+
+ const [firstName, setFirstName] = useState('');
+ const [lastName, setLastName] = useState('');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [isLoading, setIsLoading] = useState(false);
+
+ /**
+ * Handle form submission based on current mode
+ * @param {FormEvent} e - Form event
+ */
+ const handleSubmit = (e: FormEvent): void => {
+ e.preventDefault();
+ setIsLoading(true);
+
+ if (isRegister) {
+ onRegister?.({ firstName, lastName, email, password });
+ } else {
+ onSignIn?.(email, password);
+ }
+
+ setTimeout(() => setIsLoading(false), 1000);
+ };
+
+ /**
+ * Toggle between Sign In and Register modes
+ */
+ const toggleMode = (): void => {
+ setMode((prev) => (prev === 'signin' ? 'register' : 'signin'));
+ setFirstName('');
+ setLastName('');
+ setEmail('');
+ setPassword('');
+ };
+
+ return (
+
+
+ {/* Header Section */}
+
+
+ {/* Form Content */}
+
+
+
+ {/* Social Login Buttons */}
+
+ }
+ onClick={onGoogleAuth}
+ className="flex-1"
+ >
+ {isRegister ? 'Sign Up with Google' : 'Sign In with Google'}
+
+ }
+ onClick={onAzureAuth}
+ className="flex-1"
+ >
+ {isRegister ? 'Sign Up with Azure' : 'Sign In with Azure'}
+
+
+
+
+ {/* Footer Section */}
+
+
+ {isRegister ? 'Already have an account?' : "Don't have an account?"}
+
+
+ {isRegister ? 'Sign In' : 'Register here'}
+
+
+
+
+ );
+}
diff --git a/src/components/auth/auth-input.tsx b/src/components/auth/auth-input.tsx
new file mode 100644
index 0000000..a1b4c24
--- /dev/null
+++ b/src/components/auth/auth-input.tsx
@@ -0,0 +1,168 @@
+/**
+ * AuthInput Component
+ * @description Reusable input field for authentication forms.
+ * Features semi-transparent background, white text, and password visibility toggle.
+ * Follows AgenticIQ Enterprise Coding Guidelines v1.0
+ */
+
+import { forwardRef, useState, type InputHTMLAttributes } from 'react';
+
+/**
+ * Props for AuthInput component
+ */
+interface AuthInputProps extends InputHTMLAttributes {
+ /** Label text for the input */
+ label: string;
+ /** Whether the field is required */
+ isRequired?: boolean;
+ /** Error message to display */
+ error?: string;
+ /** Additional container classes */
+ containerClassName?: string;
+}
+
+/**
+ * Eye closed icon for password visibility toggle
+ * @returns {JSX.Element} Eye closed SVG icon
+ */
+function EyeClosedIcon(): JSX.Element {
+ return (
+
+
+
+ );
+}
+
+/**
+ * Eye open icon for password visibility toggle
+ * @returns {JSX.Element} Eye open SVG icon
+ */
+function EyeOpenIcon(): JSX.Element {
+ return (
+
+
+
+
+ );
+}
+
+/**
+ * AuthInput component
+ * @description Styled input field with label, required indicator, and password toggle.
+ * Semi-transparent background with white text for dark gradient cards.
+ * @param {AuthInputProps} props - Component props
+ * @returns {JSX.Element} AuthInput element
+ */
+export const AuthInput = forwardRef(
+ function AuthInput(
+ {
+ label,
+ isRequired = false,
+ error,
+ containerClassName = '',
+ type = 'text',
+ placeholder,
+ ...inputProps
+ },
+ ref
+ ): JSX.Element {
+ const [showPassword, setShowPassword] = useState(false);
+ const isPasswordType = type === 'password';
+ const inputType = isPasswordType && showPassword ? 'text' : type;
+
+ const togglePasswordVisibility = (): void => {
+ setShowPassword((prev) => !prev);
+ };
+
+ return (
+
+ {/* Label */}
+
+ {label}
+ {isRequired && * }
+
+
+ {/* Input Container */}
+
+
+
+ {/* Password Toggle Icon */}
+ {isPasswordType && (
+
+ {showPassword ? : }
+
+ )}
+
+
+ {/* Error Message */}
+ {error && (
+
{error}
+ )}
+
+ );
+ }
+);
+
diff --git a/src/components/auth/forgot-password-modal.tsx b/src/components/auth/forgot-password-modal.tsx
new file mode 100644
index 0000000..f5c9aaf
--- /dev/null
+++ b/src/components/auth/forgot-password-modal.tsx
@@ -0,0 +1,391 @@
+/**
+ * ForgotPasswordModal Component
+ * @description Modal dialog for password recovery with two steps:
+ * 1. Email input (forgot password)
+ * 2. OTP verification (verify your email)
+ * Features smooth animated transitions between steps.
+ * Follows AgenticIQ Enterprise Coding Guidelines v1.0
+ */
+
+import { useState, useRef, useEffect, type FormEvent, type KeyboardEvent, type ClipboardEvent } from 'react';
+import { motion, AnimatePresence, type Easing } from 'framer-motion';
+import { AuthInput, AuthButton } from './index';
+
+/**
+ * Modal step type - determines which view to show
+ */
+type ModalStep = 'email' | 'verify';
+
+/**
+ * Props for ForgotPasswordModal component
+ */
+interface ForgotPasswordModalProps {
+ /** Whether the modal is visible */
+ isOpen: boolean;
+ /** Callback when modal should close */
+ onClose: () => void;
+ /** Callback when email is submitted */
+ onSubmit?: (email: string) => void;
+ /** Callback when OTP is verified */
+ onVerify?: (otp: string) => void;
+}
+
+/**
+ * Close icon component
+ */
+function CloseIcon(): JSX.Element {
+ return (
+
+
+
+ );
+}
+
+/**
+ * Left arrow icon component
+ */
+function ArrowLeftIcon(): JSX.Element {
+ return (
+
+
+
+ );
+}
+
+/**
+ * Smooth easing curve for animations (cubic-bezier)
+ */
+const smoothEasing: Easing = [0.4, 0, 0.2, 1];
+
+/**
+ * OTP Input component for 6-digit verification code
+ */
+function OTPInput({
+ otp,
+ setOtp,
+}: {
+ otp: string[];
+ setOtp: React.Dispatch>;
+}): JSX.Element {
+ const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
+
+ // Auto-focus first input when component mounts
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ inputRefs.current[0]?.focus();
+ }, 300);
+ return () => clearTimeout(timer);
+ }, []);
+
+ const handleChange = (index: number, value: string): void => {
+ if (value.length > 1) value = value.slice(-1);
+ if (value && !/^\d$/.test(value)) return;
+
+ const newOtp = [...otp];
+ newOtp[index] = value;
+ setOtp(newOtp);
+
+ if (value && index < 5) {
+ inputRefs.current[index + 1]?.focus();
+ }
+ };
+
+ const handleKeyDown = (e: KeyboardEvent, index: number): void => {
+ if (e.key === 'Backspace' && !otp[index] && index > 0) {
+ inputRefs.current[index - 1]?.focus();
+ }
+ };
+
+ const handlePaste = (e: ClipboardEvent): void => {
+ e.preventDefault();
+ const pastedData = e.clipboardData.getData('text').replace(/\D/g, '').slice(0, 6);
+ const newOtp = [...otp];
+ for (let i = 0; i < pastedData.length; i++) {
+ newOtp[i] = pastedData[i];
+ }
+ setOtp(newOtp);
+ const nextIndex = Math.min(pastedData.length, 5);
+ inputRefs.current[nextIndex]?.focus();
+ };
+
+ return (
+
+ {otp.map((digit, index) => (
+ { inputRefs.current[index] = el; }}
+ type="text"
+ inputMode="numeric"
+ maxLength={1}
+ value={digit}
+ onChange={(e) => handleChange(index, e.target.value)}
+ onKeyDown={(e) => handleKeyDown(e, index)}
+ onPaste={handlePaste}
+ className="
+ w-[44px] h-[44px]
+ bg-[rgba(255,255,255,0.15)]
+ border border-[rgba(255,255,255,0.1)]
+ rounded-[8px]
+ text-center text-white text-[18px] font-medium
+ outline-none
+ focus:border-[rgba(255,255,255,0.4)]
+ focus:bg-[rgba(255,255,255,0.2)]
+ transition-all duration-200
+ "
+ placeholder="•"
+ aria-label={`Digit ${index + 1}`}
+ />
+ ))}
+
+ );
+}
+
+/**
+ * ForgotPasswordModal component
+ * @description Modal with smooth transitions between email input and OTP verification.
+ * @param {ForgotPasswordModalProps} props - Component props
+ * @returns {JSX.Element} ForgotPasswordModal element
+ */
+export function ForgotPasswordModal({
+ isOpen,
+ onClose,
+ onSubmit,
+ onVerify,
+}: ForgotPasswordModalProps): JSX.Element {
+ const [step, setStep] = useState('email');
+ const [email, setEmail] = useState('');
+ const [otp, setOtp] = useState(['', '', '', '', '', '']);
+ const [isLoading, setIsLoading] = useState(false);
+
+ const handleClose = (): void => {
+ onClose();
+ setTimeout(() => {
+ setStep('email');
+ setEmail('');
+ setOtp(['', '', '', '', '', '']);
+ setIsLoading(false);
+ }, 250);
+ };
+
+ const handleEmailSubmit = (e: FormEvent): void => {
+ e.preventDefault();
+ setIsLoading(true);
+ onSubmit?.(email);
+ setTimeout(() => {
+ setIsLoading(false);
+ setStep('verify');
+ }, 600);
+ };
+
+ const handleVerifySubmit = (e: FormEvent): void => {
+ e.preventDefault();
+ const otpString = otp.join('');
+ if (otpString.length !== 6) return;
+
+ setIsLoading(true);
+ onVerify?.(otpString);
+ setTimeout(() => {
+ setIsLoading(false);
+ handleClose();
+ }, 800);
+ };
+
+ const handleResendCode = (): void => {
+ console.log('Resend code to:', email);
+ };
+
+ const handleBackdropClick = (): void => handleClose();
+ const handleModalClick = (e: React.MouseEvent): void => e.stopPropagation();
+
+ const isEmailStep = step === 'email';
+
+ return (
+
+ {isOpen && (
+ <>
+ {/* Backdrop */}
+
+
+ {/* Modal Container */}
+
+ {/* Modal Card */}
+
+ {/* Header with Close Button */}
+
+ {/* Title Section */}
+
+
+
+
+ {isEmailStep ? 'Forgot your password' : 'Verify Your Email'}
+
+
+ {isEmailStep ? 'and continue' : 'Enter the 6-Digit Verification Code'}
+
+
+
+
+
+ {/* Close Button */}
+
+
+
+
+
+ {/* Form Content */}
+
+
+ {isEmailStep ? (
+
+ setEmail(e.target.value)}
+ isRequired
+ autoComplete="email"
+ />
+
+ Submit
+
+
+ ) : (
+
+
+
+ Continue
+
+
+ )}
+
+
+
+ {/* Footer */}
+
+ {isEmailStep ? (
+
+
+ Back to Sign In
+
+ ) : (
+
+
+ Didn't you receive any code?
+
+
+ Resend Code
+
+
+ )}
+
+
+
+ >
+ )}
+
+ );
+}
diff --git a/src/components/auth/index.ts b/src/components/auth/index.ts
new file mode 100644
index 0000000..0bda060
--- /dev/null
+++ b/src/components/auth/index.ts
@@ -0,0 +1,12 @@
+/**
+ * Auth Components Barrel Export
+ * @description Exports all authentication-related components.
+ * Follows AgenticIQ Enterprise Coding Guidelines v1.0
+ */
+
+export { AuthCard, AuthCardHeader, AuthCardContent } from './auth-card';
+export { AuthInput } from './auth-input';
+export { AuthButton, SocialButton, TextButton, GoogleIcon, AzureIcon } from './auth-button';
+export { AuthFormCard } from './auth-form-card';
+export { ForgotPasswordModal } from './forgot-password-modal';
+
diff --git a/src/pages/login-page.tsx b/src/pages/login-page.tsx
new file mode 100644
index 0000000..14e024e
--- /dev/null
+++ b/src/pages/login-page.tsx
@@ -0,0 +1,190 @@
+/**
+ * Login Page Component
+ * @description Main authentication page with 2-column responsive layout.
+ * Left column displays branding/marketing content, right column contains auth form.
+ * Supports both Sign In and Register modes with animated transitions.
+ * Includes Forgot Password modal with OTP verification.
+ * Follows AgenticIQ Enterprise Coding Guidelines v1.0
+ */
+
+import { useState } from 'react';
+import agenticiqLogo from '@/assets/images/logo/AgenticIQLogo.svg';
+import topRightGlow from '@/assets/images/backgrounds/top-right-glow.svg';
+import bottomLeftWave1 from '@/assets/images/backgrounds/bottom-left-wave1 .svg';
+import bottomLeftWave2 from '@/assets/images/backgrounds/bottom-left-wave2.svg';
+import logoGlowBg from '@/assets/images/backgrounds/logo-glow-bg.svg';
+import { AuthFormCard, ForgotPasswordModal } from '@/components/auth';
+
+/**
+ * LoginPage component
+ * @description Full-page login layout with responsive 2-column grid structure.
+ * Mobile-first design that stacks columns on smaller screens.
+ * @returns {JSX.Element} LoginPage element
+ */
+export function LoginPage(): JSX.Element {
+ const [showForgotPwd, setShowForgotPwd] = useState(false);
+
+ const handleSignIn = (email: string, password: string): void => {
+ console.log('Sign in:', { email, password });
+ };
+
+ const handleRegister = (data: {
+ firstName: string;
+ lastName: string;
+ email: string;
+ password: string;
+ }): void => {
+ console.log('Register:', data);
+ };
+
+ const handleGoogleAuth = (): void => {
+ console.log('Google auth clicked');
+ };
+
+ const handleAzureAuth = (): void => {
+ console.log('Azure auth clicked');
+ };
+
+ const handleForgotPasswordClick = (): void => {
+ setShowForgotPwd(true);
+ };
+
+ const handleForgotPasswordClose = (): void => {
+ setShowForgotPwd(false);
+ };
+
+ const handleForgotPasswordSubmit = (email: string): void => {
+ console.log('Password recovery requested for:', email);
+ };
+
+ const handleOtpVerify = (otp: string): void => {
+ console.log('OTP verification:', otp);
+ };
+
+ return (
+
+
+ {/* Decorative Background Elements */}
+
+
+ {/* AgenticIQ Logo */}
+
+
+
+
+ {/* Left Side Text Content */}
+
+
+ {/* Main Content Grid */}
+
+ {/* Left Column - Branding/Marketing Content */}
+
+
+ {/* Right Column - Auth Form Card */}
+
+
+
+
+ {/* Forgot Password Modal */}
+
+
+ );
+}
+
+/**
+ * BackgroundDecorations component
+ * @description Renders decorative background images matching Figma design.
+ * @returns {JSX.Element} Background decoration elements
+ */
+function BackgroundDecorations(): JSX.Element {
+ return (
+
+ {/* Logo glow background */}
+
+
+ {/* Top-right glow decoration */}
+
+
+ {/* Bottom-left wave decoration 1 */}
+
+
+ {/* Bottom-left wave decoration 2 */}
+
+
+ );
+}
+
+/**
+ * LeftColumnText component
+ * @description Left side text content (heading and description).
+ * @returns {JSX.Element} Text elements positioned as per Figma
+ */
+function LeftColumnText(): JSX.Element {
+ return (
+ <>
+
+ Engineering the Future with Intelligent Agents
+
+
+ Deploy intelligent agents that automate complex workflows, enhance decision-making, and scale your operations. Built for enterprise reliability with seamless integration capabilities.
+
+ >
+ );
+}
+
+/**
+ * LeftColumn component
+ * @description Empty container for left side content.
+ * @returns {JSX.Element} Left column container
+ */
+function LeftColumn(): JSX.Element {
+ return (
+
+ {/* Text content is positioned absolutely on page level */}
+
+ );
+}
diff --git a/src/pages/sign-in.tsx b/src/pages/sign-in.tsx
deleted file mode 100644
index 86eb94d..0000000
--- a/src/pages/sign-in.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Sign In Page
- * @description Basic sign-in form for existing users.
- */
-
-import { Link } from '@tanstack/react-router';
-
-export function SignInPage() {
- return (
-
-
-
-
-
Welcome back
-
Sign in to continue to your dashboard.
-
-
-
-
-
- New here?{' '}
-
- Create an account
-
-
-
-
- );
-}
-
diff --git a/src/routes.tsx b/src/routes.tsx
index a03eb0d..2bf20b3 100644
--- a/src/routes.tsx
+++ b/src/routes.tsx
@@ -8,8 +8,8 @@ import { RootLayout } from '@/components/layout';
import { AgentPage } from '@/pages/agent';
import { AgentCreatePage } from '@/pages/agent-create';
import { Dashboard } from '@/pages/dashboard';
-import { SignInPage } from '@/pages/sign-in';
import { SignUpPage } from '@/pages/sign-up';
+import { LoginPage } from '@/pages/login-page';
export const APP_PATHS = {
signIn: '/',
@@ -39,10 +39,10 @@ const appRoute = createRoute({
),
});
-const signInRoute = createRoute({
+const loginRoute = createRoute({
getParentRoute: () => publicRoute,
- path: APP_PATHS.signIn,
- component: SignInPage,
+ path: '/',
+ component: LoginPage,
});
const signUpRoute = createRoute({
@@ -83,9 +83,8 @@ const notFoundRoute = createRoute({
});
const routeTree = rootRoute.addChildren([
- publicRoute.addChildren([signInRoute, signUpRoute]),
- appRoute.addChildren([dashboardRoute, agentRoute, agentCreateRoute]),
- notFoundRoute,
+ publicRoute.addChildren([loginRoute, signUpRoute]),
+ appRoute.addChildren([dashboardRoute,agentRoute,agentCreateRoute,notFoundRoute]),
]);
export const router = createRouter({
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
new file mode 100644
index 0000000..8d6a9c5
--- /dev/null
+++ b/src/vite-env.d.ts
@@ -0,0 +1,14 @@
+///
+
+/**
+ * SVG Module Declaration
+ * @description Allows importing SVG files as modules in TypeScript.
+ * Supports both default export (URL string) and ReactComponent export.
+ */
+declare module '*.svg' {
+ import React = require('react');
+ export const ReactComponent: React.FC>;
+ const src: string;
+ export default src;
+}
+
diff --git a/tsconfig.app.json b/tsconfig.app.json
index 9a5e0a3..1f88941 100644
--- a/tsconfig.app.json
+++ b/tsconfig.app.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "incremental": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,
@@ -24,9 +25,7 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
- "erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
- "noUncheckedSideEffectImports": true,
/* Path Aliases */
"baseUrl": ".",
"paths": {