From 0c8c102114bf7c41781a988d5a2e8725cac686ac Mon Sep 17 00:00:00 2001 From: rishu685 Date: Wed, 15 Oct 2025 16:00:34 +0530 Subject: [PATCH 1/2] Add CSS-Only OTP Verification Animation (Issue #796) Features: - Pure CSS implementation (no JavaScript required) - 6-digit OTP input with individual field validation - Automatic format detection for proper OTP entry - Loading animation with bouncing dots during verification - Success feedback with animated checkmark - Responsive design for all devices Technical Implementation: - State management using CSS checkbox hack - Keyframe animations for smooth transitions - Advanced pseudo-selectors (:checked, :valid, :focus) - Transform and transition effects - Responsive flexbox layout Fixes #796 --- OTP Verification Animation/index.html | 57 +++++ OTP Verification Animation/styles.css | 353 ++++++++++++++++++++++++++ 2 files changed, 410 insertions(+) create mode 100644 OTP Verification Animation/index.html create mode 100644 OTP Verification Animation/styles.css diff --git a/OTP Verification Animation/index.html b/OTP Verification Animation/index.html new file mode 100644 index 00000000..aa744f1d --- /dev/null +++ b/OTP Verification Animation/index.html @@ -0,0 +1,57 @@ + + + + + + OTP Verification + + + +
+
+

Verify Your Phone

+

We sent a code to your mobile number

+ + +
+
+ + + + + + +
+ + + + + + +
+
+ + + +
+

Checking code...

+
+ + +
+
+

Phone Verified!

+

You're all set

+
+
+ + +
+

Click to test: 123456

+ + +
+
+
+ + \ No newline at end of file diff --git a/OTP Verification Animation/styles.css b/OTP Verification Animation/styles.css new file mode 100644 index 00000000..9189cd40 --- /dev/null +++ b/OTP Verification Animation/styles.css @@ -0,0 +1,353 @@ +/* Reset and Base Styles */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + background: #f5f7fa; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; +} + +.container { + width: 100%; + max-width: 420px; +} + +/* OTP Card Styling */ +.otp-card { + background: white; + border-radius: 8px; + padding: 32px 24px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + text-align: center; + position: relative; + border: 1px solid #e9ecef; +} + +.otp-card h2 { + color: #2d3748; + margin-bottom: 8px; + font-size: 24px; + font-weight: 600; +} + +.otp-card p { + color: #718096; + margin-bottom: 24px; + font-size: 15px; +} + +/* OTP Input Styling */ +.otp-inputs { + display: flex; + gap: 12px; + justify-content: center; + margin-bottom: 24px; +} + +.otp-input { + width: 48px; + height: 56px; + border: 2px solid #e2e8f0; + border-radius: 6px; + text-align: center; + font-size: 20px; + font-weight: 500; + color: #2d3748; + transition: border-color 0.2s ease; + background: #fdfdfd; +} + +.otp-input:focus { + outline: none; + border-color: #4299e1; + background: white; +} + +.otp-input:valid { + border-color: #48bb78; +} + +/* Verify Button */ +.verify-trigger { + display: none; +} + +.verify-btn { + display: inline-block; + background: #4299e1; + color: white; + padding: 12px 32px; + border-radius: 6px; + font-size: 15px; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s ease; + border: none; +} + +.verify-btn:hover { + background: #3182ce; +} + +/* Loading Animation */ +.loading-container { + opacity: 0; + transform: translateY(10px); + transition: all 0.3s ease; + pointer-events: none; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) translateY(10px); + width: 100%; +} + +.verify-trigger:checked ~ .loading-container { + opacity: 1; + transform: translate(-50%, -50%) translateY(0); +} + +.loading-dots { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 16px; + gap: 6px; +} + +.loading-dots span { + width: 8px; + height: 8px; + background: #4299e1; + border-radius: 50%; + animation: bounce 1.4s ease-in-out infinite both; +} + +.loading-dots span:nth-child(1) { animation-delay: -0.32s; } +.loading-dots span:nth-child(2) { animation-delay: -0.16s; } +.loading-dots span:nth-child(3) { animation-delay: 0s; } + +@keyframes bounce { + 0%, 80%, 100% { + transform: scale(0.8); + opacity: 0.5; + } + 40% { + transform: scale(1); + opacity: 1; + } +} + +.loading-container p { + color: #718096; + font-size: 15px; + margin: 0; +} + +/* Success Animation */ +.success-container { + opacity: 0; + transform: translateY(10px); + transition: all 0.3s ease; + pointer-events: none; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) translateY(10px); + width: 100%; +} + +.verify-trigger:checked ~ .success-container { + animation: showSuccess 2s ease forwards 2s; +} + +@keyframes showSuccess { + 0% { + opacity: 0; + transform: translate(-50%, -50%) translateY(10px); + } + 50%, 100% { + opacity: 1; + transform: translate(-50%, -50%) translateY(0); + } +} + +.success-icon { + width: 64px; + height: 64px; + background: #48bb78; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 16px; + font-size: 28px; + color: white; + font-weight: bold; + animation: popIn 0.4s ease-out 0.2s both; +} + +@keyframes popIn { + 0% { + transform: scale(0.8); + opacity: 0; + } + 100% { + transform: scale(1); + opacity: 1; + } +} + +.success-container h3 { + color: #2d3748; + margin-bottom: 8px; + font-size: 20px; + font-weight: 600; +} + +.success-container p { + color: #718096; + margin: 0; + font-size: 15px; +} + +/* Hide main content during animations */ +.verify-trigger:checked ~ .otp-inputs, +.verify-trigger:checked ~ .verify-btn { + opacity: 0.3; + transform: translateY(-10px); + transition: all 0.3s ease; +} + +/* Demo Section */ +.demo-section { + margin-top: 32px; + padding-top: 24px; + border-top: 1px solid #e2e8f0; +} + +.demo-text { + color: #a0aec0; + font-size: 13px; + margin-bottom: 12px; +} + +.demo-trigger { + display: none; +} + +.demo-btn { + display: inline-block; + background: #edf2f7; + color: #4a5568; + padding: 8px 20px; + border-radius: 4px; + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s ease; + border: 1px solid #e2e8f0; +} + +.demo-btn:hover { + background: #e2e8f0; +} + +/* Demo Auto-fill Animation */ +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(1) { + animation: autoFill 0.2s ease forwards 0.3s; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(2) { + animation: autoFill 0.2s ease forwards 0.4s; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(3) { + animation: autoFill 0.2s ease forwards 0.5s; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(4) { + animation: autoFill 0.2s ease forwards 0.6s; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(5) { + animation: autoFill 0.2s ease forwards 0.7s; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(6) { + animation: autoFill 0.2s ease forwards 0.8s; +} + +@keyframes autoFill { + 0% { + background: #fdfdfd; + } + 50% { + background: #bee3f8; + border-color: #4299e1; + } + 100% { + background: #f0fff4; + border-color: #48bb78; + } +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(1):after { + content: "1"; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(2):after { + content: "2"; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(3):after { + content: "3"; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(4):after { + content: "4"; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(5):after { + content: "5"; +} + +.demo-trigger:checked ~ .otp-card .otp-input:nth-child(6):after { + content: "6"; +} + +/* Auto-trigger verification after demo */ +.demo-trigger:checked ~ .otp-card .verify-trigger { + animation: autoVerify 0.1s linear forwards 1.5s; +} + +@keyframes autoVerify { + 100% { + opacity: 1; + } +} + +/* Responsive Design */ +@media (max-width: 480px) { + .otp-card { + padding: 24px 16px; + } + + .otp-inputs { + gap: 8px; + } + + .otp-input { + width: 44px; + height: 52px; + font-size: 18px; + } +} \ No newline at end of file From 74248a83de5f24ec6b40019895fbf3014a6d874b Mon Sep 17 00:00:00 2001 From: rishu685 Date: Wed, 15 Oct 2025 16:15:42 +0530 Subject: [PATCH 2/2] Fix OTP Verification Animation bugs and improve UX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐛 Bug Fixes: - Fixed non-working Fill Demo Code and Reset buttons - Improved button functionality with proper CSS selectors - Fixed animation timing and state management ✨ UI/UX Improvements: - Better spacing between buttons (12px gap) - Enhanced visual feedback with hover effects - Improved button styling with proper colors - Added working demo functionality that shows numbers 1-6 - Complete reset functionality that clears all states 🔧 Technical Improvements: - Restructured HTML for better CSS sibling selectors - Fixed CSS selectors for demo and reset functionality - Improved responsive design for mobile devices - Better placeholder styling with bullet points (•) - Enhanced animation sequences and transitions ✅ Working Features: - Fill Demo Code: Shows green fields with 123456 - Reset: Clears all inputs and animations - Verify Code: Complete loading → success animation - Responsive design for all screen sizes --- OTP Verification Animation/index.html | 30 +++-- OTP Verification Animation/styles.css | 183 ++++++++++++++++++++------ 2 files changed, 164 insertions(+), 49 deletions(-) diff --git a/OTP Verification Animation/index.html b/OTP Verification Animation/index.html index aa744f1d..1f324d91 100644 --- a/OTP Verification Animation/index.html +++ b/OTP Verification Animation/index.html @@ -8,19 +8,28 @@
+ +
+ + +
+

Verify Your Phone

We sent a code to your mobile number

+
+ 💡 Type any 6 digits or use demo below, then click Verify +
- - - - - - + + + + + +
@@ -47,9 +56,12 @@

Phone Verified!

-

Click to test: 123456

- - +

Demo: Click below to auto-fill 123456

+ +
+ + +
diff --git a/OTP Verification Animation/styles.css b/OTP Verification Animation/styles.css index 9189cd40..f5e22859 100644 --- a/OTP Verification Animation/styles.css +++ b/OTP Verification Animation/styles.css @@ -40,10 +40,21 @@ body { .otp-card p { color: #718096; - margin-bottom: 24px; + margin-bottom: 16px; font-size: 15px; } +.instruction { + text-align: center; + margin-bottom: 16px; +} + +.instruction small { + color: #a0aec0; + font-size: 12px; + font-style: italic; +} + /* OTP Input Styling */ .otp-inputs { display: flex; @@ -113,6 +124,18 @@ body { .verify-trigger:checked ~ .loading-container { opacity: 1; transform: translate(-50%, -50%) translateY(0); + animation: hideLoading 0.3s ease forwards 2.5s; +} + +@keyframes hideLoading { + 0% { + opacity: 1; + transform: translate(-50%, -50%) translateY(0); + } + 100% { + opacity: 0; + transform: translate(-50%, -50%) translateY(-10px); + } } .loading-dots { @@ -166,7 +189,7 @@ body { } .verify-trigger:checked ~ .success-container { - animation: showSuccess 2s ease forwards 2s; + animation: showSuccess 0.5s ease forwards 3s; } @keyframes showSuccess { @@ -229,79 +252,159 @@ body { /* Demo Section */ .demo-section { - margin-top: 32px; - padding-top: 24px; + margin-top: 24px; + padding-top: 20px; border-top: 1px solid #e2e8f0; + text-align: center; } .demo-text { color: #a0aec0; font-size: 13px; - margin-bottom: 12px; + margin-bottom: 16px; +} + +.demo-buttons { + display: flex; + gap: 12px; + justify-content: center; + align-items: center; +} + +/* Demo Controls (hidden) */ +.demo-controls { + position: absolute; + opacity: 0; + pointer-events: none; } -.demo-trigger { +.demo-trigger, +.reset-trigger { display: none; } .demo-btn { display: inline-block; - background: #edf2f7; - color: #4a5568; - padding: 8px 20px; - border-radius: 4px; - font-size: 13px; + background: #e6fffa; + color: #234e52; + padding: 10px 20px; + border-radius: 6px; + font-size: 14px; font-weight: 500; cursor: pointer; - transition: background-color 0.2s ease; - border: 1px solid #e2e8f0; + transition: all 0.2s ease; + border: 2px solid #81e6d9; + user-select: none; } .demo-btn:hover { - background: #e2e8f0; + background: #b2f5ea; + transform: translateY(-1px); } -/* Demo Auto-fill Animation */ -.demo-trigger:checked ~ .otp-card .otp-input:nth-child(1) { - animation: autoFill 0.2s ease forwards 0.3s; +.demo-trigger:checked ~ .otp-card .demo-btn { + background: #4fd1c7; + color: white; + border-color: #38b2ac; } -.demo-trigger:checked ~ .otp-card .otp-input:nth-child(2) { - animation: autoFill 0.2s ease forwards 0.4s; +.reset-btn { + display: inline-block; + background: #fed7d7; + color: #c53030; + padding: 10px 20px; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + border: 2px solid #feb2b2; + user-select: none; } -.demo-trigger:checked ~ .otp-card .otp-input:nth-child(3) { - animation: autoFill 0.2s ease forwards 0.5s; +.reset-btn:hover { + background: #feb2b2; + transform: translateY(-1px); } -.demo-trigger:checked ~ .otp-card .otp-input:nth-child(4) { - animation: autoFill 0.2s ease forwards 0.6s; +.reset-trigger:checked ~ .otp-card .reset-btn { + background: #e53e3e; + color: white; + border-color: #c53030; } -.demo-trigger:checked ~ .otp-card .otp-input:nth-child(5) { - animation: autoFill 0.2s ease forwards 0.7s; +/* Demo functionality - simulate filled inputs */ +.demo-trigger:checked ~ .otp-card .otp-input { + background-color: #f0fff4; + border-color: #48bb78; + color: #2d3748; + position: relative; } -.demo-trigger:checked ~ .otp-card .otp-input:nth-child(6) { - animation: autoFill 0.2s ease forwards 0.8s; +.demo-trigger:checked ~ .otp-card #otp1:after { content: "1"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-weight: 600; } +.demo-trigger:checked ~ .otp-card #otp2:after { content: "2"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-weight: 600; } +.demo-trigger:checked ~ .otp-card #otp3:after { content: "3"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-weight: 600; } +.demo-trigger:checked ~ .otp-card #otp4:after { content: "4"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-weight: 600; } +.demo-trigger:checked ~ .otp-card #otp5:after { content: "5"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-weight: 600; } +.demo-trigger:checked ~ .otp-card #otp6:after { content: "6"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-weight: 600; } + +/* Reset functionality */ +.reset-trigger:checked ~ .otp-card .otp-input { + background-color: #fdfdfd; + border-color: #e2e8f0; } -@keyframes autoFill { - 0% { - background: #fdfdfd; +.reset-trigger:checked ~ .otp-card .otp-input:after { + content: ""; +} + +.reset-trigger:checked ~ .otp-card .loading-container, +.reset-trigger:checked ~ .otp-card .success-container { + opacity: 0 !important; + transform: translate(-50%, -50%) translateY(10px) !important; + animation: none !important; +} + +.reset-trigger:checked ~ .otp-card .verify-trigger { + visibility: visible; +} + +.reset-trigger:checked ~ .otp-card .otp-inputs, +.reset-trigger:checked ~ .otp-card .verify-btn { + opacity: 1 !important; + transform: translateY(0) !important; +} + +/* Responsive Design */ +@media (max-width: 480px) { + .container { + padding: 16px; } - 50% { - background: #bee3f8; - border-color: #4299e1; + + .otp-card { + padding: 24px 20px; } - 100% { - background: #f0fff4; - border-color: #48bb78; + + .otp-inputs { + gap: 8px; + } + + .otp-input { + width: 40px; + height: 48px; + font-size: 16px; + } + + .demo-buttons { + flex-direction: column; + gap: 8px; + } + + .demo-btn, + .reset-btn { + padding: 12px 24px; + font-size: 16px; } -} - -.demo-trigger:checked ~ .otp-card .otp-input:nth-child(1):after { - content: "1"; } .demo-trigger:checked ~ .otp-card .otp-input:nth-child(2):after {