Spaces:
Running
Running
Create a Flutter-based, cross-platform calculator app (Android & iOS) with the following ultra-detailed specs: 1. UI / UX β’ Full glassmorphism card design with backdrop blur. β’ Neon-glow accents (cyan by day, magenta by night). β’ Micro-interactions: 120 ms haptic feedback + 180 ms ripple-splash on every key. β’ Numbers slide-in with 300 ms cubic-bezier ease-out animation. 2. Day / Night Toggle β’ Floating Sun π / Moon π toggle top-right. β’ 500 ms animated gradient transition: β Day: soft pastel gradient (#F6F9FC - Initial Deployment
5859752
verified
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Glassmorphic Calculator</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| @keyframes slideIn { | |
| from { transform: translateY(20px); opacity: 0; } | |
| to { transform: translateY(0); opacity: 1; } | |
| } | |
| .number-animation { | |
| animation: slideIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; | |
| } | |
| .glassmorphism { | |
| background: rgba(255, 255, 255, 0.15); | |
| backdrop-filter: blur(10px); | |
| -webkit-backdrop-filter: blur(10px); | |
| border-radius: 20px; | |
| border: 1px solid rgba(255, 255, 255, 0.18); | |
| box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); | |
| } | |
| .ripple { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .ripple-effect { | |
| position: absolute; | |
| border-radius: 50%; | |
| background: rgba(255, 255, 255, 0.4); | |
| transform: scale(0); | |
| animation: ripple 0.6s linear; | |
| pointer-events: none; | |
| } | |
| @keyframes ripple { | |
| to { | |
| transform: scale(4); | |
| opacity: 0; | |
| } | |
| } | |
| .day-mode { | |
| background: linear-gradient(135deg, #F6F9FC 0%, #E6F0F8 100%); | |
| } | |
| .night-mode { | |
| background: linear-gradient(135deg, #0F0C29 0%, #302B63 50%, #24243E 100%); | |
| } | |
| .day-text { | |
| color: #2D3748; | |
| } | |
| .night-text { | |
| color: #E2E8F0; | |
| } | |
| .day-accent { | |
| box-shadow: 0 0 15px rgba(0, 255, 255, 0.7); | |
| } | |
| .night-accent { | |
| box-shadow: 0 0 15px rgba(255, 0, 255, 0.7); | |
| } | |
| .day-button { | |
| background: rgba(255, 255, 255, 0.8); | |
| color: #2D3748; | |
| } | |
| .night-button { | |
| background: rgba(30, 30, 60, 0.8); | |
| color: #E2E8F0; | |
| } | |
| .day-display { | |
| background: rgba(255, 255, 255, 0.9); | |
| color: #2D3748; | |
| } | |
| .night-display { | |
| background: rgba(30, 30, 60, 0.9); | |
| color: #E2E8F0; | |
| } | |
| .theme-toggle { | |
| transition: all 0.5s ease; | |
| } | |
| .theme-toggle:hover { | |
| transform: rotate(180deg); | |
| } | |
| .gradient-transition { | |
| transition: background 0.5s ease; | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen flex items-center justify-center p-4 day-mode gradient-transition"> | |
| <div class="glassmorphism w-full max-w-md p-6 relative overflow-hidden"> | |
| <!-- Theme Toggle --> | |
| <div class="absolute top-4 right-4 z-10"> | |
| <button id="themeToggle" class="w-12 h-12 rounded-full flex items-center justify-center bg-white bg-opacity-20 shadow-lg theme-toggle"> | |
| <i id="themeIcon" class="fas fa-sun text-yellow-500 text-xl"></i> | |
| </button> | |
| </div> | |
| <!-- Display --> | |
| <div id="display" class="day-display rounded-xl p-4 mb-6 h-24 flex flex-col justify-between transition-all duration-300"> | |
| <div id="history" class="text-right text-sm opacity-70 h-6 overflow-hidden"></div> | |
| <div id="result" class="text-right text-3xl font-semibold overflow-x-auto">0</div> | |
| </div> | |
| <!-- Keypad --> | |
| <div class="grid grid-cols-4 gap-3"> | |
| <!-- Row 1 --> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('AC')">AC</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('Β±')">Β±</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('%')">%</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium bg-cyan-500 text-white day-accent transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('Γ·')">Γ·</button> | |
| <!-- Row 2 --> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('7')">7</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('8')">8</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('9')">9</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium bg-cyan-500 text-white day-accent transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('Γ')">Γ</button> | |
| <!-- Row 3 --> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('4')">4</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('5')">5</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('6')">6</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium bg-cyan-500 text-white day-accent transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('-')">-</button> | |
| <!-- Row 4 --> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('1')">1</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('2')">2</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('3')">3</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium bg-cyan-500 text-white day-accent transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('+')">+</button> | |
| <!-- Row 5 --> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium number-animation col-span-2 transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('0')">0</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium transition-all duration-200 hover:opacity-80 active:scale-95" onclick="appendToDisplay('.')">.</button> | |
| <button class="ripple day-button rounded-xl p-4 text-xl font-medium bg-cyan-500 text-white day-accent transition-all duration-200 hover:opacity-80 active:scale-95" onclick="calculate()">=</button> | |
| </div> | |
| </div> | |
| <script> | |
| // Calculator logic | |
| let currentInput = '0'; | |
| let previousInput = ''; | |
| let operation = null; | |
| let resetScreen = false; | |
| // DOM elements | |
| const resultDisplay = document.getElementById('result'); | |
| const historyDisplay = document.getElementById('history'); | |
| const themeToggle = document.getElementById('themeToggle'); | |
| const themeIcon = document.getElementById('themeIcon'); | |
| const display = document.getElementById('display'); | |
| const body = document.body; | |
| // Initialize calculator | |
| updateDisplay(); | |
| // Theme toggle | |
| let isDayMode = true; | |
| themeToggle.addEventListener('click', () => { | |
| isDayMode = !isDayMode; | |
| if (isDayMode) { | |
| body.classList.remove('night-mode'); | |
| body.classList.add('day-mode'); | |
| themeIcon.classList.remove('fa-moon'); | |
| themeIcon.classList.add('fa-sun'); | |
| themeIcon.classList.remove('text-purple-300'); | |
| themeIcon.classList.add('text-yellow-500'); | |
| // Update all buttons | |
| document.querySelectorAll('.day-button').forEach(button => { | |
| button.classList.remove('night-button'); | |
| button.classList.add('day-button'); | |
| }); | |
| // Update display | |
| display.classList.remove('night-display'); | |
| display.classList.add('day-display'); | |
| // Update accents | |
| document.querySelectorAll('.day-accent').forEach(button => { | |
| button.classList.remove('night-accent'); | |
| button.classList.add('day-accent'); | |
| button.classList.remove('bg-purple-500'); | |
| button.classList.add('bg-cyan-500'); | |
| }); | |
| } else { | |
| body.classList.remove('day-mode'); | |
| body.classList.add('night-mode'); | |
| themeIcon.classList.remove('fa-sun'); | |
| themeIcon.classList.add('fa-moon'); | |
| themeIcon.classList.remove('text-yellow-500'); | |
| themeIcon.classList.add('text-purple-300'); | |
| // Update all buttons | |
| document.querySelectorAll('.day-button').forEach(button => { | |
| button.classList.remove('day-button'); | |
| button.classList.add('night-button'); | |
| }); | |
| // Update display | |
| display.classList.remove('day-display'); | |
| display.classList.add('night-display'); | |
| // Update accents | |
| document.querySelectorAll('.day-accent').forEach(button => { | |
| button.classList.remove('day-accent'); | |
| button.classList.add('night-accent'); | |
| button.classList.remove('bg-cyan-500'); | |
| button.classList.add('bg-purple-500'); | |
| }); | |
| } | |
| }); | |
| // Ripple effect | |
| document.querySelectorAll('.ripple').forEach(button => { | |
| button.addEventListener('click', function(e) { | |
| // Haptic feedback simulation | |
| if (navigator.vibrate) { | |
| navigator.vibrate(120); | |
| } | |
| // Create ripple | |
| const ripple = document.createElement('span'); | |
| ripple.classList.add('ripple-effect'); | |
| // Position ripple | |
| const rect = this.getBoundingClientRect(); | |
| const x = e.clientX - rect.left; | |
| const y = e.clientY - rect.top; | |
| ripple.style.left = `${x}px`; | |
| ripple.style.top = `${y}px`; | |
| this.appendChild(ripple); | |
| // Remove ripple after animation | |
| setTimeout(() => { | |
| ripple.remove(); | |
| }, 600); | |
| }); | |
| }); | |
| // Number animation | |
| function animateNumberButtons() { | |
| const numberButtons = document.querySelectorAll('.number-animation'); | |
| numberButtons.forEach(button => { | |
| button.style.animation = 'none'; | |
| void button.offsetWidth; // Trigger reflow | |
| button.style.animation = 'slideIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards'; | |
| }); | |
| } | |
| // Calculator functions | |
| function appendToDisplay(value) { | |
| if (value === 'AC') { | |
| currentInput = '0'; | |
| previousInput = ''; | |
| operation = null; | |
| updateDisplay(); | |
| return; | |
| } | |
| if (value === 'Β±') { | |
| currentInput = (parseFloat(currentInput) * -1).toString(); | |
| updateDisplay(); | |
| return; | |
| } | |
| if (value === '%') { | |
| currentInput = (parseFloat(currentInput) / 100).toString(); | |
| updateDisplay(); | |
| return; | |
| } | |
| if (['+', '-', 'Γ', 'Γ·'].includes(value)) { | |
| if (operation !== null) calculate(); | |
| previousInput = currentInput; | |
| currentInput = '0'; | |
| operation = value; | |
| updateDisplay(); | |
| return; | |
| } | |
| if (value === '.') { | |
| if (!currentInput.includes('.')) { | |
| currentInput += '.'; | |
| } | |
| updateDisplay(); | |
| return; | |
| } | |
| if (currentInput === '0' || resetScreen) { | |
| currentInput = value; | |
| resetScreen = false; | |
| } else { | |
| currentInput += value; | |
| } | |
| updateDisplay(); | |
| animateNumberButtons(); | |
| } | |
| function calculate() { | |
| let result; | |
| const prev = parseFloat(previousInput); | |
| const current = parseFloat(currentInput); | |
| if (isNaN(prev) || isNaN(current)) return; | |
| switch (operation) { | |
| case '+': | |
| result = prev + current; | |
| break; | |
| case '-': | |
| result = prev - current; | |
| break; | |
| case 'Γ': | |
| result = prev * current; | |
| break; | |
| case 'Γ·': | |
| result = prev / current; | |
| break; | |
| default: | |
| return; | |
| } | |
| currentInput = result.toString(); | |
| operation = null; | |
| resetScreen = true; | |
| updateDisplay(); | |
| } | |
| function updateDisplay() { | |
| resultDisplay.textContent = currentInput; | |
| historyDisplay.textContent = previousInput + (operation ? ` ${operation} ` : ''); | |
| } | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 𧬠<a href="https://enzostvs-deepsite.hf.space?remix=Rajkumar122f/raj" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |