Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Modern Calc UI</title> | |
| <!-- Icons --> | |
| <script src="https://unpkg.com/@phosphor-icons/web@2.0.1/dist/index.js"></script> | |
| <!-- Font --> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --bg-color: #09090b; | |
| --calc-bg: #1c1c1e; | |
| --text-primary: #ffffff; | |
| --text-secondary: #a1a1aa; | |
| --accent-color: #6366f1; | |
| --accent-hover: #818cf8; | |
| --btn-bg: #27272a; | |
| --btn-hover: #3f3f46; | |
| --btn-text: #e4e4e7; | |
| --shadow-soft: 0 10px 15px -3px rgba(0, 0, 0, 0.5); | |
| --glow: 0 0 20px rgba(99, 102, 241, 0.3); | |
| } | |
| * { | |
| box-sizing: box-sizing; | |
| margin: 0; | |
| padding: 0; | |
| user-select: none; /* Prevent text selection on buttons */ | |
| } | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background-color: var(--bg-color); | |
| background-image: | |
| radial-gradient(at 0% 0%, hsla(253,16%,7%,1) 0, transparent 50%), | |
| radial-gradient(at 50% 0%, hsla(220,100%,62%,1) 0, transparent 50%), | |
| radial-gradient(at 100% 0%, hsla(340,100%,76%,1) 0, transparent 50%); | |
| height: 100vh; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| overflow: hidden; | |
| color: var(--text-primary); | |
| } | |
| /* --- Layout Wrapper --- */ | |
| .wrapper { | |
| width: 100%; | |
| max-width: 400px; | |
| padding: 20px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 20px; | |
| } | |
| /* --- Header --- */ | |
| .app-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 0 10px; | |
| } | |
| .brand { | |
| font-weight: 600; | |
| letter-spacing: -0.5px; | |
| color: var(--text-secondary); | |
| font-size: 0.9rem; | |
| } | |
| .anycoder-link { | |
| font-size: 0.85rem; | |
| color: var(--accent-color); | |
| text-decoration: none; | |
| font-weight: 600; | |
| transition: opacity 0.2s; | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .anycoder-link:hover { | |
| opacity: 0.8; | |
| text-decoration: underline; | |
| } | |
| /* --- Calculator Container --- */ | |
| .calculator { | |
| background: var(--calc-bg); | |
| border-radius: 24px; | |
| padding: 24px; | |
| box-shadow: var(--shadow-soft); | |
| border: 1px solid rgba(255, 255, 255, 0.05); | |
| backdrop-filter: blur(10px); | |
| } | |
| /* --- Display Area --- */ | |
| .display-container { | |
| height: 120px; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: flex-end; | |
| align-items: flex-end; | |
| margin-bottom: 20px; | |
| padding: 0 10px; | |
| position: relative; | |
| } | |
| .previous-operand { | |
| font-family: 'JetBrains Mono', monospace; | |
| color: var(--text-secondary); | |
| font-size: 0.9rem; | |
| min-height: 20px; | |
| margin-bottom: 5px; | |
| opacity: 0.7; | |
| overflow: hidden; | |
| white-space: nowrap; | |
| } | |
| .current-operand { | |
| font-family: 'JetBrains Mono', monospace; | |
| color: var(--text-primary); | |
| font-size: 2.5rem; | |
| font-weight: 700; | |
| word-break: break-all; | |
| line-height: 1.2; | |
| transition: font-size 0.2s ease; | |
| } | |
| /* --- Button Grid --- */ | |
| .buttons-grid { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 12px; | |
| } | |
| button { | |
| background: var(--btn-bg); | |
| border: none; | |
| border-radius: 16px; | |
| height: 60px; | |
| font-family: 'Inter', sans-serif; | |
| font-size: 1.2rem; | |
| font-weight: 500; | |
| color: var(--btn-text); | |
| cursor: pointer; | |
| transition: all 0.15s ease; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); | |
| } | |
| button:hover { | |
| background: var(--btn-hover); | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 8px -1px rgba(0, 0, 0, 0.2); | |
| } | |
| button:active { | |
| transform: translateY(0); | |
| scale: 0.95; | |
| } | |
| /* Special Button Styles */ | |
| .btn-operator { | |
| color: var(--accent-color); | |
| font-weight: 700; | |
| background: rgba(99, 102, 241, 0.1); | |
| } | |
| .btn-operator:hover { | |
| background: rgba(99, 102, 241, 0.2); | |
| } | |
| .btn-equals { | |
| background: var(--accent-color); | |
| color: white; | |
| box-shadow: var(--glow); | |
| } | |
| .btn-equals:hover { | |
| background: var(--accent-hover); | |
| } | |
| .btn-function { | |
| color: var(--text-secondary); | |
| font-size: 1rem; | |
| } | |
| .btn-zero { | |
| grid-column: span 2; /* Zero spans two columns */ | |
| } | |
| /* --- Responsive Tweaks --- */ | |
| @media (max-width: 450px) { | |
| .wrapper { | |
| padding: 10px; | |
| } | |
| .calculator { | |
| padding: 16px; | |
| } | |
| button { | |
| height: 50px; | |
| font-size: 1.1rem; | |
| } | |
| .current-operand { | |
| font-size: 2rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="wrapper"> | |
| <!-- Header Section --> | |
| <header class="app-header"> | |
| <div class="brand">Calc.UI</div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link" target="_blank"> | |
| Built with anycoder <phosphor-icon name="arrow-right"></phosphor-icon> | |
| </a> | |
| </header> | |
| <!-- Main Calculator Unit --> | |
| <main class="calculator"> | |
| <!-- Display --> | |
| <div class="display-container"> | |
| <div class="previous-operand" data-previous></div> | |
| <div class="current-operand" data-current>0</div> | |
| </div> | |
| <!-- Controls --> | |
| <div class="buttons-grid"> | |
| <button class="btn-function" onclick="calculator.clear()"> | |
| <phosphor-icon name="trash"></phosphor-icon> | |
| </button> | |
| <button class="btn-function" onclick="calculator.delete()"> | |
| <phosphor-icon name="backspace"></phosphor-icon> | |
| </button> | |
| <button class="btn-operator" onclick="calculator.chooseOperation('%')">%</button> | |
| <button class="btn-operator" onclick="calculator.chooseOperation('÷')">÷</button> | |
| <button onclick="calculator.appendNumber('7')">7</button> | |
| <button onclick="calculator.appendNumber('8')">8</button> | |
| <button onclick="calculator.appendNumber('9')">9</button> | |
| <button class="btn-operator" onclick="calculator.chooseOperation('*')">×</button> | |
| <button onclick="calculator.appendNumber('4')">4</button> | |
| <button onclick="calculator.appendNumber('5')">5</button> | |
| <button onclick="calculator.appendNumber('6')">6</button> | |
| <button class="btn-operator" onclick="calculator.chooseOperation('-')">-</button> | |
| <button onclick="calculator.appendNumber('1')">1</button> | |
| <button onclick="calculator.appendNumber('2')">2</button> | |
| <button onclick="calculator.appendNumber('3')">3</button> | |
| <button class="btn-operator" onclick="calculator.chooseOperation('+')">+</button> | |
| <button class="btn-zero" onclick="calculator.appendNumber('0')">0</button> | |
| <button onclick="calculator.appendNumber('.')">.</button> | |
| <button class="btn-equals" onclick="calculator.compute()">=</button> | |
| </div> | |
| </main> | |
| </div> | |
| <script> | |
| class Calculator { | |
| constructor(previousOperandTextElement, currentOperandTextElement) { | |
| this.previousOperandTextElement = previousOperandTextElement; | |
| this.currentOperandTextElement = currentOperandTextElement; | |
| this.clear(); | |
| } | |
| clear() { | |
| this.currentOperand = ''; | |
| this.previousOperand = ''; | |
| this.operation = undefined; | |
| this.updateDisplay(); | |
| } | |
| delete() { | |
| this.currentOperand = this.currentOperand.toString().slice(0, -1); | |
| this.updateDisplay(); | |
| } | |
| appendNumber(number) { | |
| if (number === '.' && this.currentOperand.includes('.')) return; | |
| this.currentOperand = this.currentOperand.toString() + number.toString(); | |
| this.updateDisplay(); | |
| } | |
| chooseOperation(operation) { | |
| if (this.currentOperand === '') return; | |
| if (this.previousOperand !== '') { | |
| this.compute(); | |
| } | |
| this.operation = operation; | |
| this.previousOperand = this.currentOperand; | |
| this.currentOperand = ''; | |
| this.updateDisplay(); | |
| } | |
| compute() { | |
| let computation; | |
| const prev = parseFloat(this.previousOperand); | |
| const current = parseFloat(this.currentOperand); | |
| if (isNaN(prev) || isNaN(current)) return; | |
| switch (this.operation) { | |
| case '+': | |
| computation = prev + current; | |
| break; | |
| case '-': | |
| computation = prev - current; | |
| break; | |
| case '*': | |
| computation = prev * current; | |
| break; | |
| case '÷': | |
| if(current === 0) { | |
| alert("Cannot divide by zero!"); | |
| this.clear(); | |
| return; | |
| } | |
| computation = prev / current; | |
| break; | |
| case '%': | |
| computation = prev % current; | |
| break; | |
| default: | |
| return; | |
| } | |
| this.currentOperand = computation; | |
| this.operation = undefined; | |
| this.previousOperand = ''; | |
| this.updateDisplay(); | |
| } | |
| getDisplayNumber(number) { | |
| const stringNumber = number.toString(); | |
| const integerDigits = parseFloat(stringNumber.split('.')[0]); | |
| const decimalDigits = stringNumber.split('.')[1]; | |
| let integerDisplay; | |
| if (isNaN(integerDigits)) { | |
| integerDisplay = ''; | |
| } else { | |
| integerDisplay = integerDigits.toLocaleString('en', { maximumFractionDigits: 0 }); | |
| } | |
| if (decimalDigits != null) { | |
| return `${integerDisplay}.${decimalDigits}`; | |
| } else { | |
| return integerDisplay; | |
| } | |
| } | |
| updateDisplay() { | |
| this.currentOperandTextElement.innerText = | |
| this.getDisplayNumber(this.currentOperand); | |
| if (this.operation != null) { | |
| this.previousOperandTextElement.innerText = | |
| `${this.getDisplayNumber(this.previousOperand)} ${this.operation}`; | |
| } else { | |
| this.previousOperandTextElement.innerText = ''; | |
| } | |
| } | |
| } | |
| const numberElements = document.querySelectorAll('[data-current]'); | |
| const previousOperandTextElement = document.querySelector('[data-previous]'); | |
| const currentOperandTextElement = document.querySelector('[data-current]'); | |
| const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement); | |
| // Keyboard Support | |
| document.addEventListener('keydown', (e) => { | |
| if ((e.key >= 0 && e.key <= 9) || e.key === '.') { | |
| calculator.appendNumber(e.key); | |
| } | |
| if (e.key === '+' || e.key === '-') { | |
| calculator.chooseOperation(e.key); | |
| } | |
| if (e.key === '*') { | |
| calculator.chooseOperation('*'); | |
| } | |
| if (e.key === '/') { | |
| calculator.chooseOperation('÷'); | |
| } | |
| if (e.key === 'Enter' || e.key === '=') { | |
| calculator.compute(); | |
| } | |
| if (e.key === 'Backspace') { | |
| calculator.delete(); | |
| } | |
| if (e.key === 'Escape') { | |
| calculator.clear(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |