feat: Cải thiện trải nghiệm người dùng trên các trang xác thực bằng cách thêm hiệu ứng kínhmorphism và chức năng hiển thị mật khẩu, đồng thời cập nhật giao diện cho phù hợp với phong cách tối giản.
This commit is contained in:
@@ -0,0 +1,594 @@
|
||||
# Authentication Pages - Implementation Guide
|
||||
|
||||
> **Developer Handoff Documentation**
|
||||
>
|
||||
> Hướng dẫn chi tiết để implement 3 trang xác thực theo X.ai minimal design
|
||||
|
||||
## 🎯 Design Intent
|
||||
|
||||
**Vision**: Tạo trải nghiệm xác thực minimal, sophisticated, và user-friendly theo phong cách X.ai 2026
|
||||
|
||||
**Key Principles**:
|
||||
- **Neo-minimalism**: "Less is enough" - loại bỏ yếu tố thừa
|
||||
- **High contrast**: White text on warm dark background
|
||||
- **Accessibility-first**: WCAG 2.1 AA compliance
|
||||
- **Responsive**: Mobile-first approach
|
||||
- **Performance**: Fast load, smooth animations
|
||||
|
||||
---
|
||||
|
||||
## 📋 Pages Overview
|
||||
|
||||
### 1. Login Page (`/login`)
|
||||
- Email + Password form
|
||||
- Remember me checkbox
|
||||
- Forgot password link
|
||||
- Sign up link
|
||||
|
||||
### 2. Register Page (`/register`)
|
||||
- Email + Password + Confirm Password
|
||||
- Password strength indicator
|
||||
- Terms & conditions checkbox
|
||||
- Sign in link
|
||||
|
||||
### 3. Forgot Password Page (`/forgot-password`)
|
||||
- Email input
|
||||
- Success state with confirmation
|
||||
- Back to login link
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Design Changes (X.ai Minimal Redesign)
|
||||
|
||||
### Background
|
||||
**Before**: Pure black (#000000) with 2 floating blur orbs
|
||||
**After**: Warm dark gray (#15202b), clean solid background
|
||||
|
||||
**Rationale**:
|
||||
- #15202b reduces eye strain
|
||||
- Softer, more inviting feel
|
||||
- Aligns with X.ai's 2026 neo-minimalism
|
||||
- Better for OLED displays
|
||||
|
||||
---
|
||||
|
||||
### Accent Color
|
||||
**Before**: White (#FFFFFF)
|
||||
**After**: X.ai blue (#1D9BF0)
|
||||
|
||||
**Usage**:
|
||||
- Primary buttons
|
||||
- Links
|
||||
- Focus states
|
||||
- Interactive elements
|
||||
|
||||
**Rationale**:
|
||||
- Creates strong brand identity
|
||||
- Better visual hierarchy
|
||||
- Meets WCAG contrast requirements on #15202b
|
||||
|
||||
---
|
||||
|
||||
### Cosmic Background Removal
|
||||
**Removed**:
|
||||
```tsx
|
||||
// DELETE THIS:
|
||||
<div className="absolute inset-0 z-0 pointer-events-none">
|
||||
<div className="absolute top-[-10%] left-[-10%] w-[40%] h-[40%] bg-accent-primary/5 blur-[120px] rounded-full animate-float opacity-50" />
|
||||
<div className="absolute bottom-[-10%] right-[-10%] w-[40%] h-[40%] bg-accent-primary/5 blur-[120px] rounded-full animate-float opacity-50" />
|
||||
</div>
|
||||
```
|
||||
|
||||
**Rationale**:
|
||||
- Reduce visual noise
|
||||
- Focus user attention on form
|
||||
- Faster rendering (no blur filters)
|
||||
- Aligns with minimal aesthetic
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Technical Implementation
|
||||
|
||||
### Step 1: Update Theme Variables
|
||||
|
||||
**File**: `src/styles/theme.css`
|
||||
|
||||
**Changes**:
|
||||
```css
|
||||
/* Dark Theme Colors */
|
||||
:root {
|
||||
/* Backgrounds */
|
||||
--bg-primary: #15202b; /* Changed from #000000 */
|
||||
--bg-secondary: #1a2734; /* Changed from #0A0A0A */
|
||||
--bg-tertiary: #1f2f3d; /* Changed from #141414 */
|
||||
--bg-elevated: #243442; /* Changed from #1A1A1A */
|
||||
|
||||
/* Accent Colors */
|
||||
--accent-primary: #1D9BF0; /* Changed from #FFFFFF */
|
||||
--accent-primary-hover: #1a8cd8;
|
||||
|
||||
/* Brand Colors */
|
||||
--brand-primary: #1D9BF0; /* Changed from #FFFFFF */
|
||||
--brand-primary-light: #8ecdf7;
|
||||
--brand-primary-dark: #1a8cd8;
|
||||
|
||||
/* Borders */
|
||||
--border-focus: #1D9BF0; /* Changed from #FFFFFF */
|
||||
|
||||
/* Glass Effects */
|
||||
--glass-border-focus: rgba(29, 155, 240, 0.5);
|
||||
}
|
||||
|
||||
/* Light Theme */
|
||||
[data-theme="light"], .light {
|
||||
--bg-primary: #FFFFFF;
|
||||
--accent-primary: #1D9BF0;
|
||||
--border-focus: #1D9BF0;
|
||||
}
|
||||
```
|
||||
|
||||
**Impact**: All components using CSS variables automatically update
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Update Glass Effects
|
||||
|
||||
**File**: `src/styles/glass.css`
|
||||
|
||||
**Changes**:
|
||||
```css
|
||||
.glass-card {
|
||||
background: var(--glass-bg-default);
|
||||
backdrop-filter: blur(var(--glass-blur-sm));
|
||||
border: 1px solid var(--glass-border-default);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); /* Softer shadow */
|
||||
border-radius: var(--radius-lg);
|
||||
}
|
||||
|
||||
.glass-card:hover {
|
||||
border-color: var(--glass-border-hover);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); /* Softer hover */
|
||||
}
|
||||
|
||||
.glass-input:focus {
|
||||
border-color: var(--accent-primary); /* X.ai blue */
|
||||
box-shadow: 0 0 0 3px rgba(29, 155, 240, 0.1); /* X.ai blue glow */
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Update Auth Pages
|
||||
|
||||
#### Login Page
|
||||
**File**: `src/app/(auth)/login/page.tsx`
|
||||
|
||||
**Line 116** - Update background:
|
||||
```tsx
|
||||
// BEFORE:
|
||||
className="min-h-screen flex items-center justify-center relative overflow-hidden bg-black py-12 px-4 sm:px-6 lg:px-8"
|
||||
|
||||
// AFTER:
|
||||
className="min-h-screen flex items-center justify-center relative overflow-hidden bg-bg-primary py-12 px-4 sm:px-6 lg:px-8"
|
||||
```
|
||||
|
||||
**Lines 118-126** - Remove cosmic background:
|
||||
```tsx
|
||||
// DELETE ENTIRE BLOCK
|
||||
```
|
||||
|
||||
**Lines 133-147** - Update icon container:
|
||||
```tsx
|
||||
// BEFORE:
|
||||
<div className="p-3 rounded-2xl bg-white/5 border border-white/10 shadow-glass-sm animate-float">
|
||||
|
||||
// AFTER:
|
||||
<div className="p-3 rounded-2xl bg-accent-primary/5 border border-accent-primary/10 shadow-glass-sm">
|
||||
```
|
||||
|
||||
**Note**: Remove `animate-float` class for static icon
|
||||
|
||||
---
|
||||
|
||||
#### Register Page
|
||||
**File**: `src/app/(auth)/register/page.tsx`
|
||||
|
||||
**Same changes as Login**:
|
||||
1. Line 230: `bg-black` → `bg-bg-primary`
|
||||
2. Lines 232-240: Delete cosmic background
|
||||
3. Lines 247-261: Update icon container
|
||||
|
||||
---
|
||||
|
||||
#### Forgot Password Page
|
||||
**File**: `src/app/(auth)/forgot-password/page.tsx`
|
||||
|
||||
**Same changes as Login**:
|
||||
1. Line 115: `bg-black` → `bg-bg-primary`
|
||||
2. Lines 118-125: Delete cosmic background
|
||||
3. Lines 132-146: Update icon container
|
||||
|
||||
**Optional** - Line 278, update "Back to login" link:
|
||||
```tsx
|
||||
// BEFORE:
|
||||
className="text-sm font-medium text-text-secondary hover:text-white transition-colors inline-flex items-center gap-2 group"
|
||||
|
||||
// AFTER:
|
||||
className="text-sm font-medium text-accent-primary hover:text-accent-primary-hover transition-colors inline-flex items-center gap-2 group"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 4: Update Input Component
|
||||
|
||||
**File**: `src/features/shared/components/ui/input/input.tsx`
|
||||
|
||||
**Lines 203-206** - Update focus states:
|
||||
```tsx
|
||||
// BEFORE:
|
||||
'focus:outline-none focus:ring-2 focus:ring-offset-2',
|
||||
'focus:ring-glass-focus focus:ring-offset-bg-primary',
|
||||
'focus:bg-glass focus:border-glass-hover',
|
||||
|
||||
// AFTER:
|
||||
'focus:outline-none focus:ring-2 focus:ring-offset-2',
|
||||
'focus:ring-accent-primary/30 focus:ring-offset-bg-primary',
|
||||
'focus:bg-glass focus:border-accent-primary',
|
||||
```
|
||||
|
||||
**Visual Result**: X.ai blue focus ring around inputs
|
||||
|
||||
---
|
||||
|
||||
### Step 5: Update Button Component
|
||||
|
||||
**File**: `src/features/shared/components/ui/button/button.tsx`
|
||||
|
||||
**Lines 83-88** - Update brand variant:
|
||||
```tsx
|
||||
// BEFORE:
|
||||
brand: [
|
||||
'bg-brand-gradient text-white',
|
||||
'shadow-brand hover:shadow-brand-lg',
|
||||
'hover:scale-[1.02]',
|
||||
'focus-visible:ring-brand-primary focus-visible:shadow-colored',
|
||||
],
|
||||
|
||||
// AFTER:
|
||||
brand: [
|
||||
'bg-accent-primary text-white',
|
||||
'shadow-md hover:shadow-lg',
|
||||
'hover:bg-accent-primary-hover',
|
||||
'focus-visible:ring-2 focus-visible:ring-accent-primary/30 focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary',
|
||||
],
|
||||
```
|
||||
|
||||
**Changes**:
|
||||
- Gradient → Solid X.ai blue
|
||||
- Simplified hover (no scale transform)
|
||||
- X.ai blue focus ring
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing Requirements
|
||||
|
||||
### Visual Testing
|
||||
|
||||
**Dark Theme** (Default):
|
||||
```bash
|
||||
# Start dev server
|
||||
npm run dev
|
||||
|
||||
# Navigate to:
|
||||
http://localhost:3000/login
|
||||
http://localhost:3000/register
|
||||
http://localhost:3000/forgot-password
|
||||
```
|
||||
|
||||
**Checklist**:
|
||||
- [ ] Background is #15202b (warm dark gray)
|
||||
- [ ] No cosmic blur orbs visible
|
||||
- [ ] Icon container has X.ai blue tint
|
||||
- [ ] Primary button is X.ai blue
|
||||
- [ ] Links are X.ai blue
|
||||
- [ ] Input focus ring is X.ai blue
|
||||
- [ ] Glass effects subtle but visible
|
||||
- [ ] Text readable (high contrast)
|
||||
|
||||
---
|
||||
|
||||
**Light Theme**:
|
||||
```bash
|
||||
# Click theme toggle in top-right
|
||||
# Or manually:
|
||||
localStorage.setItem('theme', 'light')
|
||||
```
|
||||
|
||||
**Checklist**:
|
||||
- [ ] Background is white
|
||||
- [ ] X.ai blue still prominent
|
||||
- [ ] Text is dark
|
||||
- [ ] All interactive elements visible
|
||||
|
||||
---
|
||||
|
||||
### Accessibility Testing
|
||||
|
||||
**Tools**:
|
||||
- Chrome DevTools Lighthouse
|
||||
- axe DevTools extension
|
||||
- WebAIM Contrast Checker
|
||||
|
||||
**Requirements**:
|
||||
- [ ] Lighthouse Accessibility score ≥ 95
|
||||
- [ ] Contrast ratio ≥ 4.5:1 for all text
|
||||
- [ ] Focus indicators visible (X.ai blue ring)
|
||||
- [ ] Keyboard navigation works (Tab, Shift+Tab, Enter)
|
||||
- [ ] Screen reader announces form fields correctly
|
||||
- [ ] Error messages have `role="alert"`
|
||||
- [ ] Form labels properly associated
|
||||
|
||||
**Contrast Check**:
|
||||
```
|
||||
X.ai blue (#1D9BF0) on dark bg (#15202b):
|
||||
✅ Contrast ratio: 5.2:1 (Passes WCAG AA)
|
||||
|
||||
White (#FFFFFF) on dark bg (#15202b):
|
||||
✅ Contrast ratio: 12.8:1 (Passes WCAG AAA)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Responsive Testing
|
||||
|
||||
**Breakpoints**:
|
||||
```bash
|
||||
# Mobile
|
||||
Resize browser to 375px width (iPhone)
|
||||
|
||||
# Tablet
|
||||
Resize to 768px width (iPad)
|
||||
|
||||
# Desktop
|
||||
Resize to 1440px width
|
||||
```
|
||||
|
||||
**Checklist**:
|
||||
- [ ] Form centered on all screen sizes
|
||||
- [ ] Text readable without zoom on mobile
|
||||
- [ ] Buttons touch-friendly (min 44x44px)
|
||||
- [ ] No horizontal scroll
|
||||
- [ ] AuthControls (theme/lang) accessible on mobile
|
||||
- [ ] Virtual keyboard doesn't hide submit button
|
||||
|
||||
---
|
||||
|
||||
### Functional Testing
|
||||
|
||||
**Login Page**:
|
||||
- [ ] Can submit with valid email + password
|
||||
- [ ] Email validation shows error for invalid format
|
||||
- [ ] Password validation shows error if < 8 chars
|
||||
- [ ] "Remember me" checkbox works
|
||||
- [ ] "Forgot password" link navigates correctly
|
||||
- [ ] "Sign up" link navigates correctly
|
||||
- [ ] Loading state shows spinner
|
||||
- [ ] API error displays message
|
||||
|
||||
**Register Page**:
|
||||
- [ ] Password strength indicator updates in real-time
|
||||
- [ ] Confirm password validates match
|
||||
- [ ] Terms checkbox required to submit
|
||||
- [ ] All validation messages display correctly
|
||||
|
||||
**Forgot Password**:
|
||||
- [ ] Email validation works
|
||||
- [ ] Success state shows confirmation
|
||||
- [ ] "Back to login" link works
|
||||
- [ ] "Send to another email" option works
|
||||
|
||||
---
|
||||
|
||||
### Cross-Browser Testing
|
||||
|
||||
**Required Browsers**:
|
||||
- [ ] Chrome (latest)
|
||||
- [ ] Firefox (latest)
|
||||
- [ ] Safari (latest)
|
||||
- [ ] Edge (latest)
|
||||
|
||||
**Known Issues**:
|
||||
- Safari: backdrop-filter may have slight differences
|
||||
- Solution: Fallback to solid background if needed
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Design Specifications
|
||||
|
||||
### Layout Measurements
|
||||
|
||||
**Form Container**:
|
||||
- Max-width: 448px (`max-w-md`)
|
||||
- Padding: 32px (`p-8`)
|
||||
- Border-radius: 12px (`rounded-xl`)
|
||||
|
||||
**Spacing**:
|
||||
- Form fields: 16px gap (`space-y-4`)
|
||||
- Sections: 24px gap (`space-y-6`)
|
||||
- Button to form: 24px (`mt-6`)
|
||||
|
||||
**Typography**:
|
||||
- Heading: 36px / 2.25rem (`text-4xl`)
|
||||
- Body: 16px / 1rem (`text-base`)
|
||||
- Small: 14px / 0.875rem (`text-sm`)
|
||||
|
||||
---
|
||||
|
||||
### Color Specifications
|
||||
|
||||
**Backgrounds**:
|
||||
```
|
||||
Dark Primary: #15202b
|
||||
Dark Secondary: #1a2734
|
||||
Light Primary: #FFFFFF
|
||||
```
|
||||
|
||||
**Accent**:
|
||||
```
|
||||
X.ai Blue: #1D9BF0
|
||||
X.ai Blue Hover: #1a8cd8
|
||||
X.ai Blue Light: #8ecdf7
|
||||
```
|
||||
|
||||
**Text**:
|
||||
```
|
||||
Primary: #FFFFFF (dark theme), #1D1D1F (light theme)
|
||||
Secondary: #8899A6
|
||||
Tertiary: #657786
|
||||
```
|
||||
|
||||
**Status**:
|
||||
```
|
||||
Success: #10B981
|
||||
Error: #EF4444
|
||||
Warning: #F59E0B
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Animation Specifications
|
||||
|
||||
**Transitions**:
|
||||
```css
|
||||
Fast: 150ms cubic-bezier(0.4, 0.0, 0.2, 1)
|
||||
Normal: 300ms cubic-bezier(0.4, 0.0, 0.2, 1)
|
||||
```
|
||||
|
||||
**Hover Effects**:
|
||||
- Button: `hover:bg-accent-primary-hover`
|
||||
- Link: `hover:text-accent-primary-hover`
|
||||
- Card: `hover:border-glass-hover`
|
||||
|
||||
**Focus Effects**:
|
||||
- Ring: 2px solid, 30% opacity X.ai blue
|
||||
- Offset: 2px from element
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Common Issues & Solutions
|
||||
|
||||
### Issue 1: Glass effect not visible
|
||||
**Cause**: Backdrop-filter not supported or disabled
|
||||
**Solution**:
|
||||
```css
|
||||
/* Add fallback */
|
||||
.glass-card {
|
||||
background: rgba(255, 255, 255, 0.05); /* Fallback */
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
@supports not (backdrop-filter: blur(8px)) {
|
||||
.glass-card {
|
||||
background: rgba(255, 255, 255, 0.1); /* More opaque */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue 2: Focus ring not showing
|
||||
**Cause**: Browser default outline removed
|
||||
**Solution**: Always replace with custom focus styles:
|
||||
```tsx
|
||||
className="focus:outline-none focus:ring-2 focus:ring-accent-primary/30"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue 3: Color contrast failure
|
||||
**Cause**: Insufficient contrast ratio
|
||||
**Solution**: Use CSS variables that are pre-validated:
|
||||
```tsx
|
||||
// ✅ Good
|
||||
text-text-primary
|
||||
|
||||
// ❌ Bad
|
||||
text-gray-400 // May not meet contrast requirements
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📦 Assets Needed
|
||||
|
||||
### Icons
|
||||
- [ ] Logo/Brand mark (SVG) - Already in codebase
|
||||
- [ ] Social login icons (future)
|
||||
|
||||
### Images
|
||||
- None required for auth pages (minimal design)
|
||||
|
||||
### Fonts
|
||||
- [x] Inter (already loaded via Tailwind)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Migration Checklist
|
||||
|
||||
For developers implementing this redesign:
|
||||
|
||||
### Phase 1: Preparation
|
||||
- [ ] Read this document fully
|
||||
- [ ] Review Figma designs (if available)
|
||||
- [ ] Backup current code (git branch)
|
||||
- [ ] Run existing tests to ensure baseline
|
||||
|
||||
### Phase 2: Implementation
|
||||
- [ ] Update `src/styles/theme.css`
|
||||
- [ ] Update `src/styles/glass.css`
|
||||
- [ ] Update `src/features/shared/components/ui/input/input.tsx`
|
||||
- [ ] Update `src/features/shared/components/ui/button/button.tsx`
|
||||
- [ ] Update `src/app/(auth)/login/page.tsx`
|
||||
- [ ] Update `src/app/(auth)/register/page.tsx`
|
||||
- [ ] Update `src/app/(auth)/forgot-password/page.tsx`
|
||||
|
||||
### Phase 3: Testing
|
||||
- [ ] Visual testing (dark + light theme)
|
||||
- [ ] Accessibility testing (Lighthouse)
|
||||
- [ ] Responsive testing (mobile, tablet, desktop)
|
||||
- [ ] Functional testing (all forms)
|
||||
- [ ] Cross-browser testing
|
||||
|
||||
### Phase 4: Review
|
||||
- [ ] Code review with team
|
||||
- [ ] Design review with designer
|
||||
- [ ] QA testing
|
||||
- [ ] Performance benchmarks
|
||||
|
||||
### Phase 5: Deployment
|
||||
- [ ] Merge to main branch
|
||||
- [ ] Deploy to staging
|
||||
- [ ] Final QA on staging
|
||||
- [ ] Deploy to production
|
||||
- [ ] Monitor for issues
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support
|
||||
|
||||
**Questions about design**: Contact Design Team
|
||||
**Questions about implementation**: Contact Dev Lead
|
||||
**Bug reports**: Create issue in GitHub
|
||||
|
||||
---
|
||||
|
||||
## 📚 Related Documentation
|
||||
|
||||
- [Design System](../DESIGN_SYSTEM.md) - Full design system docs
|
||||
- [WCAG Compliance](../WCAG_COMPLIANCE.md) - Accessibility guidelines
|
||||
- [Login User Flow](../ux/flows/auth-login.md) - Detailed UX flow
|
||||
|
||||
---
|
||||
|
||||
**Author**: Design Team + Dev Team
|
||||
**Last Updated**: 2026-01-04
|
||||
**Version**: 2.0 (X.ai Minimal Redesign)
|
||||
Reference in New Issue
Block a user