Added eye/eye-off icon toggle for password field

This commit is contained in:
Arunavo Ray
2025-08-28 14:55:42 +05:30
parent 29a08ee3e3
commit d9bfc59a2d
3 changed files with 97 additions and 36 deletions

View File

@@ -11,11 +11,12 @@ import { authClient } from '@/lib/auth-client';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { toast, Toaster } from 'sonner'; import { toast, Toaster } from 'sonner';
import { showErrorToast } from '@/lib/utils'; import { showErrorToast } from '@/lib/utils';
import { Loader2, Mail, Globe } from 'lucide-react'; import { Loader2, Mail, Globe, Eye, EyeOff } from 'lucide-react';
export function LoginForm() { export function LoginForm() {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const [ssoEmail, setSsoEmail] = useState(''); const [ssoEmail, setSsoEmail] = useState('');
const { login } = useAuth(); const { login } = useAuth();
const { authMethods, isLoading: isLoadingMethods } = useAuthMethods(); const { authMethods, isLoading: isLoadingMethods } = useAuthMethods();
@@ -139,15 +140,29 @@ export function LoginForm() {
<label htmlFor="password" className="block text-sm font-medium mb-1"> <label htmlFor="password" className="block text-sm font-medium mb-1">
Password Password
</label> </label>
<input <div className="relative">
id="password" <input
name="password" id="password"
type="password" name="password"
required type={showPassword ? "text" : "password"}
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" required
placeholder="Enter your password" className="w-full rounded-md border border-input bg-background px-3 py-2 pr-10 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
disabled={isLoading} placeholder="Enter your password"
/> disabled={isLoading}
/>
<button
type="button"
className="absolute inset-y-0 right-0 flex items-center pr-3"
onClick={() => setShowPassword(!showPassword)}
tabIndex={-1}
>
{showPassword ? (
<EyeOff className="h-4 w-4 text-muted-foreground hover:text-foreground transition-colors" />
) : (
<Eye className="h-4 w-4 text-muted-foreground hover:text-foreground transition-colors" />
)}
</button>
</div>
</div> </div>
</div> </div>
</form> </form>

View File

@@ -6,9 +6,12 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
import { toast, Toaster } from 'sonner'; import { toast, Toaster } from 'sonner';
import { showErrorToast } from '@/lib/utils'; import { showErrorToast } from '@/lib/utils';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { Eye, EyeOff } from 'lucide-react';
export function SignupForm() { export function SignupForm() {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const { register } = useAuth(); const { register } = useAuth();
async function handleSignup(e: React.FormEvent<HTMLFormElement>) { async function handleSignup(e: React.FormEvent<HTMLFormElement>) {
@@ -86,29 +89,57 @@ export function SignupForm() {
<label htmlFor="password" className="block text-sm font-medium mb-1"> <label htmlFor="password" className="block text-sm font-medium mb-1">
Password Password
</label> </label>
<input <div className="relative">
id="password" <input
name="password" id="password"
type="password" name="password"
required type={showPassword ? "text" : "password"}
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" required
placeholder="Create a password" className="w-full rounded-md border border-input bg-background px-3 py-2 pr-10 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
disabled={isLoading} placeholder="Create a password"
/> disabled={isLoading}
/>
<button
type="button"
className="absolute inset-y-0 right-0 flex items-center pr-3"
onClick={() => setShowPassword(!showPassword)}
tabIndex={-1}
>
{showPassword ? (
<EyeOff className="h-4 w-4 text-muted-foreground hover:text-foreground transition-colors" />
) : (
<Eye className="h-4 w-4 text-muted-foreground hover:text-foreground transition-colors" />
)}
</button>
</div>
</div> </div>
<div> <div>
<label htmlFor="confirmPassword" className="block text-sm font-medium mb-1"> <label htmlFor="confirmPassword" className="block text-sm font-medium mb-1">
Confirm Password Confirm Password
</label> </label>
<input <div className="relative">
id="confirmPassword" <input
name="confirmPassword" id="confirmPassword"
type="password" name="confirmPassword"
required type={showConfirmPassword ? "text" : "password"}
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" required
placeholder="Confirm your password" className="w-full rounded-md border border-input bg-background px-3 py-2 pr-10 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
disabled={isLoading} placeholder="Confirm your password"
/> disabled={isLoading}
/>
<button
type="button"
className="absolute inset-y-0 right-0 flex items-center pr-3"
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
tabIndex={-1}
>
{showConfirmPassword ? (
<EyeOff className="h-4 w-4 text-muted-foreground hover:text-foreground transition-colors" />
) : (
<Eye className="h-4 w-4 text-muted-foreground hover:text-foreground transition-colors" />
)}
</button>
</div>
</div> </div>
</div> </div>
</form> </form>

View File

@@ -2,6 +2,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import type { MirrorJob } from "@/lib/db/schema"; import type { MirrorJob } from "@/lib/db/schema";
import { formatDate, getStatusColor } from "@/lib/utils"; import { formatDate, getStatusColor } from "@/lib/utils";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
import { Activity, Clock } from "lucide-react";
interface RecentActivityProps { interface RecentActivityProps {
activities: MirrorJob[]; activities: MirrorJob[];
@@ -17,11 +18,25 @@ export function RecentActivity({ activities }: RecentActivityProps) {
</Button> </Button>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="flex flex-col divide-y divide-border"> {activities.length === 0 ? (
{activities.length === 0 ? ( <div className="flex flex-col items-center justify-center py-6 text-center">
<p className="text-sm text-muted-foreground">No recent activity</p> <Clock className="h-10 w-10 text-muted-foreground mb-4" />
) : ( <h3 className="text-lg font-medium">No recent activity</h3>
activities.map((activity, index) => ( <p className="text-sm text-muted-foreground mt-1 mb-4">
Activity will appear here when you start mirroring repositories.
</p>
<div className="flex gap-2">
<Button variant="outline" size="sm" asChild>
<a href="/activity">
<Activity className="h-3.5 w-3.5 mr-1.5" />
View History
</a>
</Button>
</div>
</div>
) : (
<div className="flex flex-col divide-y divide-border">
{activities.map((activity, index) => (
<div key={index} className="flex items-center gap-x-3 py-3.5"> <div key={index} className="flex items-center gap-x-3 py-3.5">
<div className="relative flex-shrink-0"> <div className="relative flex-shrink-0">
<div <div
@@ -39,9 +54,9 @@ export function RecentActivity({ activities }: RecentActivityProps) {
</div> </div>
</div> </div>
</div> </div>
)) ))}
)} </div>
</div> )}
</CardContent> </CardContent>
</Card> </Card>
); );