- Fix responsiveness at md (768px) and lg (1024px) breakpoints across all pages - Reduce forgot-password-modal.tsx from 472 to 319 lines by extracting components - Extract OTPInput and modal icons into separate files for better code organization - Optimize card sizes and text scaling for lg (1024px) breakpoint - Adjust login page layout: smaller card and reduced text sizes at lg breakpoint - Improve responsive typography, spacing, and touch targets across all components - Update all pages (login, sign-up, dashboard) with proper mobile-first responsive design
221 lines
7.1 KiB
TypeScript
221 lines
7.1 KiB
TypeScript
/**
|
|
* 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<HTMLButtonElement> {
|
|
/** Button content */
|
|
children: ReactNode;
|
|
/** Loading state */
|
|
isLoading?: boolean;
|
|
/** Full width button */
|
|
fullWidth?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Props for SocialButton component
|
|
*/
|
|
interface SocialButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
/** Button text */
|
|
children: ReactNode;
|
|
/** Icon element to show before text */
|
|
icon: ReactNode;
|
|
}
|
|
|
|
/**
|
|
* Props for TextButton component
|
|
*/
|
|
interface TextButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
/** Button text */
|
|
children: ReactNode;
|
|
}
|
|
|
|
/**
|
|
* Google icon for social login
|
|
* @returns {JSX.Element} Google SVG icon
|
|
*/
|
|
export function GoogleIcon(): JSX.Element {
|
|
return (
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path
|
|
d="M22.56 12.25C22.56 11.47 22.49 10.72 22.36 10H12V14.26H17.92C17.66 15.63 16.88 16.79 15.71 17.57V20.34H19.28C21.36 18.42 22.56 15.6 22.56 12.25Z"
|
|
fill="#4285F4"
|
|
/>
|
|
<path
|
|
d="M12 23C14.97 23 17.46 22.02 19.28 20.34L15.71 17.57C14.73 18.23 13.48 18.63 12 18.63C9.13999 18.63 6.70999 16.7 5.83999 14.1H2.17999V16.94C3.98999 20.53 7.69999 23 12 23Z"
|
|
fill="#34A853"
|
|
/>
|
|
<path
|
|
d="M5.84 14.1C5.62 13.44 5.49 12.73 5.49 12C5.49 11.27 5.62 10.56 5.84 9.9V7.06H2.18C1.43 8.55 1 10.22 1 12C1 13.78 1.43 15.45 2.18 16.94L5.84 14.1Z"
|
|
fill="#FBBC05"
|
|
/>
|
|
<path
|
|
d="M12 5.38C13.62 5.38 15.06 5.94 16.21 7.02L19.36 3.87C17.45 2.09 14.97 1 12 1C7.69999 1 3.98999 3.47 2.17999 7.06L5.83999 9.9C6.70999 7.3 9.13999 5.38 12 5.38Z"
|
|
fill="#EA4335"
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Azure icon for social login
|
|
* @returns {JSX.Element} Azure SVG icon
|
|
*/
|
|
export function AzureIcon(): JSX.Element {
|
|
return (
|
|
<svg width="23" height="23" viewBox="0 0 23 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M0 11.5L7.667 2.875L14.375 0L14.833 11.5L7.667 20.125L0 11.5Z" fill="#0078D4" />
|
|
<path d="M8.625 8.625L14.375 0L23 5.75V17.25L14.375 23L8.625 8.625Z" fill="#0078D4" />
|
|
<path d="M8.625 8.625L14.375 11.5L14.375 23L8.625 8.625Z" fill="#0050A4" />
|
|
<path d="M14.375 11.5L23 5.75V17.25L14.375 11.5Z" fill="#0050A4" />
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 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 (
|
|
<button
|
|
type="submit"
|
|
disabled={disabled || isLoading}
|
|
className={`
|
|
flex items-center justify-center
|
|
min-h-[44px] h-11 md:h-[52px]
|
|
px-4 md:px-[18px] py-2.5 md:py-[13px]
|
|
bg-[#00E2E0]
|
|
border border-[rgba(255,255,255,0.2)]
|
|
rounded-lg md:rounded-[12px]
|
|
shadow-[0px_1px_2px_0px_rgba(16,24,40,0.05)]
|
|
text-sm md:text-base md:text-[16px] font-semibold leading-5 md:leading-6 text-black
|
|
cursor-pointer
|
|
hover:bg-[#00D4D2]
|
|
active:bg-[#00C6C4]
|
|
disabled:opacity-50 disabled:cursor-not-allowed
|
|
transition-colors duration-150
|
|
${fullWidth ? 'w-full' : ''}
|
|
${className}
|
|
`}
|
|
{...buttonProps}
|
|
>
|
|
{isLoading ? (
|
|
<span className="flex items-center gap-2">
|
|
<svg
|
|
className="animate-spin h-5 w-5"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<circle
|
|
className="opacity-25"
|
|
cx="12"
|
|
cy="12"
|
|
r="10"
|
|
stroke="currentColor"
|
|
strokeWidth="4"
|
|
/>
|
|
<path
|
|
className="opacity-75"
|
|
fill="currentColor"
|
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
/>
|
|
</svg>
|
|
Loading...
|
|
</span>
|
|
) : (
|
|
children
|
|
)}
|
|
</button>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 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 (
|
|
<button
|
|
type="button"
|
|
className={`
|
|
flex items-center justify-center gap-2 md:gap-3
|
|
px-3 md:px-4 py-2 md:py-2.5
|
|
bg-white
|
|
rounded-lg md:rounded-xl
|
|
shadow-[0px_1px_2px_0px_rgba(16,24,40,0.05)]
|
|
text-xs md:text-sm font-semibold leading-5 md:leading-6 text-black
|
|
cursor-pointer
|
|
hover:bg-gray-50
|
|
active:bg-gray-100
|
|
transition-colors duration-200
|
|
min-h-[44px]
|
|
${className}
|
|
`}
|
|
{...buttonProps}
|
|
>
|
|
<span className="shrink-0 w-6 h-6 flex items-center justify-center">
|
|
{icon}
|
|
</span>
|
|
{children}
|
|
</button>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 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 (
|
|
<button
|
|
type="button"
|
|
className={`
|
|
text-sm font-medium leading-5
|
|
text-[rgba(255,255,255,0.75)]
|
|
cursor-pointer
|
|
hover:text-white
|
|
hover:underline
|
|
transition-colors duration-200
|
|
${className}
|
|
`}
|
|
{...buttonProps}
|
|
>
|
|
{children}
|
|
</button>
|
|
);
|
|
}
|
|
|