AgentIQ_Frontend/src/components/auth/auth-button.tsx
SanaullasAzaan ab3bf2038b feat: improve responsiveness and refactor auth components
- 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
2025-12-24 11:02:55 +05:30

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>
);
}