Floating Action Buttons (FABs) are a staple in modern UI design, offering users a quick and intuitive way to perform primary actions. Their versatility and prominence make them an essential component in many applications.
In this article, we will explore 10 exemplary Floating Action Button designs that showcase their functionality and aesthetic appeal. These examples will provide inspiration and insights for integrating FABs into your own projects.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Designers and developers, elevate your UI game with Subframe's drag-and-drop interface. Its intuitive, responsive canvas ensures pixel-perfect designs every time, making it a favorite among professionals.
Ready to create stunning Floating Action Buttons effortlessly? Start for free today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Unlock the power of Subframe and design pixel-perfect UIs with ease. Whether you're crafting a Floating Action Button or an entire interface, Subframe's drag-and-drop editor ensures efficiency and precision.
Don't wait—start creating stunning designs immediately. Start for free today!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Modern E-commerce FAB</title> <style> :root { --primary-color: #ff4757; --secondary-color: #2f3542; --light-color: #f1f2f6; --accent-color: #5352ed; --success-color: #2ed573; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f8f9fa; overflow-x: hidden; height: 100vh; display: flex; flex-direction: column; } .e-commerce-container { max-width: 700px; margin: 0 auto; padding: 20px; width: 100%; position: relative; flex-grow: 1; display: flex; flex-direction: column; } .header { display: flex; justify-content: space-between; align-items: center; padding: 15px 0; border-bottom: 1px solid rgba(0, 0, 0, 0.1); margin-bottom: 20px; } .logo { font-size: 24px; font-weight: bold; color: var(--secondary-color); } .search-bar { flex-grow: 1; margin: 0 20px; position: relative; } .search-bar input { width: 100%; padding: 10px 15px; border-radius: 25px; border: 1px solid rgba(0, 0, 0, 0.1); font-size: 14px; outline: none; transition: all 0.3s ease; } .search-bar input:focus { border-color: var(--accent-color); box-shadow: 0 0 0 2px rgba(83, 82, 237, 0.2); } .search-icon { position: absolute; right: 15px; top: 50%; transform: translateY(-50%); color: #999; } .products-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; } .product-card { background-color: white; border-radius: 10px; overflow: hidden; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); transition: transform 0.3s ease, box-shadow 0.3s ease; cursor: pointer; position: relative; } .product-card:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); } .product-image { width: 100%; height: 160px; background-size: cover; background-position: center; position: relative; } .wishlist-icon { position: absolute; top: 10px; right: 10px; background-color: white; border-radius: 50%; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s ease; } .wishlist-icon:hover { background-color: var(--primary-color); color: white; } .product-details { padding: 15px; } .product-name { font-weight: 600; margin-bottom: 5px; color: var(--secondary-color); font-size: 16px; } .product-price { font-weight: 700; color: var(--primary-color); margin-bottom: 10px; font-size: 18px; } .product-rating { display: flex; align-items: center; margin-bottom: 15px; } .stars { color: #fdcb6e; margin-right: 5px; } .review-count { font-size: 12px; color: #777; } .add-to-cart { background-color: var(--accent-color); color: white; border: none; border-radius: 20px; padding: 8px 15px; width: 100%; cursor: pointer; font-weight: 500; transition: all 0.3s ease; } .add-to-cart:hover { background-color: #4040cc; } /* FAB Styles */ .fab-container { position: fixed; bottom: 30px; right: 30px; z-index: 999; display: flex; flex-direction: column; align-items: flex-end; } .fab-menu { position: absolute; bottom: 70px; right: 0; display: flex; flex-direction: column; align-items: flex-end; gap: 15px; opacity: 0; transform: translateY(10px); pointer-events: none; transition: all 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); } .fab-menu.active { opacity: 1; transform: translateY(0); pointer-events: auto; } .fab-menu-item { background-color: white; width: 50px; height: 50px; border-radius: 50%; display: flex; justify-content: center; align-items: center; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2); color: var(--secondary-color); cursor: pointer; transition: all 0.3s ease; position: relative; } .fab-menu-item:hover { background-color: var(--light-color); transform: scale(1.1); } .fab-menu-item .tooltip { position: absolute; right: 60px; background-color: var(--secondary-color); color: white; padding: 5px 10px; border-radius: 4px; font-size: 12px; white-space: nowrap; opacity: 0; transform: translateX(10px); transition: all 0.3s ease; } .fab-menu-item:hover .tooltip { opacity: 1; transform: translateX(0); } .fab-menu-item .tooltip::after { content: ''; position: absolute; top: 50%; right: -4px; transform: translateY(-50%) rotate(45deg); width: 8px; height: 8px; background-color: var(--secondary-color); } .fab-menu-item .badge { position: absolute; top: -5px; right: -5px; background-color: var(--primary-color); color: white; font-size: 12px; width: 20px; height: 20px; border-radius: 50%; display: flex; justify-content: center; align-items: center; } .fab { width: 60px; height: 60px; border-radius: 50%; background-color: var(--primary-color); color: white; display: flex; justify-content: center; align-items: center; box-shadow: 0 4px 15px rgba(255, 71, 87, 0.4); cursor: pointer; transition: all 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); position: relative; } .fab:hover { transform: rotate(45deg); background-color: #ff2a3e; } .fab.active { transform: rotate(45deg); background-color: var(--secondary-color); } .fab .badge { position: absolute; top: 0px; right: 0px; background-color: var(--success-color); color: white; font-size: 12px; min-width: 20px; height: 20px; border-radius: 10px; display: flex; justify-content: center; align-items: center; transform: scale(0); transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); padding: 0 5px; } .fab .badge.active { transform: scale(1); } .fab.bounce { animation: bounce 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55); } @keyframes bounce { 0%, 100% { transform: translateY(0) scale(1); } 50% { transform: translateY(-10px) scale(1.1); } } /* Cart Drawer */ .cart-drawer { position: fixed; top: 0; right: -350px; width: 350px; height: 100vh; background-color: white; box-shadow: -5px 0 20px rgba(0, 0, 0, 0.1); transition: right 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); z-index: 9999; display: flex; flex-direction: column; } .cart-drawer.active { right: 0; } .cart-header { padding: 20px; border-bottom: 1px solid rgba(0, 0, 0, 0.1); display: flex; justify-content: space-between; align-items: center; } .cart-header h2 { margin: 0; color: var(--secondary-color); font-size: 20px; } .close-cart { background: none; border: none; font-size: 24px; cursor: pointer; color: var(--secondary-color); } .cart-items { flex-grow: 1; overflow-y: auto; padding: 20px; } .cart-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; color: #999; text-align: center; } .cart-empty i { font-size: 48px; margin-bottom: 15px; color: #ddd; } .cart-item { display: flex; margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid rgba(0, 0, 0, 0.1); animation: fadeIn 0.5s ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .cart-item-image { width: 80px; height: 80px; border-radius: 8px; background-size: cover; background-position: center; margin-right: 15px; flex-shrink: 0; } .cart-item-details { flex-grow: 1; } .cart-item-name { font-weight: 600; margin-bottom: 5px; color: var(--secondary-color); } .cart-item-price { font-weight: 700; color: var(--primary-color); margin-bottom: 10px; } .cart-item-controls { display: flex; align-items: center; } .quantity-control { display: flex; align-items: center; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 20px; overflow: hidden; } .quantity-btn { width: 28px; height: 28px; background: none; border: none; font-size: 16px; cursor: pointer; display: flex; align-items: center; justify-content: center; color: var(--secondary-color); transition: background-color 0.3s ease; } .quantity-btn:hover { background-color: rgba(0, 0, 0, 0.05); } .quantity-value { width: 28px; text-align: center; font-weight: 500; } .remove-item { margin-left: 15px; background: none; border: none; color: #999; cursor: pointer; transition: color 0.3s ease; } .remove-item:hover { color: var(--primary-color); } .cart-footer { padding: 20px; border-top: 1px solid rgba(0, 0, 0, 0.1); background-color: #f9f9f9; } .subtotal { display: flex; justify-content: space-between; margin-bottom: 15px; font-size: 16px; } .subtotal-value { font-weight: 700; color: var(--secondary-color); } .checkout-btn { width: 100%; background-color: var(--accent-color); color: white; border: none; border-radius: 25px; padding: 12px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; } .checkout-btn:hover { background-color: #4040cc; transform: translateY(-2px); box-shadow: 0 4px 10px rgba(83, 82, 237, 0.3); } .overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); opacity: 0; visibility: hidden; transition: all 0.3s ease; z-index: 998; } .overlay.active { opacity: 1; visibility: visible; } /* Wish List Drawer */ .wishlist-drawer { position: fixed; top: 0; right: -350px; width: 350px; height: 100vh; background-color: white; box-shadow: -5px 0 20px rgba(0, 0, 0, 0.1); transition: right 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); z-index: 9999; display: flex; flex-direction: column; } .wishlist-drawer.active { right: 0; } .toast { position: fixed; bottom: 110px; right: 30px; background-color: var(--secondary-color); color: white; padding: 15px 25px; border-radius: 30px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); z-index: 1000; opacity: 0; transform: translateY(20px); transition: all 0.3s ease; display: flex; align-items: center; } .toast.show { opacity: 1; transform: translateY(0); } .toast i { margin-right: 10px; color: var(--success-color); } /* Make responsive for screens < 700px */ @media (max-width: 700px) { .products-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 15px; } .header { flex-wrap: wrap; } .search-bar { order: 3; margin: 15px 0 0; width: 100%; } .cart-drawer, .wishlist-drawer { width: 300px; right: -300px; } .fab-container { bottom: 20px; right: 20px; } } @media (max-width: 400px) { .products-grid { grid-template-columns: 1fr 1fr; } .cart-drawer, .wishlist-drawer { width: 100%; right: -100%; } } </style> </head> <body> <div class="e-commerce-container"> <div class="header"> <div class="logo">CozyShopper</div> <div class="search-bar"> <input type="text" placeholder="Search for products..."> <i class="search-icon">🔍</i> </div> </div> <div class="products-grid"> <div class="product-card" data-id="1" data-name="Minimalist Desk Lamp" data-price="39.99" data-image="https://images.unsplash.com/photo-1507473885765-e6ed057f782c?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"> <div class="product-image" style="background-image: url('https://images.unsplash.com/photo-1507473885765-e6ed057f782c?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80')"> <div class="wishlist-icon">♡</div> </div> <div class="product-details"> <div class="product-name">Minimalist Desk Lamp</div> <div class="product-price">$39.99</div> <div class="product-rating"> <div class="stars">★★★★☆</div> <div class="review-count">(42)</div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card" data-id="2" data-name="Ceramic Plant Pot" data-price="24.99" data-image="https://images.unsplash.com/photo-1485955900006-10f4d324d411?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"> <div class="product-image" style="background-image: url('https://images.unsplash.com/photo-1485955900006-10f4d324d411?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80')"> <div class="wishlist-icon">♡</div> </div> <div class="product-details"> <div class="product-name">Ceramic Plant Pot</div> <div class="product-price">$24.99</div> <div class="product-rating"> <div class="stars">★★★★★</div> <div class="review-count">(78)</div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card" data-id="3" data-name="Wireless Earbuds" data-price="99.00" data-image="https://images.unsplash.com/photo-1572569511254-d8f925fe2cbb?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"> <div class="product-image" style="background-image: url('https://images.unsplash.com/photo-1572569511254-d8f925fe2cbb?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80')"> <div class="wishlist-icon">♡</div> </div> <div class="product-details"> <div class="product-name">Wireless Earbuds</div> <div class="product-price">$99.00</div> <div class="product-rating"> <div class="stars">★★★★☆</div> <div class="review-count">(125)</div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card" data-id="4" data-name="Smartwatch" data-price="149.99" data-image="https://images.unsplash.com/photo-1523275335684-37898b6baf30?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"> <div class="product-image" style="background-image: url('https://images.unsplash.com/photo-1523275335684-37898b6baf30?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80')"> <div class="wishlist-icon">♡</div> </div> <div class="product-details"> <div class="product-name">Smartwatch</div> <div class="product-price">$149.99</div> <div class="product-rating"> <div class="stars">★★★★★</div> <div class="review-count">(93)</div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card" data-id="5" data-name="Coffee Mug Set" data-price="19.95" data-image="https://images.unsplash.com/photo-1514228742587-6b1558fcca3d?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"> <div class="product-image" style="background-image: url('https://images.unsplash.com/photo-1514228742587-6b1558fcca3d?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80')"> <div class="wishlist-icon">♡</div> </div> <div class="product-details"> <div class="product-name">Coffee Mug Set</div> <div class="product-price">$19.95</div> <div class="product-rating"> <div class="stars">★★★☆☆</div> <div class="review-count">(37)</div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card" data-id="6" data-name="Portable Charger" data-price="34.50" data-image="https://images.unsplash.com/photo-1603539947369-b5a6f06e9d03?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80"> <div class="product-image" style="background-image: url('https://images.unsplash.com/photo-1603539947369-b5a6f06e9d03?ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80')"> <div class="wishlist-icon">♡</div> </div> <div class="product-details"> <div class="product-name">Portable Charger</div> <div class="product-price">$34.50</div> <div class="product-rating"> <div class="stars">★★★★☆</div> <div class="review-count">(62)</div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> </div> </div> <!-- FAB Components --> <div class="fab-container"> <div class="fab-menu"> <div class="fab-menu-item" id="wishlistFabItem"> <div class="tooltip">Wishlist</div> <i>♡</i> <div class="badge" id="wishlistBadge">0</div> </div> <div class="fab-menu-item" id="cartFabItem"> <div class="tooltip">Cart</div> <i>🛒</i> <div class="badge" id="cartBadge">0</div> </div> </div> <div class="fab" id="mainFab"> <i>+</i> <div class="badge" id="fabBadge">0</div> </div> </div> <!-- Cart Drawer --> <div class="cart-drawer" id="cartDrawer"> <div class="cart-header"> <h2>Your Cart</h2> <button class="close-cart">×</button> </div> <div class="cart-items" id="cartItems"> <div class="cart-empty"> <i>🛒</i> <p>Your cart is empty</p> <p>Start adding items to see them here.</p> </div> </div> <div class="cart-footer"> <div class="subtotal"> <div>Subtotal:</div> <div class="subtotal-value" id="subtotalValue">$0.00</div> </div> <button class="checkout-btn">Proceed to Checkout</button> </div> </div> <!-- Wishlist Drawer --> <div class="wishlist-drawer" id="wishlistDrawer"> <div class="cart-header"> <h2>Your Wishlist</h2> <button class="close-cart" id="closeWishlist">×</button> </div> <div class="cart-items" id="wishlistItems"> <div class="cart-empty"> <i>♡</i> <p>Your wishlist is empty</p> <p>Save items you love for later.</p> </div> </div> </div> <!-- Overlay --> <div class="overlay" id="overlay"></div> <!-- Toast Notification --> <div class="toast" id="toast"> <i>✓</i> <span id="toastMessage"></span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Elements const mainFab = document.getElementById('mainFab'); const fabMenu = document.querySelector('.fab-menu'); const cartFabItem = document.getElementById('cartFabItem'); const wishlistFabItem = document.getElementById('wishlistFabItem'); const cartDrawer = document.getElementById('cartDrawer'); const wishlistDrawer = document.getElementById('wishlistDrawer'); const overlay = document.getElementById('overlay'); const closeCart = document.querySelector('.close-cart'); const closeWishlist = document.getElementById('closeWishlist'); const toast = document.getElementById('toast'); const toastMessage = document.getElementById('toastMessage'); const fabBadge = document.getElementById('fabBadge'); const cartBadge = document.getElementById('cartBadge'); const wishlistBadge = document.getElementById('wishlistBadge'); const cartItems = document.getElementById('cartItems'); const wishlistItems = document.getElementById('wishlistItems'); const subtotalValue = document.getElementById('subtotalValue'); // State let cart = []; let wishlist = []; let isFabMenuOpen = false; // Toggle FAB menu mainFab.addEventListener('click', () => { isFabMenuOpen = !isFabMenuOpen; mainFab.classList.toggle('active', isFabMenuOpen); fabMenu.classList.toggle('active', isFabMenuOpen); }); // Open Cart Drawer cartFabItem.addEventListener('click', () => { cartDrawer.classList.add('active'); overlay.classList.add('active'); if (isFabMenuOpen) { mainFab.click(); } renderCart(); }); // Open Wishlist Drawer wishlistFabItem.addEventListener('click', () => { wishlistDrawer.classList.add('active'); overlay.classList.add('active'); if (isFabMenuOpen) { mainFab.click(); } renderWishlist(); }); // Close drawers closeCart.addEventListener('click', () => { cartDrawer.classList.remove('active'); overlay.classList.remove('active'); }); closeWishlist.addEventListener('click', () => { wishlistDrawer.classList.remove('active'); overlay.classList.remove('active'); }); overlay.addEventListener('click', () => { cartDrawer.classList.remove('active'); wishlistDrawer.classList.remove('active'); overlay.classList.remove('active'); }); // Add to cart functionality document.querySelectorAll('.add-to-cart').forEach(button => { button.addEventListener('click', (e) => { const productCard = e.target.closest('.product-card'); const productId = productCard.dataset.id; const productName = productCard.dataset.name; const productPrice = parseFloat(productCard.dataset.price); const productImage = productCard.dataset.image; // Check if product is already in cart const existingItem = cart.find(item => item.id === productId); if (existingItem) { existingItem.quantity += 1; } else { cart.push({ id: productId, name: productName, price: productPrice, image: productImage, quantity: 1 }); } updateCartBadge(); showToast(`${productName} added to cart`); bounceFab(); }); }); // Wishlist toggle functionality document.querySelectorAll('.wishlist-icon').forEach(icon => { icon.addEventListener('click', (e) => { e.stopPropagation(); const productCard = e.target.closest('.product-card'); const productId = productCard.dataset.id; const productName = productCard.dataset.name; const productPrice = parseFloat(productCard.dataset.price); const productImage = productCard.dataset.image; // Check if product is already in wishlist const existingItemIndex = wishlist.findIndex(item => item.id === productId); if (existingItemIndex >= 0) { // Remove from wishlist wishlist.splice(existingItemIndex, 1); e.target.textContent = '♡'; showToast(`${productName} removed from wishlist`); } else { // Add to wishlist wishlist.push({ id: productId, name: productName, price: productPrice, image: productImage }); e.target.textContent = '♥'; showToast(`${productName} added to wishlist`); bounceFab(); } updateWishlistBadge(); }); }); // Update cart badge function updateCartBadge() { const totalItems = cart.reduce((total, item) => total + item.quantity, 0); cartBadge.textContent = totalItems; fabBadge.textContent = totalItems + wishlist.length; if (totalItems > 0) { cartBadge.classList.add('active'); fabBadge.classList.add('active'); } else { cartBadge.classList.remove('active'); if (wishlist.length === 0) { fabBadge.classList.remove('active'); } } } // Update wishlist badge function updateWishlistBadge() { const totalItems = wishlist.length; wishlistBadge.textContent = totalItems; fabBadge.textContent = totalItems + cart.reduce((total, item) => total + item.quantity, 0); if (totalItems > 0) { wishlistBadge.classList.add('active'); fabBadge.classList.add('active'); } else { wishlistBadge.classList.remove('active'); if (cart.length === 0) { fabBadge.classList.remove('active'); } } } // Bounce FAB animation function bounceFab() { mainFab.classList.add('bounce'); setTimeout(() => { mainFab.classList.remove('bounce'); }, 500); } // Show toast notification function showToast(message) { toastMessage.textContent = message; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); }, 3000); } // Render cart items function renderCart() { if (cart.length === 0) { cartItems.innerHTML = ` <div class="cart-empty"> <i>🛒</i> <p>Your cart is empty</p> <p>Start adding items to see them here.</p> </div> `; subtotalValue.textContent = '$0.00'; return; } let cartHTML = ''; let subtotal = 0; cart.forEach(item => { const itemTotal = item.price * item.quantity; subtotal += itemTotal; cartHTML += ` <div class="cart-item" data-id="${item.id}"> <div class="cart-item-image" style="background-image: url('${item.image}')"></div> <div class="cart-item-details"> <div class="cart-item-name">${item.name}</div> <div class="cart-item-price">$${item.price.toFixed(2)}</div> <div class="cart-item-controls"> <div class="quantity-control"> <button class="quantity-btn decrease">-</button> <div class="quantity-value">${item.quantity}</div> <button class="quantity-btn increase">+</button> </div> <button class="remove-item">🗑️</button> </div> </div> </div> `; }); cartItems.innerHTML = cartHTML; subtotalValue.textContent = `$${subtotal.toFixed(2)}`; // Add event listeners for quantity controls document.querySelectorAll('.quantity-btn.decrease').forEach(btn => { btn.addEventListener('click', e => { const cartItem = e.target.closest('.cart-item'); const productId = cartItem.dataset.id; const item = cart.find(item => item.id === productId); if (item.quantity > 1) { item.quantity -= 1; cartItem.querySelector('.quantity-value').textContent = item.quantity; updateCartBadge(); renderCart(); } }); }); document.querySelectorAll('.quantity-btn.increase').forEach(btn => { btn.addEventListener('click', e => { const cartItem = e.target.closest('.cart-item'); const productId = cartItem.dataset.id; const item = cart.find(item => item.id === productId); item.quantity += 1; cartItem.querySelector('.quantity-value').textContent = item.quantity; updateCartBadge(); renderCart(); }); }); document.querySelectorAll('.remove-item').forEach(btn => { btn.addEventListener('click', e => { const cartItem = e.target.closest('.cart-item'); const productId = cartItem.dataset.id; const itemIndex = cart.findIndex(item => item.id === productId); if (itemIndex !== -1) { const removedItem = cart[itemIndex]; cart.splice(itemIndex, 1); updateCartBadge(); renderCart(); showToast(`${removedItem.name} removed from cart`); } }); }); } // Render wishlist items function renderWishlist() { if (
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Navigation FAB</title> <style> *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; overflow: hidden; background-color: #f5f5f5; } .map-container { position: relative; width: 100%; max-width: 700px; height: 700px; overflow: hidden; border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); } .map { width: 100%; height: 100%; background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MDAgNTAwIj48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2YyZjJmMjt9LmNscy0ye2ZpbGw6I2U2ZTZlNjt9LmNscy0ze2ZpbGw6I2QxZTNmZjt9LmNscy00e2ZpbGw6I2NjZDhkYjt9LmNscy01e2ZpbGw6I2IzZDhiMzt9LmNscy02e2ZpbGw6I2Q5ZDlkOTt9PC9zdHlsZT48L2RlZnM+PHJlY3QgY2xhc3M9ImNscy0xIiB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTM4LDEwNXMzNy43NCw1Ljc3LDQ2LjUyLDIuNSw0Mi4yMy0xNi40Miw0OS4yNC0xMi4yNyw2MywxNC4yOSw2OSwxOC4yOSw3OS45Mi0xNS45MSw3OS45Mi0xNS45MWw2Mi4xLDI3Ljc4TDQxMCw5OS44M2w5MCw1Ni44MXY5OS43MnMtOS4zNS03MS4zOS00Mi0yNi44M2MtMTMuNjMsMTguNTktOTAuMzYsMTcuNzgtOTAsMzJzLTUyLDYtNzgsMjRTMTkwLDMxNiwxNzAsMzE2cy03OS40MSw1My43OS0xMTkuODQtMTQuNDFMOTAsMjQ4LDM4LDEwNVoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0wLDE5Mi44M3M0MC42Miw2LDUzLjA2LDEwLjgyLDEzLjg4LDEyLjI3LDI1LjcyLDIwLjI3UzEwOCwyNDAsMTIwLDI0MHMyMS0yLjEzLDMzLTQsMTMsNS44LDI5LjUsMjQtNC41LDI2LTcsMzksMTcsMjYsMTcsMjZsMjYtOC4yMWMyNC44Miw4LjIxLDQzLjUsMjcuMDUsNjgsMjgsNDksMTksMTM5LDYzLDE5Mi41LDIxLjVsLTE5LDEzNC43M0gwWiIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTAsMjcwLjgzczM3LjU3LDcuOTQsNTYsMTkuM2M1LjcyLDYuODQsMjkuODYsODYuODYsMjkuODYsODYuODZMMCw1MDBaIi8+PHBhdGggY2xhc3M9ImNscy01IiBkPSJNNTAwLDQzNC43M3YzTDxwYXRoIGNsYXNzPSJjbHMtNSIgZD0iTTI2OSwzNjRjLTEwLjEzLTMuOC0yMS43NC00LjE3LTMyLjE0LTEtNS43NCwxLjcyLTExLDUuNjItMTQuMywxMC43cy00LDExLjc2LTEuNSwxNy4zYzMsMTEsMTEuMjIsMTEuNTMsMTkuOTQsMTYuNDcsNS42MSwzLDkuMjIsOSw4LjQ0LDE1LjM1cy02LjQsMTEuNjEtMTIuNzYsMTIuMjJjLTcuNzYuNzUtMTQuNzItMy45Mi0yMC4xOC0xMCIvPjwvc3ZnPg=='); background-size: cover; background-position: center; transition: transform 0.3s ease; position: relative; } /* Fake map elements */ .map::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MDAgNTAwIj48ZGVmcz48c3R5bGU+LmEge2ZpbGw6bm9uZTtzdHJva2U6I2QxZDFkMTtzdHJva2Utd2lkdGg6MS41cHg7fSAuYiB7ZmlsbDpub25lO3N0cm9rZTojYzdjN2M3O3N0cm9rZS13aWR0aDoxLjJweDt9IC5jIHtmaWxsOiM0Mjg1RjQ7c3Ryb2tlOndoaXRlO3N0cm9rZS13aWR0aDoxLjVweDt9IC5kIHtmaWxsOiNFQTQzMzU7c3Ryb2tlOndoaXRlO3N0cm9rZS13aWR0aDoxLjVweDt9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImEiIGQ9Ik0xMDAsMTAwIEw0MDAsMTAwIEw0MDAsNDAwIEwxMDAsNDAwIFoiLz48cGF0aCBjbGFzcz0iYSIgZD0iTTE1MCwxNTAgTDM1MCwxNTAgTDM1MCwzNTAgTDE1MCwzNTAgWiIvPjxwYXRoIGNsYXNzPSJiIiBkPSJNNTAsNTAgTDQ1MCw1MCBMNDUwLDQ1MCBMNTAsNDUwIFoiLz48cGF0aCBjbGFzcz0iYiIgZD0iTTEwMCwxMDAgTDIwMCwzMDAgTDMwMCwxNTAgTDQwMCwzNTAiLz48Y2lyY2xlIGNsYXNzPSJjIiBjeD0iMjAwIiBjeT0iMzAwIiByPSI4Ii8+PGNpcmNsZSBjbGFzcz0iZCIgY3g9IjM1MCIgY3k9IjIwMCIgcj0iOCIvPjwvc3ZnPg=='); opacity: 0.6; pointer-events: none; } .fab-container { position: absolute; bottom: 32px; right: 32px; z-index: 10; } .fab { width: 64px; height: 64px; border-radius: 50%; background-color: #4285F4; box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2); display: flex; justify-content: center; align-items: center; cursor: pointer; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); position: relative; overflow: hidden; } .fab::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(circle at center, rgba(255,255,255,0.2) 0%, rgba(255,255,255,0) 70%); opacity: 0.8; z-index: 1; } .fab:hover { transform: translateY(-4px) scale(1.05); box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25); } .fab:active { transform: translateY(0) scale(0.98); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); } .fab-icon { width: 28px; height: 28px; fill: white; z-index: 2; transition: transform 0.3s ease; } .fab:hover .fab-icon { transform: scale(1.15); } .fab-ripple { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0); width: 200px; height: 200px; background-color: rgba(255, 255, 255, 0.4); border-radius: 50%; opacity: 0; z-index: 0; } .fab-options { position: absolute; bottom: 80px; right: 8px; display: flex; flex-direction: column; align-items: flex-end; gap: 16px; opacity: 0; transform: translateY(10px); pointer-events: none; transition: all 0.3s ease; } .fab-options.active { opacity: 1; transform: translateY(0); pointer-events: all; } .fab-option { display: flex; align-items: center; gap: 12px; } .fab-option-button { width: 48px; height: 48px; border-radius: 50%; background-color: white; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); display: flex; justify-content: center; align-items: center; cursor: pointer; transition: all 0.3s ease; } .fab-option-button:hover { transform: scale(1.1); box-shadow: 0 6px 14px rgba(0, 0, 0, 0.15); } .fab-option-label { background-color: rgba(0, 0, 0, 0.7); color: white; padding: 6px 12px; border-radius: 4px; font-size: 14px; white-space: nowrap; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); opacity: 0; transform: translateX(10px); transition: all 0.2s ease; } .fab-option:hover .fab-option-label { opacity: 1; transform: translateX(0); } .fab-option-icon { width: 24px; height: 24px; fill: #4285F4; } .marker { position: absolute; width: 32px; height: 32px; transition: transform 0.3s ease; transform: translate(-50%, -100%); cursor: pointer; } .marker-current { top: 60%; left: 45%; } .pulse { position: absolute; width: 16px; height: 16px; background-color: rgba(66, 133, 244, 0.6); border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); } .pulse::before { content: ''; position: absolute; width: 100%; height: 100%; background-color: #4285F4; border-radius: 50%; transform: scale(0.5); animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(0.5); opacity: 1; } 100% { transform: scale(2); opacity: 0; } } .tooltip { position: absolute; background-color: white; padding: 12px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); max-width: 200px; display: none; z-index: 5; } .tooltip.active { display: block; animation: fadeIn 0.3s forwards; } .tooltip-title { font-weight: bold; margin-bottom: 4px; color: #333; } .tooltip-address { font-size: 12px; color: #666; margin-bottom: 8px; } .tooltip-actions { display: flex; gap: 8px; } .tooltip-action { padding: 6px 10px; border-radius: 4px; font-size: 12px; cursor: pointer; transition: background-color 0.2s; } .tooltip-action.directions { background-color: #4285F4; color: white; } .tooltip-action.save { background-color: #f1f1f1; color: #333; } .tooltip-action:hover { opacity: 0.9; } .toast { position: absolute; top: 24px; left: 50%; transform: translateX(-50%) translateY(-100px); background-color: rgba(0, 0, 0, 0.8); color: white; padding: 12px 24px; border-radius: 8px; font-size: 14px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); opacity: 0; transition: all 0.3s ease; z-index: 20; } .toast.active { transform: translateX(-50%) translateY(0); opacity: 1; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes ripple { 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(1); opacity: 0; } } .zoom-controls { position: absolute; left: 20px; bottom: 32px; display: flex; flex-direction: column; gap: 8px; z-index: 10; } .zoom-btn { width: 40px; height: 40px; background-color: white; border-radius: 4px; display: flex; justify-content: center; align-items: center; cursor: pointer; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); transition: all 0.2s ease; } .zoom-btn:hover { background-color: #f9f9f9; } .zoom-btn:active { transform: scale(0.95); } .search-container { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); width: 80%; max-width: 400px; z-index: 10; } .search-bar { width: 100%; padding: 12px 16px; padding-left: 48px; border-radius: 8px; border: none; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); font-size: 16px; outline: none; transition: all 0.3s ease; } .search-bar:focus { box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15); } .search-icon { position: absolute; left: 16px; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; fill: #666; pointer-events: none; } </style> </head> <body> <div class="map-container"> <div class="map" id="map"> <div class="marker marker-current"> <div class="pulse"></div> <svg viewBox="0 0 24 24" fill="#4285F4" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" stroke="white" stroke-width="1.5"/> </svg> </div> <div class="tooltip" id="tooltip"> <div class="tooltip-title">Current Location</div> <div class="tooltip-address">123 Navigation St, Map City</div> <div class="tooltip-actions"> <div class="tooltip-action directions">Directions</div> <div class="tooltip-action save">Save</div> </div> </div> </div> <div class="search-container"> <input type="text" class="search-bar" placeholder="Search locations..."> <svg class="search-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/> </svg> </div> <div class="zoom-controls"> <div class="zoom-btn" id="zoom-in"> <svg width="18" height="18" viewBox="0 0 24 24" fill="#666" xmlns="http://www.w3.org/2000/svg"> <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/> </svg> </div> <div class="zoom-btn" id="zoom-out"> <svg width="18" height="18" viewBox="0 0 24 24" fill="#666" xmlns="http://www.w3.org/2000/svg"> <path d="M19 13H5v-2h14v2z"/> </svg> </div> </div> <div class="fab-container"> <div class="fab" id="main-fab"> <svg class="fab-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm8.94 3c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/> </svg> <div class="fab-ripple" id="fab-ripple"></div> </div> <div class="fab-options" id="fab-options"> <div class="fab-option"> <div class="fab-option-label">Navigate</div> <div class="fab-option-button" id="navigate-btn"> <svg class="fab-option-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71L12 2z"/> </svg> </div> </div> <div class="fab-option"> <div class="fab-option-label">Explore Nearby</div> <div class="fab-option-button" id="explore-btn"> <svg class="fab-option-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 10.9c-.61 0-1.1.49-1.1 1.1s.49 1.1 1.1 1.1c.61 0 1.1-.49 1.1-1.1s-.49-1.1-1.1-1.1zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm2.19 12.19L6 18l3.81-8.19L18 6l-3.81 8.19z"/> </svg> </div> </div> <div class="fab-option"> <div class="fab-option-label">Find My Location</div> <div class="fab-option-button" id="location-btn"> <svg class="fab-option-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/> <path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/> </svg> </div> </div> </div> </div> <div class="toast" id="toast">Finding optimal route...</div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const mainFab = document.getElementById('main-fab'); const fabOptions = document.getElementById('fab-options'); const fabRipple = document.getElementById('fab-ripple'); const marker = document.querySelector('.marker-current'); const tooltip = document.getElementById('tooltip'); const navigateBtn = document.getElementById('navigate-btn'); const exploreBtn = document.getElementById('explore-btn'); const locationBtn = document.getElementById('location-btn'); const toast = document.getElementById('toast'); const zoomIn = document.getElementById('zoom-in'); const zoomOut = document.getElementById('zoom-out'); const map = document.getElementById('map'); const searchBar = document.querySelector('.search-bar'); let isOptionsOpen = false; let scale = 1; let isDragging = false; let startX, startY, startTranslateX = 0, startTranslateY = 0; let currentTranslateX = 0, currentTranslateY = 0; // FAB click handler mainFab.addEventListener('click', () => { isOptionsOpen = !isOptionsOpen; if (isOptionsOpen) { fabOptions.classList.add('active'); // Show ripple effect fabRipple.style.animation = 'ripple 0.6s forwards'; } else { fabOptions.classList.remove('active'); // Remove animation after it completes setTimeout(() => { fabRipple.style.animation = ''; }, 600); } }); // Show tooltip when marker is clicked marker.addEventListener('click', (e) => { const markerRect = marker.getBoundingClientRect(); tooltip.style.top = `${markerRect.top - 120}px`; tooltip.style.left = `${markerRect.left}px`; tooltip.classList.toggle('active'); e.stopPropagation(); }); // Close tooltip when clicking elsewhere document.addEventListener('click', (e) => { if (tooltip.classList.contains('active') && e.target !== marker) { tooltip.classList.remove('active'); } }); // Navigate button action navigateBtn.addEventListener('click', () => { showToast('Finding fastest route to destination...'); fabOptions.classList.remove('active'); isOptionsOpen = false; }); // Explore button action exploreBtn.addEventListener('click', () => { showToast('Exploring points of interest nearby...'); fabOptions.classList.remove('active'); isOptionsOpen = false; }); // Location button action locationBtn.addEventListener('click', () => { showToast('Pinpointing your current location...'); // Simulate finding location with pulse effect const pulse = document.querySelector('.pulse'); pulse.style.animation = 'none'; setTimeout(() => { pulse.style.animation = ''; }, 10); // Center map on marker centerMap(); fabOptions.classList.remove('active'); isOptionsOpen = false; }); // Zoom controls zoomIn.addEventListener('click', () => { if (scale < 2) { scale += 0.2; updateMapTransform(); } }); zoomOut.addEventListener('click', () => { if (scale > 0.6) { scale -= 0.2; updateMapTransform(); } }); // Map dragging functionality map.addEventListener('mousedown', startDrag); map.addEventListener('touchstart', (e) => { const touch = e.touches[0]; startDrag({ clientX: touch.clientX, clientY: touch.clientY }); }, { passive: true }); function startDrag(e) { if (e.target.closest('.fab') || e.target.closest('.fab-options') || e.target.closest('.zoom-controls') || e.target.closest('.search-container')) { return; } isDragging = true; startX = e.clientX; startY = e.clientY; startTranslateX = currentTranslateX; startTranslateY = currentTranslateY; document.addEventListener('mousemove', drag); document.addEventListener('touchmove', touchDrag, { passive: true }); document.addEventListener('mouseup', endDrag); document.addEventListener('touchend', endDrag); } function touchDrag(e) { const touch = e.touches[0]; drag({ clientX: touch.clientX, clientY: touch.clientY }); } function drag(e) { if (!isDragging) return; const deltaX = e.clientX - startX; const deltaY = e.clientY - startY; currentTranslateX = startTranslateX + deltaX; currentTranslateY = startTranslateY + deltaY; updateMapTransform(); } function endDrag() { isDragging = false; document.removeEventListener('mousemove', drag); document.removeEventListener('touchmove', touchDrag); document.removeEventListener('mouseup', endDrag); document.removeEventListener('touchend', endDrag); } function updateMapTransform() { map.style.transform = `translate(${currentTranslateX}px, ${currentTranslateY}px) scale(${scale})`; } function centerMap() { currentTranslateX = 0; currentTranslateY = 0; scale = 1; updateMapTransform(); } function showToast(message) { toast.textContent = message; toast.classList.add('active'); setTimeout(() => { toast.classList.remove('active'); }, 3000); } // Search functionality searchBar.addEventListener('keypress', (e) => { if (e.key === 'Enter') { showToast(`Searching for "${searchBar.value}"...`); searchBar.blur(); } }); // Tooltip action buttons document.querySelector('.tooltip-action.directions').addEventListener('click', () => { showToast('Getting directions to Current Location...'); tooltip.classList.remove('active'); }); document.querySelector('.tooltip-action.save').addEventListener('click', () => { showToast('Location saved to your favorites'); tooltip.classList.remove('active'); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>FitPulse Tracker</title> <style> @import url('https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@500;700&family=Montserrat:wght@400;600&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Montserrat', sans-serif; background-color: #f5f7fa; background-image: linear-gradient(135deg, #f0f3f8 25%, transparent 25%), linear-gradient(225deg, #f0f3f8 25%, transparent 25%), linear-gradient(45deg, #f0f3f8 25%, transparent 25%), linear-gradient(315deg, #f0f3f8 25%, #f5f7fa 25%); background-position: 40px 0, 40px 0, 0 0, 0 0; background-size: 80px 80px; background-repeat: repeat; height: 100vh; display: flex; justify-content: center; align-items: center; color: #333; overflow: hidden; } .app-container { width: 100%; max-width: 660px; height: 600px; background-color: white; border-radius: 18px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); position: relative; overflow: hidden; padding: 20px; } .header { padding: 10px 0 20px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #f0f0f0; } .logo { display: flex; align-items: center; gap: 10px; } .logo svg { width: 32px; height: 32px; } .logo h1 { font-family: 'Barlow Condensed', sans-serif; font-size: 24px; color: #1e2f5d; font-weight: 700; letter-spacing: 0.5px; } .user-profile { width: 40px; height: 40px; border-radius: 50%; background-color: #ff5757; display: flex; justify-content: center; align-items: center; color: white; font-weight: 600; font-size: 16px; box-shadow: 0 2px 10px rgba(255, 87, 87, 0.3); } .main-content { padding: 20px 0; height: calc(100% - 110px); overflow-y: auto; } .stats-section { margin-bottom: 25px; } .section-title { font-family: 'Barlow Condensed', sans-serif; font-size: 18px; color: #666; margin-bottom: 15px; text-transform: uppercase; letter-spacing: 1px; } .stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; } .stat-card { background-color: #fafbfd; border-radius: 12px; padding: 15px; box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05); } .stat-card .value { font-family: 'Barlow Condensed', sans-serif; font-size: 28px; font-weight: 700; color: #1e2f5d; margin-bottom: 5px; } .stat-card .label { font-size: 12px; color: #888; } .recent-activities { margin-top: 25px; } .activity-item { display: flex; align-items: center; margin-bottom: 15px; padding: 12px; background-color: #fafbfd; border-radius: 12px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03); } .activity-icon { width: 42px; height: 42px; border-radius: 10px; margin-right: 15px; display: flex; justify-content: center; align-items: center; } .running { background-color: #ffedcc; color: #ff9500; } .cycling { background-color: #e3f5ff; color: #0090ff; } .strength { background-color: #ffd9e4; color: #ff2d55; } .activity-icon i { font-size: 20px; } .activity-details { flex: 1; } .activity-name { font-weight: 600; font-size: 15px; margin-bottom: 4px; } .activity-time { font-size: 12px; color: #888; } .activity-stats { display: flex; gap: 12px; } .activity-stat { text-align: center; min-width: 60px; } .activity-stat .value { font-family: 'Barlow Condensed', sans-serif; font-size: 15px; font-weight: 700; color: #1e2f5d; } .activity-stat .label { font-size: 11px; color: #888; } /* FAB Styles */ .fab-container { position: absolute; bottom: 20px; right: 20px; z-index: 100; } .fab-main { width: 64px; height: 64px; border-radius: 32px; background: linear-gradient(135deg, #ff5757 0%, #ff3131 100%); box-shadow: 0 4px 15px rgba(255, 87, 87, 0.4); display: flex; justify-content: center; align-items: center; cursor: pointer; transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow 0.3s ease; position: relative; overflow: hidden; } .fab-main:hover { transform: scale(1.05); box-shadow: 0 6px 20px rgba(255, 87, 87, 0.5); } .fab-main:active { transform: scale(0.95); } .fab-main i { color: white; font-size: 26px; transition: transform 0.3s ease; } .pulse { position: absolute; width: 64px; height: 64px; border-radius: 50%; background: transparent; border: 2px solid rgba(255, 255, 255, 0.8); opacity: 0; animation: none; } @keyframes heartbeat { 0% { transform: scale(1); opacity: 0.8; } 50% { transform: scale(1.3); opacity: 0.4; } 100% { transform: scale(1.6); opacity: 0; } } .fab-menu { position: absolute; bottom: 80px; right: 10px; display: flex; flex-direction: column; gap: 16px; opacity: 0; pointer-events: none; transform: translateY(20px); transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .fab-menu.active { opacity: 1; pointer-events: all; transform: translateY(0); } .fab-item { display: flex; align-items: center; background: white; padding: 10px 16px 10px 14px; border-radius: 30px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); cursor: pointer; transform: translateX(100px); opacity: 0; transition: all 0.3s ease; } .fab-menu.active .fab-item { transform: translateX(0); opacity: 1; } .fab-menu.active .fab-item:nth-child(1) { transition-delay: 0.1s; } .fab-menu.active .fab-item:nth-child(2) { transition-delay: 0.15s; } .fab-menu.active .fab-item:nth-child(3) { transition-delay: 0.2s; } .fab-menu.active .fab-item:nth-child(4) { transition-delay: 0.25s; } .fab-item:hover { transform: scale(1.05); } .fab-item:active { transform: scale(0.98); } .fab-item .icon-container { width: 36px; height: 36px; border-radius: 50%; display: flex; justify-content: center; align-items: center; margin-right: 10px; } .fab-item .fab-text { font-family: 'Barlow Condensed', sans-serif; font-weight: 600; font-size: 15px; letter-spacing: 0.5px; white-space: nowrap; color: #444; } .fab-item:nth-child(1) .icon-container { background-color: #ff5757; color: white; } .fab-item:nth-child(2) .icon-container { background-color: #ff9500; color: white; } .fab-item:nth-child(3) .icon-container { background-color: #0090ff; color: white; } .fab-item:nth-child(4) .icon-container { background-color: #32d74b; color: white; } .overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.4); opacity: 0; pointer-events: none; transition: opacity 0.3s ease; backdrop-filter: blur(2px); } .overlay.active { opacity: 1; pointer-events: all; } .quick-log { position: absolute; bottom: 20px; left: 20px; background-color: white; border-radius: 50px; padding: 6px 6px 6px 18px; display: flex; align-items: center; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); opacity: 0; transform: translateX(-20px); transition: all 0.3s ease; pointer-events: none; } .quick-log.active { opacity: 1; transform: translateX(0); pointer-events: all; } .quick-log span { font-family: 'Barlow Condensed', sans-serif; font-weight: 600; font-size: 15px; margin-right: 12px; color: #555; } .quick-action { width: 36px; height: 36px; border-radius: 18px; background-color: #ff5757; display: flex; justify-content: center; align-items: center; color: white; cursor: pointer; transition: all 0.2s ease; } .quick-action:hover { transform: scale(1.1); background-color: #ff3131; } /* Animation for heart line */ .heart-line { position: absolute; width: 24px; height: 12px; top: 50%; left: 50%; transform: translate(-50%, -50%); overflow: hidden; } .heart-line path { stroke: white; stroke-width: 2; fill: none; stroke-dasharray: 30; stroke-dashoffset: 30; animation: pulse-line 1.5s ease-in-out infinite; } @keyframes pulse-line { 0% { stroke-dashoffset: 30; } 50% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: -30; } } /* Responsive Design */ @media (max-width: 600px) { .app-container { height: 550px; max-width: 90%; padding: 15px; } .stats-grid { grid-template-columns: repeat(2, 1fr); } .stats-grid .stat-card:last-child { grid-column: span 2; } .activity-stats { gap: 8px; } .activity-stat { min-width: 50px; } .fab-main { width: 56px; height: 56px; } .pulse { width: 56px; height: 56px; } .quick-log { padding: 4px 4px 4px 14px; } .quick-action { width: 32px; height: 32px; } } </style> </head> <body> <div class="app-container"> <div class="header"> <div class="logo"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#ff5757"> <path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"/> </svg> <h1>FitPulse</h1> </div> <div class="user-profile">JS</div> </div> <div class="main-content"> <div class="stats-section"> <h2 class="section-title">Today's Stats</h2> <div class="stats-grid"> <div class="stat-card"> <div class="value">6,842</div> <div class="label">Steps</div> </div> <div class="stat-card"> <div class="value">3.2</div> <div class="label">Miles</div> </div> <div class="stat-card"> <div class="value">384</div> <div class="label">Calories</div> </div> </div> </div> <div class="recent-activities"> <h2 class="section-title">Recent Workouts</h2> <div class="activity-item"> <div class="activity-icon running"> <i class="fas fa-running"></i> </div> <div class="activity-details"> <div class="activity-name">Morning Run</div> <div class="activity-time">Today · 6:30 AM</div> </div> <div class="activity-stats"> <div class="activity-stat"> <div class="value">2.4</div> <div class="label">Miles</div> </div> <div class="activity-stat"> <div class="value">22'</div> <div class="label">Time</div> </div> <div class="activity-stat"> <div class="value">246</div> <div class="label">Cal</div> </div> </div> </div> <div class="activity-item"> <div class="activity-icon cycling"> <i class="fas fa-bicycle"></i> </div> <div class="activity-details"> <div class="activity-name">Sunset Cycling</div> <div class="activity-time">Yesterday · 7:15 PM</div> </div> <div class="activity-stats"> <div class="activity-stat"> <div class="value">8.7</div> <div class="label">Miles</div> </div> <div class="activity-stat"> <div class="value">42'</div> <div class="label">Time</div> </div> <div class="activity-stat"> <div class="value">318</div> <div class="label">Cal</div> </div> </div> </div> <div class="activity-item"> <div class="activity-icon strength"> <i class="fas fa-dumbbell"></i> </div> <div class="activity-details"> <div class="activity-name">Full Body Workout</div> <div class="activity-time">Yesterday · 11:45 AM</div> </div> <div class="activity-stats"> <div class="activity-stat"> <div class="value">8</div> <div class="label">Exercises</div> </div> <div class="activity-stat"> <div class="value">35'</div> <div class="label">Time</div> </div> <div class="activity-stat"> <div class="value">275</div> <div class="label">Cal</div> </div> </div> </div> </div> </div> <!-- Floating Action Button (FAB) --> <div class="fab-container"> <div class="fab-main" id="fabMain"> <div class="pulse" id="pulse"></div> <div class="heart-line"> <svg viewBox="0 0 30 15"> <path d="M0,7.5 Q5,0 10,7.5 Q15,15 20,7.5 Q25,0 30,7.5" /> </svg> </div> </div> <div class="fab-menu" id="fabMenu"> <div class="fab-item" data-workout="running"> <div class="icon-container"> <i class="fas fa-running"></i> </div> <div class="fab-text">Start Running</div> </div> <div class="fab-item" data-workout="cycling"> <div class="icon-container"> <i class="fas fa-bicycle"></i> </div> <div class="fab-text">Start Cycling</div> </div> <div class="fab-item" data-workout="swimming"> <div class="icon-container"> <i class="fas fa-swimmer"></i> </div> <div class="fab-text">Start Swimming</div> </div> <div class="fab-item" data-workout="custom"> <div class="icon-container"> <i class="fas fa-plus"></i> </div> <div class="fab-text">Custom Workout</div> </div> </div> </div> <div class="quick-log" id="quickLog"> <span>TRACKING: RUNNING</span> <div class="quick-action"> <i class="fas fa-stop"></i> </div> </div> <div class="overlay" id="overlay"></div> </div> <!-- Font Awesome for Icons --> <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script> <script> document.addEventListener('DOMContentLoaded', () => { const fabMain = document.getElementById('fabMain'); const fabMenu = document.getElementById('fabMenu'); const overlay = document.getElementById('overlay'); const pulse = document.getElementById('pulse'); const quickLog = document.getElementById('quickLog'); const fabItems = document.querySelectorAll('.fab-item'); let isActive = false; let isTracking = false; // Pulse animation function function startPulse() { pulse.style.animation = 'heartbeat 1.5s cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite'; } function stopPulse() { pulse.style.animation = 'none'; } // Toggle FAB menu fabMain.addEventListener('click', () => { if (isTracking) return; isActive = !isActive; if (isActive) { fabMenu.classList.add('active'); overlay.classList.add('active'); startPulse(); } else { fabMenu.classList.remove('active'); overlay.classList.remove('active'); stopPulse(); } }); // Close menu when overlay is clicked overlay.addEventListener('click', () => { if (isActive) { isActive = false; fabMenu.classList.remove('active'); overlay.classList.remove('active'); stopPulse(); } }); // Handle workout selection fabItems.forEach(item => { item.addEventListener('click', () => { const workoutType = item.getAttribute('data-workout'); // Update quick log text const quickLogText = quickLog.querySelector('span'); quickLogText.textContent = `TRACKING: ${workoutType.toUpperCase()}`; // Start tracking isTracking = true; isActive = false; // Show quick log quickLog.classList.add('active'); // Hide fab menu and overlay fabMenu.classList.remove('active'); overlay.classList.remove('active'); // Change FAB icon to pause and start continuous pulse fabMain.innerHTML = '<i class="fas fa-pause"></i>'; startPulse(); // Continuous pulse while tracking const pulseInterval = setInterval(startPulse, 1500); // Store interval to clear later fabMain.setAttribute('data-interval', pulseInterval); }); }); // Stop tracking when quick action button is clicked const quickAction = quickLog.querySelector('.quick-action'); quickAction.addEventListener('click', () => { isTracking = false; // Hide quick log quickLog.classList.remove('active'); // Restore FAB icon fabMain.innerHTML = ` <div class="pulse" id="pulse"></div> <div class="heart-line"> <svg viewBox="0 0 30 15"> <path d="M0,7.5 Q5,0 10,7.5 Q15,15 20,7.5 Q25,0 30,7.5" /> </svg> </div> `; // Get updated pulse element const newPulse = document.getElementById('pulse'); pulse = newPulse; // Stop pulse animation stopPulse(); // Clear interval const interval = fabMain.getAttribute('data-interval'); if (interval) { clearInterval(parseInt(interval)); } }); // Touch effects for better mobile experience const touchElements = document.querySelectorAll('.fab-main, .fab-item, .quick-action'); touchElements.forEach(el => { el.addEventListener('touchstart', () => { el.style.transform = 'scale(0.95)'; }); el.addEventListener('touchend', () => { el.style.transform = ''; }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>LearnWell Accessible FAB</title> <style> :root { --primary: #4C6EF5; --hover: #364FC7; --light: #F8F9FA; --dark: #212529; --shadow: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background-color: #f0f2f5; position: relative; overflow: hidden; } .platform-preview { width: 100%; max-width: 680px; height: 600px; background-color: white; border-radius: 16px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); position: relative; overflow: hidden; padding: 20px; } .platform-header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #eee; padding-bottom: 15px; margin-bottom: 20px; } .platform-logo { font-size: 24px; font-weight: bold; color: var(--primary); } .platform-nav { display: flex; gap: 15px; } .nav-item { color: var(--dark); text-decoration: none; padding: 5px 10px; border-radius: 5px; transition: background-color 0.3s; } .nav-item:hover { background-color: #f5f5f5; } .platform-content { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; margin-bottom: 20px; } .course-card { background-color: white; border-radius: 10px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); overflow: hidden; transition: transform 0.3s, box-shadow 0.3s; position: relative; } .course-card:hover { transform: translateY(-5px); box-shadow: 0 12px 20px rgba(0, 0, 0, 0.1); } .course-image { height: 100px; background-color: #e9ecef; position: relative; overflow: hidden; } .course-image::before { content: ""; position: absolute; width: 100%; height: 100%; background: linear-gradient(135deg, var(--primary) 0%, #6ea8fe 100%); opacity: 0.8; } .course-image-icon { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-size: 32px; } .course-content { padding: 15px; } .course-title { font-size: 16px; font-weight: 600; margin-bottom: 5px; color: var(--dark); } .course-info { font-size: 12px; color: #6c757d; } .fab-container { position: fixed; bottom: 30px; right: 30px; z-index: 999; } .fab { width: 60px; height: 60px; border-radius: 30px; background-color: var(--primary); box-shadow: 0 4px 14px rgba(76, 110, 245, 0.4); display: flex; justify-content: center; align-items: center; color: white; cursor: pointer; transition: transform 0.3s, box-shadow 0.3s, background-color 0.3s; position: relative; overflow: hidden; } .fab:focus { outline: 3px solid rgba(76, 110, 245, 0.5); } .fab::before { content: ""; position: absolute; width: 0; height: 0; background-color: rgba(255, 255, 255, 0.2); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.6s, height 0.6s; } .fab:hover { background-color: var(--hover); transform: scale(1.05); box-shadow: 0 6px 20px rgba(54, 79, 199, 0.5); } .fab:active { transform: scale(0.95); } .fab i { font-size: 24px; transition: transform 0.3s; } .fab:hover i { animation: pulse 1.5s infinite; } .fab-menu { position: absolute; bottom: 70px; right: 0; width: 260px; background-color: white; border-radius: 12px; box-shadow: 0 5px 25px rgba(0, 0, 0, 0.15); padding: 10px; transform: scale(0); transform-origin: bottom right; opacity: 0; transition: transform 0.3s, opacity 0.3s; pointer-events: none; } .fab-menu.active { transform: scale(1); opacity: 1; pointer-events: auto; } .fab-menu-header { padding: 12px 15px; border-bottom: 1px solid #eee; margin-bottom: 10px; } .fab-menu-title { font-size: 18px; color: var(--dark); font-weight: 600; margin-bottom: 5px; } .fab-menu-subtitle { font-size: 13px; color: #6c757d; } .fab-menu-item { padding: 12px 15px; display: flex; align-items: center; border-radius: 8px; transition: background-color 0.3s; cursor: pointer; margin-bottom: 5px; } .fab-menu-item:hover { background-color: #f8f9fa; } .fab-menu-item:focus { outline: 2px solid rgba(76, 110, 245, 0.5); background-color: #f8f9fa; } .fab-menu-item-icon { width: 36px; height: 36px; border-radius: 18px; background-color: #e9ecef; display: flex; justify-content: center; align-items: center; margin-right: 15px; color: var(--primary); transition: background-color 0.3s; } .fab-menu-item:hover .fab-menu-item-icon { background-color: #dbe4ff; } .fab-menu-item-content { flex: 1; } .fab-menu-item-title { font-size: 14px; color: var(--dark); font-weight: 500; margin-bottom: 2px; } .fab-menu-item-description { font-size: 12px; color: #6c757d; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.15); } 100% { transform: scale(1); } } .backdrop { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); opacity: 0; visibility: hidden; transition: opacity 0.3s; z-index: 998; } .backdrop.active { opacity: 1; visibility: visible; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; } .badge { position: absolute; top: -5px; right: -5px; background-color: #fa5252; color: white; width: 20px; height: 20px; border-radius: 10px; display: flex; justify-content: center; align-items: center; font-size: 10px; font-weight: bold; border: 2px solid white; } .tooltip { position: absolute; bottom: 75px; right: 0; background-color: #212529; color: white; padding: 8px 12px; border-radius: 6px; font-size: 12px; white-space: nowrap; opacity: 0; transform: translateY(10px); transition: opacity 0.3s, transform 0.3s; pointer-events: none; } .tooltip::after { content: ""; position: absolute; bottom: -6px; right: 25px; width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 6px solid #212529; } .fab:hover .tooltip { opacity: 1; transform: translateY(0); } /* For screen readers */ .visually-hidden { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; } @media (max-width: 480px) { .platform-preview { height: 550px; padding: 15px; } .platform-content { grid-template-columns: 1fr; } .platform-nav { display: none; } .fab-container { bottom: 20px; right: 20px; } .fab-menu { width: 240px; max-width: calc(100vw - 40px); } } </style> </head> <body> <div class="platform-preview"> <div class="platform-header"> <div class="platform-logo">LearnWell</div> <nav class="platform-nav"> <a href="#" class="nav-item">Dashboard</a> <a href="#" class="nav-item">My Courses</a> <a href="#" class="nav-item">Catalog</a> </nav> </div> <div class="platform-content"> <div class="course-card"> <div class="course-image"> <div class="course-image-icon">📊</div> </div> <div class="course-content"> <h3 class="course-title">Data Visualization</h3> <p class="course-info">4 modules · 2 hrs left</p> </div> </div> <div class="course-card"> <div class="course-image"> <div class="course-image-icon">🧠</div> </div> <div class="course-content"> <h3 class="course-title">Critical Thinking</h3> <p class="course-info">5 modules · New</p> </div> </div> <div class="course-card"> <div class="course-image"> <div class="course-image-icon">💻</div> </div> <div class="course-content"> <h3 class="course-title">Web Accessibility</h3> <p class="course-info">3 modules · 1 hr left</p> </div> </div> <div class="course-card"> <div class="course-image"> <div class="course-image-icon">🔍</div> </div> <div class="course-content"> <h3 class="course-title">Research Methods</h3> <p class="course-info">6 modules · 30 min left</p> </div> </div> </div> </div> <div class="backdrop" id="backdrop"></div> <div class="fab-container"> <button class="fab" id="fab" aria-label="Learning assistance" aria-expanded="false" aria-controls="fab-menu"> <span class="badge">3</span> <i>🎓</i> <span class="tooltip">Learning Resources</span> <span class="visually-hidden">Opens menu with learning assistance options</span> </button> <div class="fab-menu" id="fab-menu"> <div class="fab-menu-header"> <h3 class="fab-menu-title">Learning Resources</h3> <p class="fab-menu-subtitle">Get help or discover new content</p> </div> <button class="fab-menu-item" tabindex="0"> <div class="fab-menu-item-icon">📚</div> <div class="fab-menu-item-content"> <h4 class="fab-menu-item-title">Study Guides</h4> <p class="fab-menu-item-description">Access downloadable resources</p> </div> </button> <button class="fab-menu-item" tabindex="0"> <div class="fab-menu-item-icon">🔔</div> <div class="fab-menu-item-content"> <h4 class="fab-menu-item-title">Personalized Recommendations</h4> <p class="fab-menu-item-description">3 new lessons based on your progress</p> </div> </button> <button class="fab-menu-item" tabindex="0"> <div class="fab-menu-item-icon">👥</div> <div class="fab-menu-item-content"> <h4 class="fab-menu-item-title">Live Assistance</h4> <p class="fab-menu-item-description">Connect with a tutor (24/7)</p> </div> </button> <button class="fab-menu-item" tabindex="0"> <div class="fab-menu-item-icon">🎯</div> <div class="fab-menu-item-content"> <h4 class="fab-menu-item-title">Practice Exercises</h4> <p class="fab-menu-item-description">Reinforce your learning</p> </div> </button> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const fab = document.getElementById('fab'); const fabMenu = document.getElementById('fab-menu'); const backdrop = document.getElementById('backdrop'); let isMenuOpen = false; // Function to handle ripple effect on FAB fab.addEventListener('click', function(e) { // Create ripple effect const rect = fab.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const circle = document.createElement('span'); const diameter = Math.max(rect.width, rect.height); circle.style.width = circle.style.height = `${diameter}px`; circle.style.left = `${x}px`; circle.style.top = `${y}px`; circle.classList.add('ripple'); const ripple = fab.getElementsByClassName('ripple')[0]; if (ripple) { ripple.remove(); } fab.appendChild(circle); // Toggle menu toggleMenu(); }); // Close menu when backdrop is clicked backdrop.addEventListener('click', function() { closeMenu(); }); // Handle keyboard navigation document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && isMenuOpen) { closeMenu(); } }); // Toggle menu function function toggleMenu() { isMenuOpen = !isMenuOpen; fab.setAttribute('aria-expanded', isMenuOpen); if (isMenuOpen) { fabMenu.classList.add('active'); backdrop.classList.add('active'); // Focus the first menu item setTimeout(() => { const firstItem = fabMenu.querySelector('.fab-menu-item'); if (firstItem) { firstItem.focus(); } }, 100); } else { closeMenu(); } } // Close menu function function closeMenu() { isMenuOpen = false; fab.setAttribute('aria-expanded', false); fabMenu.classList.remove('active'); backdrop.classList.remove('active'); fab.focus(); // Return focus to the FAB } // Add bounce animation for badge function animateBadge() { const badge = document.querySelector('.badge'); if (badge) { badge.style.animation = 'none'; setTimeout(() => { badge.style.animation = 'pulse 1.5s infinite'; }, 10); } } // Run the badge animation periodically animateBadge(); setInterval(animateBadge, 10000); // Add interaction for menu items const menuItems = document.querySelectorAll('.fab-menu-item'); menuItems.forEach(item => { item.addEventListener('click', function() { // Visual feedback this.style.backgroundColor = '#e7f5ff'; setTimeout(() => { this.style.backgroundColor = ''; // We'd normally navigate or perform an action here // For this demo, we'll just close the menu after a delay setTimeout(() => { closeMenu(); }, 300); }, 200); }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; width: 100%; max-width: 700px; margin: 0 auto; background: linear-gradient(135deg, #15151e 0%, #1f1f2c 100%); position: relative; overflow: hidden; } .now-playing { position: absolute; top: 30px; left: 30px; color: #fff; display: flex; flex-direction: column; align-items: flex-start; width: calc(100% - 60px); animation: fadeIn 0.5s ease-in-out; } .now-playing-title { font-size: 1.5rem; font-weight: 700; margin-bottom: 6px; max-width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .now-playing-artist { font-size: 1rem; color: rgba(255, 255, 255, 0.7); max-width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .album-art { position: absolute; width: 280px; height: 280px; border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); overflow: hidden; animation: albumFloat 3s ease-in-out infinite alternate; } .album-art img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.3s ease; } .album-art:hover img { transform: scale(1.05); } .fab-container { position: fixed; bottom: 50px; width: 100%; display: flex; justify-content: center; align-items: center; z-index: 1000; } .fab { position: relative; width: 64px; height: 64px; border-radius: 50%; background: rgba(20, 20, 30, 0.8); backdrop-filter: blur(10px); display: flex; justify-content: center; align-items: center; cursor: pointer; box-shadow: 0 4px 20px rgba(97, 97, 230, 0.4); transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); overflow: hidden; } .fab::before { content: ''; position: absolute; top: -2px; left: -2px; right: -2px; bottom: -2px; border-radius: 50%; background: linear-gradient(45deg, #5e72eb, #ff77e1, #5e72eb); z-index: -1; animation: borderRotate 3s linear infinite; } .fab-icon { color: #fff; font-size: 24px; transition: transform 0.3s ease; } .fab-menu { position: absolute; bottom: 75px; display: flex; flex-direction: column; align-items: center; opacity: 0; pointer-events: none; transform: translateY(20px); transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .fab-menu.active { opacity: 1; pointer-events: all; transform: translateY(0); } .fab-menu-item { margin-bottom: 16px; width: 50px; height: 50px; border-radius: 50%; display: flex; justify-content: center; align-items: center; cursor: pointer; background: rgba(20, 20, 30, 0.8); backdrop-filter: blur(10px); box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); position: relative; transition: all 0.2s ease; } .fab-menu-item:hover { transform: scale(1.1); } .fab-menu-item::before { content: ''; position: absolute; top: -1px; left: -1px; right: -1px; bottom: -1px; border-radius: 50%; background: linear-gradient(45deg, #5e72eb, #ff77e1); z-index: -1; opacity: 0; transition: opacity 0.2s ease; } .fab-menu-item:hover::before { opacity: 1; } .fab-menu-item i { color: #fff; font-size: 20px; } .fab-menu-tooltip { position: absolute; right: 65px; background: rgba(20, 20, 30, 0.9); color: #fff; padding: 6px 12px; border-radius: 4px; font-size: 14px; white-space: nowrap; pointer-events: none; opacity: 0; transform: translateX(10px); transition: all 0.2s ease; } .fab-menu-item:hover .fab-menu-tooltip { opacity: 1; transform: translateX(0); } .fab.active { transform: rotate(45deg); box-shadow: 0 6px 30px rgba(97, 97, 230, 0.6); } .pulse { position: absolute; width: 100%; height: 100%; border-radius: 50%; background: rgba(97, 97, 230, 0.3); opacity: 0; transform: scale(0.8); animation: pulse 2s infinite; } .progress-bar { position: absolute; bottom: 0; left: 0; width: 100%; height: 5px; background: rgba(255, 255, 255, 0.1); } .progress { height: 100%; background: linear-gradient(90deg, #5e72eb, #ff77e1); width: 0; transition: width 0.2s linear; } .visualizer { position: absolute; bottom: 120px; left: 50%; transform: translateX(-50%); width: 200px; height: 60px; display: flex; justify-content: space-between; align-items: flex-end; opacity: 0; transition: opacity 0.5s ease; } .visualizer.active { opacity: 1; } .visualizer-bar { width: 5px; height: 5px; background: rgba(255, 255, 255, 0.7); border-radius: 2px; transition: height 0.2s ease; } @keyframes albumFloat { 0% { transform: translateY(0); } 100% { transform: translateY(-10px); } } @keyframes fadeIn { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0% { transform: scale(0.95); opacity: 0.7; } 50% { transform: scale(1.2); opacity: 0.3; } 100% { transform: scale(0.95); opacity: 0.7; } } @keyframes borderRotate { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @media (max-width: 700px) { .album-art { width: 220px; height: 220px; } .now-playing-title { font-size: 1.2rem; } .now-playing-artist { font-size: 0.9rem; } .visualizer { width: 150px; } } @media (max-width: 480px) { .album-art { width: 180px; height: 180px; } .now-playing { top: 20px; left: 20px; width: calc(100% - 40px); } .fab { width: 56px; height: 56px; } .fab-menu-item { width: 42px; height: 42px; } .fab-menu-item i { font-size: 16px; } } </style> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet"> </head> <body> <div class="now-playing"> <h2 class="now-playing-title">Midnight City</h2> <p class="now-playing-artist">M83</p> </div> <div class="album-art"> <img src="https://images.unsplash.com/photo-1611162616475-46b635cb6868?q=80&w=774&auto=format&fit=crop" alt="Album Cover"> </div> <div class="progress-bar"> <div class="progress" id="progress"></div> </div> <div class="visualizer" id="visualizer"> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> </div> <div class="fab-container"> <div class="fab-menu" id="fabMenu"> <div class="fab-menu-item" id="skipPrev"> <i class="fas fa-step-backward"></i> <div class="fab-menu-tooltip">Previous</div> </div> <div class="fab-menu-item" id="playPause"> <i class="fas fa-play" id="playIcon"></i> <div class="fab-menu-tooltip">Play/Pause</div> </div> <div class="fab-menu-item" id="skipNext"> <i class="fas fa-step-forward"></i> <div class="fab-menu-tooltip">Next</div> </div> <div class="fab-menu-item" id="shuffle"> <i class="fas fa-random"></i> <div class="fab-menu-tooltip">Shuffle</div> </div> </div> <div class="fab" id="fab"> <div class="pulse"></div> <i class="fab-icon fas fa-plus"></i> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const fab = document.getElementById('fab'); const fabMenu = document.getElementById('fabMenu'); const playPauseBtn = document.getElementById('playPause'); const playIcon = document.getElementById('playIcon'); const skipPrevBtn = document.getElementById('skipPrev'); const skipNextBtn = document.getElementById('skipNext'); const shuffleBtn = document.getElementById('shuffle'); const progress = document.getElementById('progress'); const visualizer = document.getElementById('visualizer'); const visualizerBars = document.querySelectorAll('.visualizer-bar'); const albumArt = document.querySelector('.album-art'); const nowPlayingTitle = document.querySelector('.now-playing-title'); const nowPlayingArtist = document.querySelector('.now-playing-artist'); // Center the album art function centerAlbumArt() { const windowHeight = window.innerHeight; const windowWidth = window.innerWidth; const albumWidth = albumArt.offsetWidth; const albumHeight = albumArt.offsetHeight; albumArt.style.top = `${(windowHeight - albumHeight) / 2}px`; albumArt.style.left = `${(windowWidth - albumWidth) / 2}px`; } centerAlbumArt(); window.addEventListener('resize', centerAlbumArt); // Sample playlists const playlists = [ { title: "Midnight City", artist: "M83", progress: 0 }, { title: "Blinding Lights", artist: "The Weeknd", progress: 0 }, { title: "Redbone", artist: "Childish Gambino", progress: 0 }, { title: "Starboy", artist: "The Weeknd", progress: 0 }, { title: "Get Lucky", artist: "Daft Punk", progress: 0 } ]; let currentTrackIndex = 0; let isPlaying = false; let progressInterval; let visualizerInterval; // Toggle menu fab.addEventListener('click', function() { fab.classList.toggle('active'); fabMenu.classList.toggle('active'); }); // Update track info function updateTrackInfo() { const currentTrack = playlists[currentTrackIndex]; nowPlayingTitle.textContent = currentTrack.title; nowPlayingArtist.textContent = currentTrack.artist; progress.style.width = `${currentTrack.progress}%`; } // Play/Pause playPauseBtn.addEventListener('click', function() { isPlaying = !isPlaying; if (isPlaying) { playIcon.classList.remove('fa-play'); playIcon.classList.add('fa-pause'); visualizer.classList.add('active'); startProgress(); animateVisualizer(); } else { playIcon.classList.remove('fa-pause'); playIcon.classList.add('fa-play'); visualizer.classList.remove('active'); clearInterval(progressInterval); clearInterval(visualizerInterval); } // Add tactile feedback animation this.style.transform = 'scale(0.9)'; setTimeout(() => { this.style.transform = 'scale(1)'; }, 100); }); // Previous track skipPrevBtn.addEventListener('click', function() { currentTrackIndex = (currentTrackIndex - 1 + playlists.length) % playlists.length; resetTrack(); updateTrackInfo(); // Add tactile feedback animation this.style.transform = 'scale(0.9)'; setTimeout(() => { this.style.transform = 'scale(1)'; }, 100); }); // Next track skipNextBtn.addEventListener('click', function() { currentTrackIndex = (currentTrackIndex + 1) % playlists.length; resetTrack(); updateTrackInfo(); // Add tactile feedback animation this.style.transform = 'scale(0.9)'; setTimeout(() => { this.style.transform = 'scale(1)'; }, 100); }); // Shuffle shuffleBtn.addEventListener('click', function() { currentTrackIndex = Math.floor(Math.random() * playlists.length); resetTrack(); updateTrackInfo(); // Add tactile feedback animation this.style.transform = 'scale(0.9)'; setTimeout(() => { this.style.transform = 'scale(1)'; }, 100); // Visual feedback for shuffle this.querySelector('i').style.color = '#ff77e1'; setTimeout(() => { this.querySelector('i').style.color = ''; }, 500); }); // Start progress animation function startProgress() { progressInterval = setInterval(() => { const currentTrack = playlists[currentTrackIndex]; currentTrack.progress += 0.1; progress.style.width = `${currentTrack.progress}%`; if (currentTrack.progress >= 100) { currentTrackIndex = (currentTrackIndex + 1) % playlists.length; resetTrack(); updateTrackInfo(); } }, 100); } // Reset current track function resetTrack() { clearInterval(progressInterval); playlists[currentTrackIndex].progress = 0; progress.style.width = '0%'; if (isPlaying) { startProgress(); } } // Animate visualizer function animateVisualizer() { visualizerInterval = setInterval(() => { visualizerBars.forEach(bar => { const height = Math.floor(Math.random() * 50) + 5; bar.style.height = `${height}px`; }); }, 100); } // Close menu when clicking outside document.addEventListener('click', function(event) { if (!fab.contains(event.target) && !fabMenu.contains(event.target) && fabMenu.classList.contains('active')) { fab.classList.remove('active'); fabMenu.classList.remove('active'); } }); // Initialize updateTrackInfo(); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Nexus Home Hub</title> <style> :root { --primary: #2c3e50; --secondary: #34495e; --accent: #1abc9c; --accent-hover: #16a085; --text: #ecf0f1; --subtle: #7f8c8d; --dark: #1a252f; --success: #2ecc71; --warning: #f39c12; --danger: #e74c3c; --inactive: #95a5a6; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { width: 100%; height: 100vh; background: linear-gradient(135deg, var(--primary), var(--dark)); display: flex; justify-content: center; align-items: center; color: var(--text); overflow: hidden; } .container { width: 90%; max-width: 680px; height: 680px; background: rgba(22, 30, 40, 0.8); border-radius: 24px; backdrop-filter: blur(12px); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); display: flex; flex-direction: column; overflow: hidden; position: relative; } .container::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle at 10% 20%, rgba(26, 188, 156, 0.03) 0%, transparent 50%), radial-gradient(circle at 90% 80%, rgba(41, 128, 185, 0.03) 0%, transparent 50%); pointer-events: none; } .header { padding: 20px 30px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid rgba(255, 255, 255, 0.1); position: relative; } .header h1 { font-size: 1.8rem; font-weight: 500; background: linear-gradient(90deg, var(--accent), #3498db); -webkit-background-clip: text; background-clip: text; color: transparent; } .header .time { font-size: 1.2rem; color: var(--subtle); } .status-bar { padding: 12px 30px; display: flex; justify-content: space-between; align-items: center; background: rgba(0, 0, 0, 0.2); } .status-info { display: flex; align-items: center; gap: 10px; } .status-dot { width: 10px; height: 10px; border-radius: 50%; background-color: var(--success); animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(0.95); opacity: 1; } 50% { transform: scale(1.1); opacity: 0.8; } 100% { transform: scale(0.95); opacity: 1; } } .active-devices { color: var(--subtle); font-size: 0.9rem; } .grid-container { display: grid; grid-template-columns: repeat(2, 1fr); grid-auto-rows: minmax(150px, auto); gap: 20px; padding: 25px; overflow-y: auto; flex: 1; } .device-card { background: rgba(52, 73, 94, 0.4); border-radius: 16px; padding: 20px; display: flex; flex-direction: column; position: relative; overflow: hidden; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); cursor: pointer; } .device-card:hover { transform: translateY(-5px); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); } .device-card.active { background: linear-gradient(135deg, rgba(26, 188, 156, 0.4), rgba(41, 128, 185, 0.4)); border: 1px solid rgba(26, 188, 156, 0.3); } .device-card::before { content: ''; position: absolute; width: 150%; height: 150%; background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%); top: -25%; left: -25%; opacity: 0; transition: opacity 0.5s ease; pointer-events: none; transform-origin: center; } .device-card.active::before { animation: ripple 1s forwards; } @keyframes ripple { 0% { opacity: 0.7; transform: scale(0); } 100% { opacity: 0; transform: scale(1); } } .device-header { display: flex; justify-content: space-between; margin-bottom: 12px; } .device-name { font-size: 1.1rem; font-weight: 500; } .toggle-btn { position: relative; width: 50px; height: 26px; background-color: var(--inactive); border-radius: 13px; transition: all 0.3s ease; cursor: pointer; } .toggle-btn::after { content: ''; position: absolute; width: 20px; height: 20px; border-radius: 50%; top: 3px; left: 3px; background-color: white; transition: all 0.3s ease; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } .device-card.active .toggle-btn { background-color: var(--accent); } .device-card.active .toggle-btn::after { transform: translateX(24px); } .device-icon { font-size: 2.5rem; margin: 10px 0; color: var(--inactive); transition: all 0.3s ease; } .device-card.active .device-icon { color: var(--text); animation: fadeIn 0.5s forwards; } @keyframes fadeIn { from { opacity: 0.6; } to { opacity: 1; } } .device-status { font-size: 0.9rem; margin-top: auto; color: var(--subtle); } .device-card.active .device-status { color: var(--text); } .device-additional { margin-top: 10px; font-size: 0.85rem; color: var(--subtle); } .device-card.active .device-additional { color: rgba(255, 255, 255, 0.8); } .fab { position: fixed; bottom: 30px; right: 30px; width: 60px; height: 60px; border-radius: 50%; background: var(--accent); display: flex; justify-content: center; align-items: center; box-shadow: 0 4px 15px rgba(26, 188, 156, 0.5); cursor: pointer; transition: all 0.3s ease; z-index: 10; } .fab:hover { transform: scale(1.1); background: var(--accent-hover); } .fab i { font-size: 1.8rem; color: white; } .fab::after { content: ''; position: absolute; width: 100%; height: 100%; border-radius: 50%; background: var(--accent); z-index: -1; opacity: 0.7; animation: pulse-accent 2s infinite; } @keyframes pulse-accent { 0% { transform: scale(1); opacity: 0.7; } 50% { transform: scale(1.15); opacity: 0; } 100% { transform: scale(1); opacity: 0; } } .context-menu { position: absolute; width: 200px; background: rgba(22, 30, 40, 0.95); border-radius: 12px; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3); padding: 10px 0; display: none; z-index: 100; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.1); } .context-menu.show { display: block; animation: fadeInUp 0.3s forwards; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .context-menu-item { padding: 12px 20px; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; gap: 10px; } .context-menu-item:hover { background: rgba(255, 255, 255, 0.1); } .context-menu-item i { font-size: 1.2rem; color: var(--accent); } @media (max-width: 600px) { .grid-container { grid-template-columns: 1fr; padding: 15px; } .header h1 { font-size: 1.5rem; } .device-card { padding: 15px; } } /* Custom scrollbar */ ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.1); border-radius: 10px; } ::-webkit-scrollbar-thumb { background: rgba(41, 128, 185, 0.5); border-radius: 10px; } ::-webkit-scrollbar-thumb:hover { background: rgba(41, 128, 185, 0.7); } /* Pulse animation for active devices */ .pulse-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 8px; background-color: var(--accent); animation: pulse-small 1.5s infinite; } @keyframes pulse-small { 0% { transform: scale(0.95); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } 100% { transform: scale(0.95); opacity: 1; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>Nexus Home Hub</h1> <div class="time" id="current-time">18:42</div> </div> <div class="status-bar"> <div class="status-info"> <div class="status-dot"></div> <span>System Online</span> </div> <div class="active-devices" id="active-count">3 devices active</div> </div> <div class="grid-container"> <div class="device-card" data-device="livingroom-lights"> <div class="device-header"> <div class="device-name">Living Room Lights</div> <div class="toggle-btn"></div> </div> <div class="device-icon">💡</div> <div class="device-status">Off</div> <div class="device-additional">Last used: Today at 16:30</div> </div> <div class="device-card active" data-device="thermostat"> <div class="device-header"> <div class="device-name">Thermostat</div> <div class="toggle-btn"></div> </div> <div class="device-icon">🌡️</div> <div class="device-status">21°C · Auto Mode</div> <div class="device-additional">Energy saving: 18% this week</div> </div> <div class="device-card active" data-device="security-system"> <div class="device-header"> <div class="device-name">Security System</div> <div class="toggle-btn"></div> </div> <div class="device-icon">🔒</div> <div class="device-status">Armed · Home Mode</div> <div class="device-additional">All sensors active (8/8)</div> </div> <div class="device-card" data-device="kitchen-devices"> <div class="device-header"> <div class="device-name">Kitchen Devices</div> <div class="toggle-btn"></div> </div> <div class="device-icon">🍳</div> <div class="device-status">Idle</div> <div class="device-additional">3 connected devices</div> </div> <div class="device-card active" data-device="media-center"> <div class="device-header"> <div class="device-name">Media Center</div> <div class="toggle-btn"></div> </div> <div class="device-icon">🎮</div> <div class="device-status">Playing · Living Room TV</div> <div class="device-additional">Netflix · 45 min remaining</div> </div> <div class="device-card" data-device="blinds"> <div class="device-header"> <div class="device-name">Smart Blinds</div> <div class="toggle-btn"></div> </div> <div class="device-icon">🪟</div> <div class="device-status">Closed</div> <div class="device-additional">Scheduled: Open at 07:00</div> </div> </div> <div class="fab"> <i>+</i> </div> </div> <div class="context-menu" id="context-menu"> <div class="context-menu-item" data-action="schedule"> <i>⏰</i> Schedule </div> <div class="context-menu-item" data-action="customize"> <i>⚙️</i> Customize </div> <div class="context-menu-item" data-action="details"> <i>📊</i> View Details </div> <div class="context-menu-item" data-action="remove"> <i>🗑️</i> Remove </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Update current time function updateTime() { const now = new Date(); const hours = now.getHours().toString().padStart(2, '0'); const minutes = now.getMinutes().toString().padStart(2, '0'); document.getElementById('current-time').textContent = `${hours}:${minutes}`; } updateTime(); setInterval(updateTime, 60000); // Device toggle functionality const deviceCards = document.querySelectorAll('.device-card'); let activeCount = document.querySelectorAll('.device-card.active').length; document.getElementById('active-count').textContent = `${activeCount} devices active`; deviceCards.forEach(card => { card.addEventListener('click', function(e) { // Don't toggle if context menu was clicked if (e.target.closest('.context-menu')) return; // Check if the click was on the toggle button const isToggleClick = e.target.closest('.toggle-btn'); if (isToggleClick || e.target.closest('.device-card')) { this.classList.toggle('active'); const statusElement = this.querySelector('.device-status'); const iconElement = this.querySelector('.device-icon'); const deviceName = this.querySelector('.device-name').textContent; const isActive = this.classList.contains('active'); // Update device status based on which device was toggled switch(this.dataset.device) { case 'livingroom-lights': statusElement.textContent = isActive ? 'On · 80% Brightness' : 'Off'; break; case 'thermostat': statusElement.textContent = isActive ? '21°C · Auto Mode' : 'Off'; break; case 'security-system': statusElement.textContent = isActive ? 'Armed · Home Mode' : 'Disarmed'; iconElement.textContent = isActive ? '🔒' : '🔓'; break; case 'kitchen-devices': statusElement.textContent = isActive ? 'Active · 3 devices' : 'Idle'; break; case 'media-center': statusElement.textContent = isActive ? 'Playing · Living Room TV' : 'Standby'; break; case 'blinds': statusElement.textContent = isActive ? 'Open · 75%' : 'Closed'; break; } // Show notification showNotification(deviceName, isActive); // Update active count activeCount = document.querySelectorAll('.device-card.active').length; document.getElementById('active-count').textContent = `${activeCount} devices active`; } }); // Right-click context menu card.addEventListener('contextmenu', function(e) { e.preventDefault(); const contextMenu = document.getElementById('context-menu'); // Position the context menu contextMenu.style.left = `${e.pageX}px`; contextMenu.style.top = `${e.pageY}px`; // Show the context menu contextMenu.classList.add('show'); // Store the reference to the clicked card contextMenu.dataset.target = this.dataset.device; }); }); // FAB button click animation and functionality const fab = document.querySelector('.fab'); fab.addEventListener('click', function() { this.style.transform = 'scale(0.95)'; setTimeout(() => { this.style.transform = 'scale(1)'; }, 100); showNotification('Quick Scan Started', true); // Simulate scanning animation deviceCards.forEach((card, index) => { setTimeout(() => { card.style.transition = 'all 0.2s ease'; card.style.transform = 'scale(0.97)'; setTimeout(() => { card.style.transform = 'scale(1)'; }, 200); }, index * 100); }); }); // Close context menu when clicking elsewhere document.addEventListener('click', function() { const contextMenu = document.getElementById('context-menu'); contextMenu.classList.remove('show'); }); // Context menu actions const contextMenuItems = document.querySelectorAll('.context-menu-item'); contextMenuItems.forEach(item => { item.addEventListener('click', function() { const action = this.dataset.action; const targetDevice = document.getElementById('context-menu').dataset.target; const deviceCard = document.querySelector(`.device-card[data-device="${targetDevice}"]`); const deviceName = deviceCard.querySelector('.device-name').textContent; // Handle different actions switch(action) { case 'schedule': showNotification(`Scheduled ${deviceName}`, true); break; case 'customize': showNotification(`Customizing ${deviceName}`, true); break; case 'details': showNotification(`Viewing details for ${deviceName}`, true); break; case 'remove': deviceCard.style.transition = 'all 0.3s ease'; deviceCard.style.opacity = '0'; deviceCard.style.transform = 'scale(0.9)'; setTimeout(() => { deviceCard.style.display = 'none'; showNotification(`${deviceName} removed`, false); }, 300); break; } }); }); // Notification function function showNotification(message, isSuccess) { // Create notification element const notification = document.createElement('div'); notification.style.position = 'fixed'; notification.style.bottom = '20px'; notification.style.left = '50%'; notification.style.transform = 'translateX(-50%)'; notification.style.backgroundColor = isSuccess ? 'rgba(46, 204, 113, 0.9)' : 'rgba(231, 76, 60, 0.9)'; notification.style.color = 'white'; notification.style.padding = '10px 20px'; notification.style.borderRadius = '6px'; notification.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.2)'; notification.style.zIndex = '1000'; notification.style.fontWeight = '500'; notification.style.backdropFilter = 'blur(5px)'; notification.style.display = 'flex'; notification.style.alignItems = 'center'; notification.style.gap = '8px'; // Add pulse dot const pulseDot = document.createElement('span'); pulseDot.classList.add('pulse-dot'); notification.appendChild(pulseDot); // Add message const messageSpan = document.createElement('span'); messageSpan.textContent = message; notification.appendChild(messageSpan); // Add to body document.body.appendChild(notification); // Animate in notification.style.opacity = '0'; notification.style.transform = 'translateX(-50%) translateY(20px)'; notification.style.transition = 'all 0.3s ease'; setTimeout(() => { notification.style.opacity = '1'; notification.style.transform = 'translateX(-50%) translateY(0)'; }, 10); // Remove after 3 seconds setTimeout(() => { notification.style.opacity = '0'; notification.style.transform = 'translateX(-50%) translateY(20px)'; setTimeout(() => { notification.remove(); }, 300); }, 3000); } }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root { --primary: #1a365d; --secondary: #0073e6; --accent: #00a86b; --light: #f7faff; --dark: #0a1626; --error: #e63946; --success: #2ecc71; --neutral: #c8d1e0; --shadow: rgba(10, 22, 38, 0.16); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { width: 100%; height: 100vh; background-color: #f0f5ff; display: flex; justify-content: center; align-items: center; position: relative; overflow: hidden; } .app-container { width: 100%; max-width: 700px; height: 700px; background: linear-gradient(135deg, #ffffff 0%, #f7faff 100%); border-radius: 24px; box-shadow: 0 12px 30px var(--shadow); position: relative; overflow: hidden; display: flex; flex-direction: column; } .app-header { width: 100%; padding: 24px; background-color: var(--primary); color: white; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } .app-header h1 { font-size: 1.4rem; font-weight: 600; } .profile-icon { width: 32px; height: 32px; background-color: var(--light); border-radius: 50%; display: flex; justify-content: center; align-items: center; color: var(--primary); font-weight: bold; font-size: 14px; } .account-overview { padding: 25px; background: linear-gradient(135deg, var(--primary) 0%, #2c4c7c 100%); color: white; border-radius: 20px; margin: 20px; box-shadow: 0 8px 20px rgba(26, 54, 93, 0.2); position: relative; overflow: hidden; } .account-overview::before { content: ''; position: absolute; top: 0; right: 0; width: 150px; height: 150px; background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 70%); border-radius: 50%; } .account-label { font-size: 0.85rem; opacity: 0.85; margin-bottom: 5px; font-weight: 500; } .account-number { display: flex; align-items: center; gap: 8px; margin-bottom: 20px; } .account-number span { font-size: 1.1rem; letter-spacing: 1px; font-weight: 500; } .balance-amount { font-size: 2.2rem; font-weight: 700; margin-bottom: 5px; } .available-credit { font-size: 0.9rem; opacity: 0.85; } .recent-transactions { padding: 0 20px; margin-top: 10px; flex: 1; overflow-y: auto; } .section-title { font-size: 1rem; color: var(--primary); font-weight: 600; margin-bottom: 15px; } .transaction-list { list-style: none; } .transaction-item { padding: 15px; border-bottom: 1px solid var(--neutral); display: flex; justify-content: space-between; align-items: center; } .transaction-details { display: flex; align-items: center; gap: 12px; } .transaction-icon { width: 36px; height: 36px; border-radius: 10px; background-color: rgba(0, 115, 230, 0.1); display: flex; justify-content: center; align-items: center; color: var(--secondary); } .transaction-merchant { font-weight: 500; color: var(--dark); font-size: 0.95rem; margin-bottom: 3px; } .transaction-date { font-size: 0.8rem; color: #5e6e82; } .transaction-amount { font-weight: 600; font-size: 1rem; } .amount-negative { color: var(--error); } .amount-positive { color: var(--success); } /* FAB and Modal Styles */ .fab { position: absolute; bottom: 36px; right: 36px; width: 60px; height: 60px; border-radius: 50%; background-color: var(--secondary); color: white; display: flex; justify-content: center; align-items: center; box-shadow: 0 6px 16px rgba(0, 115, 230, 0.3); cursor: pointer; transition: transform 0.15s ease, box-shadow 0.15s ease; overflow: hidden; z-index: 100; } .fab:hover { background-color: #0068d0; box-shadow: 0 8px 24px rgba(0, 115, 230, 0.4); } .fab:active { transform: scale(0.92); } .fab svg { width: 24px; height: 24px; fill: none; stroke: white; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } .fab-ripple { position: absolute; width: 100%; height: 100%; background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 70%); border-radius: 50%; transform: scale(0); opacity: 1; pointer-events: none; } .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(10, 22, 38, 0.6); backdrop-filter: blur(4px); display: flex; justify-content: center; align-items: center; opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease; z-index: 1000; } .modal.active { opacity: 1; visibility: visible; } .modal-content { width: 90%; max-width: 400px; background: white; border-radius: 20px; padding: 25px; transform: translateY(30px); opacity: 0; transition: transform 0.4s ease, opacity 0.4s ease; box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15); } .modal.active .modal-content { transform: translateY(0); opacity: 1; } .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .modal-title { font-size: 1.3rem; font-weight: 600; color: var(--primary); } .close-modal { background: none; border: none; cursor: pointer; padding: 5px; color: #5e6e82; display: flex; align-items: center; justify-content: center; } .action-buttons { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 25px; } .action-button { padding: 20px 15px; border-radius: 12px; border: none; background-color: #f7faff; display: flex; flex-direction: column; align-items: center; gap: 12px; cursor: pointer; transition: background-color 0.2s ease, transform 0.2s ease; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); } .action-button:hover { background-color: #edf2fd; transform: translateY(-2px); } .action-button:active { transform: translateY(1px); } .action-button.transfer { border-left: 3px solid var(--secondary); } .action-button.balance { border-left: 3px solid var(--accent); } .action-icon { width: 40px; height: 40px; border-radius: 10px; display: flex; justify-content: center; align-items: center; } .action-icon.transfer { background-color: rgba(0, 115, 230, 0.1); color: var(--secondary); } .action-icon.balance { background-color: rgba(0, 168, 107, 0.1); color: var(--accent); } .action-label { font-weight: 600; font-size: 0.95rem; color: var(--dark); } .action-description { font-size: 0.8rem; color: #5e6e82; text-align: center; } .transfer-form, .balance-form { display: none; } .active-form { display: block; animation: fadeIn 0.3s ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .form-group { margin-bottom: 16px; } .form-label { display: block; margin-bottom: 8px; font-size: 0.85rem; font-weight: 500; color: #455571; } .form-control { width: 100%; padding: 12px 15px; border: 1px solid var(--neutral); border-radius: 10px; font-size: 0.95rem; transition: border-color 0.2s ease, box-shadow 0.2s ease; } .form-control:focus { outline: none; border-color: var(--secondary); box-shadow: 0 0 0 3px rgba(0, 115, 230, 0.15); } .amount-input-wrapper { position: relative; } .amount-input-wrapper::before { content: '$'; position: absolute; left: 15px; top: 50%; transform: translateY(-50%); color: #5e6e82; font-weight: 500; } .amount-input { padding-left: 30px; } .btn { display: inline-flex; align-items: center; justify-content: center; padding: 12px 24px; border-radius: 10px; font-weight: 600; font-size: 0.95rem; cursor: pointer; transition: background-color 0.2s ease, transform 0.1s ease; border: none; } .btn-primary { background-color: var(--secondary); color: white; } .btn-primary:hover { background-color: #0068d0; } .btn-primary:active { transform: scale(0.98); } .btn-secondary { background-color: #e6ecf7; color: var(--primary); } .btn-secondary:hover { background-color: #d9e1f1; } .balance-results { margin-top: 20px; padding: 20px; background-color: #f7faff; border-radius: 10px; border-left: 3px solid var(--accent); } .balance-title { font-size: 0.9rem; font-weight: 500; color: #455571; margin-bottom: 10px; } .balance-amount-large { font-size: 1.8rem; font-weight: 700; color: var(--primary); margin-bottom: 5px; } .balance-details { display: flex; justify-content: space-between; margin-top: 15px; padding-top: 15px; border-top: 1px solid var(--neutral); } .balance-detail { flex: 1; } .detail-label { font-size: 0.8rem; color: #5e6e82; margin-bottom: 5px; } .detail-value { font-size: 0.95rem; font-weight: 600; color: var(--dark); } .form-actions { display: flex; justify-content: space-between; gap: 10px; margin-top: 24px; } .success-message { display: none; background-color: rgba(46, 204, 113, 0.1); border-left: 3px solid var(--success); border-radius: 10px; padding: 15px; margin-top: 20px; text-align: center; animation: fadeIn 0.3s ease; } .success-message svg { color: var(--success); margin-bottom: 10px; } .success-title { font-weight: 600; color: var(--dark); margin-bottom: 5px; } .success-subtitle { font-size: 0.85rem; color: #5e6e82; } @media (max-width: 500px) { .action-buttons { grid-template-columns: 1fr; } .balance-amount { font-size: 1.8rem; } .app-header h1 { font-size: 1.2rem; } .modal-content { padding: 20px; } } </style> </head> <body> <div class="app-container"> <div class="app-header"> <h1>SecureBank Pro</h1> <div class="profile-icon">JD</div> </div> <div class="account-overview"> <div class="account-label">Premium Checking</div> <div class="account-number"> <span>•••• 4582</span> </div> <div class="balance-amount">$24,731.65</div> <div class="available-credit">Available today</div> </div> <div class="recent-transactions"> <h2 class="section-title">Recent Transactions</h2> <ul class="transaction-list"> <li class="transaction-item"> <div class="transaction-details"> <div class="transaction-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="2" y="5" width="20" height="14" rx="2" /> <line x1="2" y1="10" x2="22" y2="10" /> </svg> </div> <div> <div class="transaction-merchant">Amazon</div> <div class="transaction-date">Today, 10:24 AM</div> </div> </div> <div class="transaction-amount amount-negative">-$34.99</div> </li> <li class="transaction-item"> <div class="transaction-details"> <div class="transaction-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 2L2 7l10 5 10-5-10-5z" /> <path d="M2 17l10 5 10-5" /> <path d="M2 12l10 5 10-5" /> </svg> </div> <div> <div class="transaction-merchant">Salary Deposit</div> <div class="transaction-date">Mar 15, 9:00 AM</div> </div> </div> <div class="transaction-amount amount-positive">+$3,845.00</div> </li> <li class="transaction-item"> <div class="transaction-details"> <div class="transaction-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10" /> <polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76" /> </svg> </div> <div> <div class="transaction-merchant">Starbucks</div> <div class="transaction-date">Mar 14, 5:32 PM</div> </div> </div> <div class="transaction-amount amount-negative">-$6.45</div> </li> <li class="transaction-item"> <div class="transaction-details"> <div class="transaction-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /> <polyline points="14 2 14 8 20 8" /> <line x1="16" y1="13" x2="8" y2="13" /> <line x1="16" y1="17" x2="8" y2="17" /> <polyline points="10 9 9 9 8 9" /> </svg> </div> <div> <div class="transaction-merchant">Electric Bill</div> <div class="transaction-date">Mar 12, 11:15 AM</div> </div> </div> <div class="transaction-amount amount-negative">-$152.33</div> </li> <li class="transaction-item"> <div class="transaction-details"> <div class="transaction-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path> <circle cx="9" cy="7" r="4"></circle> <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path> <path d="M16 3.13a4 4 0 0 1 0 7.75"></path> </svg> </div> <div> <div class="transaction-merchant">Transfer to Sarah</div> <div class="transaction-date">Mar 10, 3:46 PM</div> </div> </div> <div class="transaction-amount amount-negative">-$350.00</div> </li> </ul> </div> <div class="fab" id="fabButton"> <div class="fab-ripple" id="fabRipple"></div> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="12" y1="5" x2="12" y2="19"></line> <line x1="5" y1="12" x2="19" y2="12"></line> </svg> </div> </div> <div class="modal" id="actionModal"> <div class="modal-content"> <div class="modal-header"> <h2 class="modal-title">Quick Actions</h2> <button class="close-modal" id="closeModal"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line> </svg> </button> </div> <div class="action-buttons"> <button class="action-button transfer" id="transferBtn"> <div class="action-icon transfer"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="12" y1="5" x2="12" y2="19"></line> <polyline points="19 12 12 19 5 12"></polyline> </svg> </div> <span class="action-label">Transfer Money</span> <span class="action-description">Send to accounts or contacts</span> </button> <button class="action-button balance" id="balanceBtn"> <div class="action-icon balance"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect> <path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path> </svg> </div> <span class="action-label">Check Balance</span> <span class="action-description">View detailed account info</span> </button> </div> <div class="transfer-form" id="transferForm"> <div class="form-group"> <label class="form-label" for="recipient">Recipient</label> <input type="text" id="recipient" class="form-control" placeholder="Email, phone, or name"> </div> <div class="form-group"> <label class="form-label" for="amount">Amount</label> <div class="amount-input-wrapper"> <input type="text" id="amount" class="form-control amount-input" placeholder="0.00"> </div> </div> <div class="form-group"> <label class="form-label" for="note">Note (Optional)</label> <input type="text" id="note" class="form-control" placeholder="What's this for?"> </div> <div class="form-actions"> <button class="btn btn-secondary" id="cancelTransfer">Cancel</button> <button class="btn btn-primary" id="confirmTransfer">Send Money</button> </div> <div class="success-message" id="transferSuccess"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> <div class="success-title">Transfer Successful</div> <div class="success-subtitle">Your money is on its way!</div> </div> </div> <div class="balance-form" id="balanceForm"> <div class="form-group"> <label class="form-label" for="accountSelect">Select Account</label> <select id="accountSelect" class="form-control"> <option value="checking">Premium Checking •••• 4582</option> <option value="savings">High-Yield Savings •••• 7891</option> <option value="credit">Visa Signature •••• 3456</option> </select> </div> <div class="form-actions"> <button class="btn btn-secondary" id="cancelBalance">Cancel</button> <button class="btn btn-primary" id="checkBalance">Check Balance</button> </div> <div class="balance-results" id="balanceResults" style="display: none;"> <div class="balance-title">Current Balance</div> <div class="balance-amount-large">$24,731.65</div> <div class="detail-label">Available as of March 17, 2023 at 1:45 PM</div> <div class="balance-details"> <div class="balance-detail"> <div class="detail-label">Pending</div> <div class="detail-value">$145.30</div> </div> <div class="balance-detail"> <div class="detail-label">Available</div> <div class="detail-value">$24,586.35</div> </div> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const fabButton = document.getElementById('fabButton'); const fabRipple = document.getElementById('fabRipple'); const actionModal = document.getElementById('actionModal'); const closeModal = document.getElementById('closeModal'); const transferBtn = document.getElementById('transferBtn'); const balanceBtn = document.getElementById('balanceBtn'); const transferForm = document.getElementById('transferForm'); const balanceForm = document.getElementById('balanceForm'); const cancelTransfer = document.getElementById('cancelTransfer'); const confirmTransfer = document.getElementById('confirmTransfer'); const transferSuccess = document.getElementById('transferSuccess'); const cancelBalance = document.getElementById('cancelBalance'); const checkBalance = document.getElementById('checkBalance'); const balanceResults = document.getElementById('balanceResults'); // FAB button ripple effect fabButton.addEventListener('click', function(e) { // Create ripple effect fabRipple.style.top = '0'; fabRipple.style.left = '0'; fabRipple.style.transform = 'scale(0)'; fabRipple.style.opacity = '1'; // Play ripple animation fabRipple.animate( [ { transform: 'scale(0)', opacity: 1 }, { transform: 'scale(3)', opacity: 0 } ], { duration: 600, easing: 'ease-out' } ); // Contract button slightly fabButton.style.transform = 'scale(0.92)'; setTimeout(() => { fabButton.style.transform = 'scale(1)'; // Show modal after button animation actionModal.classList.add('active'); }, 150); }); // Close modal closeModal.addEventListener('click', function() { actionModal.classList.remove('active'); // Reset forms resetForms(); }); // Close modal when clicking outside actionModal.addEventListener('click', function(e) { if (e.target === actionModal) { actionModal.classList.remove('active'); resetForms(); } }); // Transfer button action transferBtn.addEventListener('click', function() { transferForm.classList.add('active-form'); balanceForm.classList.remove('active-form'); balanceResults.style.display = 'none'; transferSuccess.style.display = 'none'; }); // Balance button action balanceBtn.addEventListener('click', function() { balanceForm.classList.add('active-form'); transferForm.classList.remove('active-form'); balanceResults.style.display = 'none'; }); // Cancel transfer cancelTransfer.addEventListener('click', function() { resetForms(); }); // Confirm transfer confirmTransfer.addEventListener('click', function() { const recipientField = document.getElementById('recipient'); const amountField = document.getElementById('amount'); if (recipientField.value.trim() === '' || amountField.value.trim() === '') { // Simple validation - shake inputs if empty if (recipientField.value.trim() === '') { shakeElement(recipientField); } if (amountField.value.trim() === '') { shakeElement(amountField); } return; } // Show success message transferSuccess.style.display = 'block'; // Scroll to see success message if needed transferSuccess.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); // Clear form recipientField.value = ''; amountField.value = ''; document.getElementById('note').value = ''; }); // Cancel balance check cancelBalance.addEventListener('click', function() { resetForms(); }); // Check balance checkBalance.addEventListener('click', function() { balanceResults.style.display = 'block'; // Scroll to see results if needed balanceResults.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }); // Reset forms function function resetForms() { transferForm.classList.remove('active-form'); balanceForm.classList.remove('active-form'); transferSuccess.style.display = 'none'; balanceResults.style.display = 'none'; } // Shake animation for validation function shakeElement(element) { element.animate( [ { transform: 'translateX(0)' }, { transform: 'translateX(-10px)' }, { transform: 'translateX(10px)' }, { transform: 'translateX(-5px)' }, { transform: 'translateX(5px)' }, { transform: 'translateX(0)' } ], { duration: 500, easing: 'ease-in-out' } ); // Add and remove error class element.style.borderColor = '#e63946'; setTimeout(() => { element.style.borderColor = ''; }, 500); } // Amount input formatting const amountInput = document.getElementById('amount'); amountInput.addEventListener('input', function(e) { // Only allow numbers and a single decimal point const value = e.target.value; const sanitized = value.replace(/[^0-9.]/g, ''); // Ensure only one decimal point const parts = sanitized.split('.'); if (parts.length > 2) { e.target.value = parts[0] + '.' + parts.slice(1).join(''); } else { e.target.value = sanitized; } // Limit to 2 decimal places if (parts.length > 1 && parts[1].length > 2) { e.target.value = parts[0] + '.' + parts[1].substring(0, 2); } }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Gamer Portal FAB</title> <style> *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } :root { --neon-pink: #ff2d74; --neon-blue: #25d4ff; --neon-green: #39ff14; --neon-purple: #bd00ff; --dark-bg: #0a0a1a; } body { background-color: var(--dark-bg); background-image: radial-gradient(circle at 20% 30%, rgba(37, 212, 255, 0.1) 0%, transparent 35%), radial-gradient(circle at 80% 70%, rgba(189, 0, 255, 0.1) 0%, transparent 35%); font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; height: 100vh; display: flex; justify-content: center; align-items: center; overflow: hidden; color: white; position: relative; } .grid-bg { position: absolute; width: 100%; height: 100%; background-image: linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px); background-size: 20px 20px; z-index: -1; opacity: 0.5; } .fab-container { position: fixed; bottom: 30px; right: 30px; z-index: 999; } .fab { width: 80px; height: 80px; border-radius: 50%; background: linear-gradient(45deg, var(--neon-blue), var(--neon-purple)); display: flex; justify-content: center; align-items: center; box-shadow: 0 0 15px rgba(189, 0, 255, 0.7), 0 0 30px rgba(37, 212, 255, 0.4); cursor: pointer; position: relative; transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); overflow: hidden; } .fab::before { content: ''; position: absolute; width: 100%; height: 100%; top: 0; left: 0; background: linear-gradient(45deg, var(--neon-blue), var(--neon-purple)); opacity: 0.7; filter: blur(15px); z-index: -1; } .fab-icon { width: 40px; height: 40px; position: relative; z-index: 1; } .pixel-plus { position: relative; width: 100%; height: 100%; } .pixel-plus::before, .pixel-plus::after { content: ''; position: absolute; background-color: white; } .pixel-plus::before { width: 100%; height: 25%; top: 37.5%; left: 0; } .pixel-plus::after { width: 25%; height: 100%; top: 0; left: 37.5%; } .pixel-dots { position: absolute; width: 5px; height: 5px; background: white; box-shadow: 10px 0 0 white, 20px 0 0 white, 30px 0 0 white, 0 10px 0 white, 10px 10px 0 white, 20px 10px 0 white, 30px 10px 0 white, 0 20px 0 white, 10px 20px 0 white, 20px 20px 0 white, 30px 20px 0 white, 0 30px 0 white, 10px 30px 0 white, 20px 30px 0 white, 30px 30px 0 white; opacity: 0.2; transform: scale(0.5) translate(-50%, -50%); left: 50%; top: 50%; } .fab-pulse { position: absolute; width: 100%; height: 100%; border-radius: 50%; background: rgba(255, 255, 255, 0.3); z-index: -1; transform: scale(0.8); opacity: 0; animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(0.8); opacity: 0.7; } 100% { transform: scale(1.5); opacity: 0; } } .fab-menu { position: absolute; bottom: 95px; right: 0; display: flex; flex-direction: column; align-items: flex-end; opacity: 0; transform: translateY(20px); pointer-events: none; transition: all 0.3s ease; } .fab-menu.active { opacity: 1; transform: translateY(0); pointer-events: all; } .menu-item { display: flex; align-items: center; margin-bottom: 15px; transform: scale(0); opacity: 0; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .menu-item.show { transform: scale(1); opacity: 1; } .menu-button { width: 60px; height: 60px; border-radius: 50%; display: flex; justify-content: center; align-items: center; cursor: pointer; background: rgba(10, 10, 26, 0.8); border: 2px solid; position: relative; overflow: hidden; transition: all 0.3s ease; } .menu-text { background: rgba(10, 10, 26, 0.9); color: white; padding: 8px 15px; border-radius: 20px; margin-right: 15px; font-weight: bold; font-size: 14px; letter-spacing: 0.5px; white-space: nowrap; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2); border: 1px solid rgba(255, 255, 255, 0.1); } .menu-item:nth-child(1) .menu-button { border-color: var(--neon-green); box-shadow: 0 0 10px rgba(57, 255, 20, 0.5); } .menu-item:nth-child(2) .menu-button { border-color: var(--neon-blue); box-shadow: 0 0 10px rgba(37, 212, 255, 0.5); } .menu-item:nth-child(3) .menu-button { border-color: var(--neon-pink); box-shadow: 0 0 10px rgba(255, 45, 116, 0.5); } .menu-item:nth-child(4) .menu-button { border-color: var(--neon-purple); box-shadow: 0 0 10px rgba(189, 0, 255, 0.5); } .menu-icon { width: 24px; height: 24px; position: relative; z-index: 1; color: white; filter: drop-shadow(0 0 5px currentColor); } .menu-item:nth-child(1) .menu-icon { color: var(--neon-green); } .menu-item:nth-child(2) .menu-icon { color: var(--neon-blue); } .menu-item:nth-child(3) .menu-icon { color: var(--neon-pink); } .menu-item:nth-child(4) .menu-icon { color: var(--neon-purple); } .menu-button:hover { transform: scale(1.1); } .menu-button::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: currentColor; opacity: 0.1; } .menu-button::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: 0.5s; } .menu-button:hover::before { left: 100%; } .fab:hover { transform: rotate(90deg) scale(1.1); } .fab.active { transform: rotate(45deg) scale(1.1); } .notification { position: absolute; top: 10px; left: 0; right: 0; margin: 0 auto; width: max-content; background: rgba(10, 10, 26, 0.95); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 10px; padding: 15px 25px; color: white; font-size: 16px; box-shadow: 0 0 20px rgba(37, 212, 255, 0.4); opacity: 0; transform: translateY(-20px); transition: all 0.3s ease; display: flex; align-items: center; z-index: 1000; } .notification.show { opacity: 1; transform: translateY(0); } .notification-icon { margin-right: 10px; color: var(--neon-blue); } .pixels { position: absolute; width: 4px; height: 4px; background: white; opacity: 0.8; box-shadow: 0 0 5px currentColor; } .helper-text { position: absolute; bottom: 130px; right: 90px; padding: 10px 20px; background: rgba(10, 10, 26, 0.8); border-radius: 30px; color: white; font-size: 14px; opacity: 0.7; transform: scale(0); transition: all 0.3s ease; transform-origin: right bottom; border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: 0 0 10px rgba(37, 212, 255, 0.3); } .helper-text.show { transform: scale(1); } @media (max-width: 600px) { .fab-container { bottom: 20px; right: 20px; } .fab { width: 70px; height: 70px; } .fab-icon { width: 35px; height: 35px; } .menu-button { width: 50px; height: 50px; } .menu-text { font-size: 12px; padding: 6px 12px; } .helper-text { right: 80px; font-size: 12px; padding: 8px 15px; } } /* Game overlay styles */ .game-preview { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.85); display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 1001; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; } .game-preview.show { opacity: 1; pointer-events: all; } .game-container { width: 80%; max-width: 500px; padding: 20px; background: rgba(15, 15, 40, 0.9); border-radius: 15px; border: 2px solid; border-image: linear-gradient(45deg, var(--neon-blue), var(--neon-purple)) 1; box-shadow: 0 0 30px rgba(37, 212, 255, 0.3); text-align: center; position: relative; overflow: hidden; } .game-title { font-size: 24px; margin-bottom: 20px; color: white; text-shadow: 0 0 10px rgba(37, 212, 255, 0.8); letter-spacing: 1px; } .game-image { width: 100%; height: 200px; background-size: cover; background-position: center; border-radius: 8px; margin-bottom: 20px; position: relative; overflow: hidden; } .game-image::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(45deg, rgba(37, 212, 255, 0.2), rgba(189, 0, 255, 0.2)); } .game-image::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(transparent 90%, rgba(10, 10, 26, 0.8)); } .game-desc { color: rgba(255, 255, 255, 0.8); font-size: 14px; margin-bottom: 25px; line-height: 1.5; } .game-cta { display: inline-block; padding: 12px 30px; background: linear-gradient(45deg, var(--neon-blue), var(--neon-purple)); border: none; border-radius: 30px; color: white; font-weight: bold; cursor: pointer; transition: all 0.3s ease; font-size: 16px; text-transform: uppercase; letter-spacing: 1px; box-shadow: 0 0 15px rgba(37, 212, 255, 0.5); position: relative; overflow: hidden; } .game-cta:hover { transform: scale(1.05); box-shadow: 0 0 20px rgba(37, 212, 255, 0.7); } .game-cta::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); transition: 0.5s; } .game-cta:hover::before { left: 100%; } .close-preview { position: absolute; top: 15px; right: 15px; width: 30px; height: 30px; cursor: pointer; z-index: 2; } .close-preview::before, .close-preview::after { content: ''; position: absolute; top: 14px; width: 30px; height: 2px; background: white; } .close-preview::before { transform: rotate(45deg); } .close-preview::after { transform: rotate(-45deg); } .player-count { position: absolute; top: 15px; right: 15px; background: rgba(10, 10, 26, 0.8); color: var(--neon-green); padding: 5px 10px; border-radius: 20px; font-size: 12px; font-weight: bold; z-index: 1; border: 1px solid rgba(57, 255, 20, 0.3); } .pixel-border { position: absolute; top: -2px; left: -2px; width: calc(100% + 4px); height: calc(100% + 4px); pointer-events: none; } .pixel-border::before, .pixel-border::after { content: ''; position: absolute; width: 8px; height: 8px; } .pixel-border::before { top: 0; left: 0; box-shadow: 0 0 0 white, 8px 0 0 white, 16px 0 0 white, 24px 0 0 white, 32px 0 0 white, calc(100% - 32px) 0 0 white, calc(100% - 24px) 0 0 white, calc(100% - 16px) 0 0 white, calc(100% - 8px) 0 0 white, calc(100% - 0px) 0 0 white, 0 8px 0 white, 0 16px 0 white, 0 24px 0 white, 0 32px 0 white, 0 calc(100% - 32px) 0 white, 0 calc(100% - 24px) 0 white, 0 calc(100% - 16px) 0 white, 0 calc(100% - 8px) 0 white, 0 calc(100% - 0px) 0 white; } .pixel-border::after { bottom: 0; right: 0; box-shadow: 0 0 0 white, -8px 0 0 white, -16px 0 0 white, -24px 0 0 white, -32px 0 0 white, calc(-100% + 32px) 0 0 white, calc(-100% + 24px) 0 0 white, calc(-100% + 16px) 0 0 white, calc(-100% + 8px) 0 0 white, calc(-100% + 0px) 0 0 white, 0 -8px 0 white, 0 -16px 0 white, 0 -24px 0 white, 0 -32px 0 white, 0 calc(-100% + 32px) 0 white, 0 calc(-100% + 24px) 0 white, 0 calc(-100% + 16px) 0 white, 0 calc(-100% + 8px) 0 white, 0 calc(-100% + 0px) 0 white; } .timer { position: absolute; bottom: 15px; left: 15px; color: var(--neon-pink); font-size: 12px; font-weight: bold; z-index: 1; display: flex; align-items: center; } .timer-icon { margin-right: 5px; animation: pulse-timer 1s infinite alternate; } @keyframes pulse-timer { from { opacity: 0.5; } to { opacity: 1; } } </style> </head> <body> <div class="grid-bg"></div> <div class="notification" id="notification"> <div class="notification-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 12L3 20l3.5-8L3 4l19 8z"></path> <path d="M10 12L13 12"></path> </svg> </div> <span id="notification-text">Galaxy Defenders tournament starts in 10 minutes!</span> </div> <div class="helper-text" id="helper-text"> Click to explore new games! </div> <div class="fab-container"> <div class="fab" id="fab"> <div class="fab-pulse"></div> <div class="pixel-dots"></div> <div class="fab-icon"> <div class="pixel-plus"></div> </div> </div> <div class="fab-menu" id="fab-menu"> <div class="menu-item" data-game="galaxy-defenders"> <div class="menu-text">Galaxy Defenders Tournament</div> <div class="menu-button"> <div class="menu-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9"></path> </svg> </div> </div> </div> <div class="menu-item" data-game="pixel-racer"> <div class="menu-text">Pixel Racer Ultimate</div> <div class="menu-button"> <div class="menu-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M17 4h1a2 2 0 012 2v1"></path> <path d="M4 7V6a2 2 0 012-2h1"></path> <path d="M7 20H6a2 2 0 01-2-2v-1"></path> <path d="M20 17v1a2 2 0 01-2 2h-1"></path> <rect x="9" y="9" width="6" height="6"></rect> </svg> </div> </div> </div> <div class="menu-item" data-game="crypto-quest"> <div class="menu-text">Crypto Quest Raids</div> <div class="menu-button"> <div class="menu-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 2L2 7l10 5 10-5-10-5z"></path> <path d="M2 17l10 5 10-5"></path> <path d="M2 12l10 5 10-5"></path> </svg> </div> </div> </div> <div class="menu-item" data-game="neon-arena"> <div class="menu-text">Neon Arena Battle</div> <div class="menu-button"> <div class="menu-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon> </svg> </div> </div> </div> </div> </div> <div class="game-preview" id="game-preview"> <div class="game-container"> <div class="close-preview" id="close-preview"></div> <div class="pixel-border"></div> <h2 class="game-title" id="game-title">Galaxy Defenders Tournament</h2> <div class="game-image" id="game-image" style="background-image: url('https://source.unsplash.com/random/800x400/?space,game');"> <div class="player-count">1,287 Players Online</div> <div class="timer"> <span class="timer-icon">⏰</span> <span>Tournament starts in 10:00</span> </div> </div> <p class="game-desc" id="game-desc">Join the ultimate space battle tournament! Compete against players from around the world in a fast-paced arcade shooter with pixel-perfect controls and retro visuals.</p> <button class="game-cta">Launch Game</button> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const fab = document.getElementById('fab'); const fabMenu = document.getElementById('fab-menu'); const menuItems = document.querySelectorAll('.menu-item'); const notification = document.getElementById('notification'); const notificationText = document.getElementById('notification-text'); const helperText = document.getElementById('helper-text'); const gamePreview = document.getElementById('game-preview'); const gameTitle = document.getElementById('game-title'); const gameDesc = document.getElementById('game-desc'); const gameImage = document.getElementById('game-image'); const closePreview = document.getElementById('close-preview'); let isOpen = false; // Create pixel animation const createPixels = (event) => { const colors = ['var(--neon-pink)', 'var(--neon-blue)', 'var(--neon-green)', 'var(--neon-purple)']; for (let i = 0; i < 20; i++) { const pixel = document.createElement('div'); pixel.classList.add('pixels'); // Random position around the cursor const x = event.clientX; const y = event.clientY; // Random offset const offsetX = Math.random() * 60 - 30; const offsetY = Math.random() * 60 - 30; pixel.style.left = (x + offsetX) + 'px'; pixel.style.top = (y + offsetY) + 'px'; pixel.style.color = colors[Math.floor(Math.random() * colors.length)]; document.body.appendChild(pixel); // Animate and remove const angle = Math.random() * Math.PI * 2; const speed = 2 + Math.random() * 3; let posX = x + offsetX; let posY = y + offsetY; let opacity = 1; const animate = () => { posX += Math.cos(angle) * speed; posY += Math.sin(angle) * speed; opacity -= 0.02; pixel.style.left = posX + 'px'; pixel.style.top = posY + 'px'; pixel.style.opacity = opacity; if (opacity > 0) { requestAnimationFrame(animate); } else { pixel.remove(); } }; requestAnimationFrame(animate); } }; // Show helper text after a delay setTimeout(() => { helperText.classList.add('show'); setTimeout(() => { helperText.classList.remove('show'); }, 4000); }, 2000); // Show notification after a delay setTimeout(() => { notification.classList.add('show'); setTimeout(() => { notification.classList.remove('show'); }, 5000); }, 3000); // Toggle FAB menu fab.addEventListener('click', (e) => { isOpen = !isOpen; fab.classList.toggle('active', isOpen); fabMenu.classList.toggle('active', isOpen); // Create pixel animation createPixels(e); // Helper text disappears when FAB is clicked helperText.classList.remove('show'); // Show menu items with staggered animation if (isOpen) { menuItems.forEach((item, index) => { setTimeout(() => { item.classList.add('show'); }, 50 * index); }); } else { menuItems.forEach((item) => { item.classList.remove('show'); }); } }); // Game data const gameData = { 'galaxy-defenders': { title: 'Galaxy Defenders Tournament', desc: 'Join the ultimate space battle tournament! Compete against players from around the world in a fast-paced arcade shooter with pixel-perfect controls and retro visuals.', image: 'https://source.unsplash.com/random/800x400/?space,game' }, 'pixel-racer': { title: 'Pixel Racer Ultimate', desc: 'Race through neon-lit cyberpunk tracks in this high-octane multiplayer racing game. Customize your vehicle with pixel mods and claim your spot on the global leaderboards!', image: 'https://source.unsplash.com/random/800x400/?racing,neon' }, 'crypto-quest': { title: 'Crypto Quest Raids', desc: 'Embark on epic dungeon raids with up to 24 players! Solve puzzles, defeat bosses, and collect rare NFT loot in this blockchain-powered cooperative adventure.', image: 'https://source.unsplash.com/random/800x400/?dungeon,fantasy' }, 'neon-arena': { title: 'Neon Arena Battle', desc: 'Enter the arena for 5v5 team-based combat with a variety of unique champions. Master your skills in this fast-paced brawler with stunning neon visuals and deep strategy.', image: 'https://source.unsplash.com/random/800x400/?cyberpunk,neon' } }; // Show game preview when menu item is clicked menuItems.forEach(item => { item.addEventListener('click', (e) => { createPixels(e); const gameId = item.getAttribute('data-game'); const game = gameData[gameId]; gameTitle.textContent = game.title; gameDesc.textContent = game.desc; gameImage.style.backgroundImage = `url('${game.image}')`; gamePreview.classList.add('show'); // Close menu fab.classList.remove('active'); fabMenu.classList.remove('active'); menuItems.forEach(menuItem => { menuItem.classList.remove('show'); }); isOpen = false; }); }); // Close preview closePreview.addEventListener('click', () => { gamePreview.classList.remove('show'); }); // Close menu when clicking outside document.addEventListener('click', (e) => { if (isOpen && !fab.contains(e.target) && !fabMenu.contains(e.target)) { fab.classList.remove('active'); fabMenu.classList.remove('active'); menuItems.forEach(item => { item.classList.remove('show'); }); isOpen = false; } }); // Add hover pulse effect to FAB fab.addEventListener('mouseenter', () => { fab.querySelector('.fab-pulse').style.animation = 'none'; void fab.querySelector('.fab-pulse').offsetWidth; fab.querySelector('.fab-pulse').style.animation = 'pulse 1s infinite'; }); fab.addEventListener('mouseleave', () => { fab.querySelector('.fab-pulse').style.animation = 'pulse 2s infinite'; }); }); </script> </body> </html>