feat: Cập nhật giao diện các trang xác thực với nền vũ trụ và hiệu ứng kínhmorphism, cải thiện trải nghiệm người dùng và thêm chức năng hiển thị mật khẩu cho trường nhập liệu.

This commit is contained in:
Ho Ngoc Hai
2026-01-04 23:23:08 +07:00
parent 2e26f71e39
commit d678d3aa8d
4 changed files with 464 additions and 349 deletions

View File

@@ -15,7 +15,7 @@
'use client';
import React from 'react';
import React, { useState } from 'react';
import {
TextField as AriaTextField,
Label,
@@ -24,6 +24,8 @@ import {
type TextFieldProps as AriaTextFieldProps,
} from 'react-aria-components';
import { cn } from '@/shared/utils';
import { Eye, EyeOff } from 'lucide-react';
import { Button } from '../button/button';
export interface InputProps extends Omit<AriaTextFieldProps, 'children'> {
/**
@@ -130,6 +132,35 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
},
ref
) => {
// EN: Internal state for password visibility
// VI: State nội bộ cho việc hiển thị mật khẩu
const [showPassword, setShowPassword] = useState(false);
// EN: Determine the actual input type
// VI: Xác định type thực tế của input
const inputType = type === 'password' && showPassword ? 'text' : type;
// EN: Determine the right element for password toggle
// VI: Xác định element bên phải cho nút gạt mật khẩu
const finalRightElement =
type === 'password' ? (
<Button
variant="ghost"
size="sm"
className="h-8 w-8 p-0 hover:bg-white/10 text-text-tertiary"
onPress={() => setShowPassword(!showPassword)}
aria-label={showPassword ? 'Hide password' : 'Show password'}
>
{showPassword ? (
<EyeOff className="h-4 w-4" />
) : (
<Eye className="h-4 w-4" />
)}
</Button>
) : (
rightElement
);
return (
<AriaTextField
className={cn('group flex flex-col gap-1.5', className)}
@@ -160,7 +191,7 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
<AriaInput
ref={ref}
type={type}
type={inputType}
placeholder={placeholder}
className={cn(
// Base glass input styles
@@ -185,15 +216,15 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
leftElement && 'pl-10',
// Right element padding
rightElement && 'pr-10',
finalRightElement && 'pr-10',
inputClassName
)}
/>
{rightElement && (
{finalRightElement && (
<div className="absolute right-3 flex items-center text-text-tertiary">
{rightElement}
{finalRightElement}
</div>
)}
</div>