Lists are an essential tool for organizing information, making it easier to digest and understand. Whether you're jotting down a grocery list or outlining a project plan, lists help streamline tasks and improve productivity.
In this article, we'll explore ten diverse examples of lists, showcasing their versatility and practical applications in everyday life. From to-do lists to bucket lists, discover how different types of lists can enhance your efficiency and keep you on track.
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 projects with Subframe's drag-and-drop interface and intuitive, responsive canvas. Create pixel-perfect UIs effortlessly, every time.
Loved by professionals, Subframe ensures your designs are both stunning and functional. 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
Ready to elevate your UI designs? With Subframe, you can create pixel-perfect interfaces, including lists, in minutes. Our drag-and-drop editor and beautifully crafted components make designing efficient and effortless.
Don't wait—start creating stunning UIs right away. Start for free today!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Taskify Pro</title> <style> :root { --primary: #2D3250; --secondary: #7077A1; --accent: #F6B17A; --accent-hover: #f9c498; --light: #f7f9fc; --dark: #424242; --completed: #8eca9f; --high: #f87171; --medium: #f59e0b; --low: #60a5fa; --shadow: 0 4px 12px rgba(0, 0, 0, 0.08); --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: var(--light); color: var(--dark); display: flex; flex-direction: column; align-items: center; justify-content: flex-start; min-height: 100vh; padding: 20px; } .container { width: 100%; max-width: 650px; background-color: white; border-radius: 12px; box-shadow: var(--shadow); overflow: hidden; position: relative; height: 650px; display: flex; flex-direction: column; } .header { padding: 24px 28px; background-color: var(--primary); color: white; position: relative; z-index: 2; } .header h1 { font-size: 24px; font-weight: 600; margin-bottom: 8px; } .header p { font-size: 14px; opacity: 0.9; } .productivity-stats { display: flex; margin-top: 16px; gap: 16px; } .stat { background-color: rgba(255, 255, 255, 0.1); padding: 8px 14px; border-radius: 6px; font-size: 12px; font-weight: 500; } .stat span { color: var(--accent); font-weight: 700; margin-left: 4px; } .filter-bar { padding: 16px 28px; background-color: white; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #eaeaea; position: relative; z-index: 1; } .filter-buttons { display: flex; gap: 10px; } .filter-button { padding: 6px 12px; font-size: 12px; border-radius: 6px; border: 1px solid #eaeaea; background-color: white; cursor: pointer; transition: var(--transition); font-weight: 500; } .filter-button:hover, .filter-button.active { background-color: var(--accent); border-color: var(--accent); color: white; } .search-bar { position: relative; } .search-bar input { padding: 8px 12px 8px 36px; font-size: 13px; border-radius: 6px; border: 1px solid #eaeaea; width: 180px; transition: var(--transition); } .search-bar input:focus { outline: none; border-color: var(--secondary); width: 220px; } .search-bar i { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: #aaa; font-size: 14px; } .task-list { padding: 10px 20px; overflow-y: auto; flex-grow: 1; } .task-item { padding: 16px; margin: 12px 0; background-color: white; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); display: flex; align-items: center; gap: 16px; transition: var(--transition); position: relative; border-left: 4px solid transparent; } .task-item:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08); } .task-item.high-priority { border-left-color: var(--high); } .task-item.medium-priority { border-left-color: var(--medium); } .task-item.low-priority { border-left-color: var(--low); } .task-item.completed { opacity: 0.75; border-left-color: var(--completed); } .task-item.completed .task-content h3 { text-decoration: line-through; color: #777; } .task-checkbox { position: relative; width: 22px; height: 22px; border-radius: 6px; cursor: pointer; flex-shrink: 0; } .checkbox-input { position: absolute; opacity: 0; cursor: pointer; height: 0; width: 0; } .checkmark { position: absolute; top: 0; left: 0; height: 22px; width: 22px; background-color: white; border: 2px solid #ddd; border-radius: 6px; transition: var(--transition); } .checkbox-input:checked ~ .checkmark { background-color: var(--completed); border-color: var(--completed); } .checkmark:after { content: ""; position: absolute; display: none; left: 7px; top: 3px; width: 5px; height: 10px; border: solid white; border-width: 0 2px 2px 0; transform: rotate(45deg); } .checkbox-input:checked ~ .checkmark:after { display: block; } .task-content { flex-grow: 1; } .task-content h3 { font-size: 15px; font-weight: 500; margin-bottom: 6px; transition: var(--transition); } .task-meta { display: flex; align-items: center; font-size: 12px; color: #777; gap: 12px; } .task-date, .task-category { display: flex; align-items: center; gap: 4px; } .task-date i, .task-category i { font-size: 14px; } .task-priority { display: inline-block; padding: 3px 8px; border-radius: 4px; font-size: 11px; font-weight: 500; color: white; margin-left: auto; text-transform: uppercase; } .high-priority .task-priority { background-color: var(--high); } .medium-priority .task-priority { background-color: var(--medium); } .low-priority .task-priority { background-color: var(--low); } .completed .task-priority { background-color: var(--completed); } .task-actions { display: flex; gap: 8px; opacity: 0; transition: var(--transition); } .task-item:hover .task-actions { opacity: 1; } .task-action-btn { background: none; border: none; color: #aaa; cursor: pointer; font-size: 16px; transition: var(--transition); padding: 4px; } .task-action-btn:hover { color: var(--primary); } .add-task-btn { position: absolute; bottom: 24px; right: 24px; width: 56px; height: 56px; border-radius: 50%; background-color: var(--accent); border: none; color: white; font-size: 24px; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 10px rgba(246, 177, 122, 0.4); transition: var(--transition); z-index: 5; } .add-task-btn:hover { background-color: var(--accent-hover); transform: scale(1.05); } .add-task-form { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 10; opacity: 0; visibility: hidden; transition: var(--transition); } .add-task-form.active { opacity: 1; visibility: visible; } .form-content { background-color: white; padding: 28px; border-radius: 12px; width: 90%; max-width: 500px; transform: translateY(20px); transition: var(--transition); } .add-task-form.active .form-content { transform: translateY(0); } .form-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .form-header h2 { font-size: 20px; font-weight: 600; color: var(--primary); } .close-form { background: none; border: none; font-size: 20px; cursor: pointer; color: #999; transition: var(--transition); } .close-form:hover { color: var(--dark); } .form-group { margin-bottom: 16px; } .form-group label { display: block; margin-bottom: 6px; font-size: 14px; font-weight: 500; color: var(--dark); } .form-control { width: 100%; padding: 10px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; transition: var(--transition); } .form-control:focus { outline: none; border-color: var(--secondary); } .form-row { display: flex; gap: 16px; } .form-row .form-group { flex: 1; } .priority-options { display: flex; gap: 12px; } .priority-option { flex: 1; position: relative; } .priority-input { position: absolute; opacity: 0; width: 0; height: 0; } .priority-label { display: block; padding: 8px; text-align: center; border-radius: 6px; border: 1px solid #ddd; cursor: pointer; transition: var(--transition); font-size: 13px; font-weight: 500; } .priority-input:checked + .priority-label.high { background-color: var(--high); border-color: var(--high); color: white; } .priority-input:checked + .priority-label.medium { background-color: var(--medium); border-color: var(--medium); color: white; } .priority-input:checked + .priority-label.low { background-color: var(--low); border-color: var(--low); color: white; } .priority-input:not(:checked) + .priority-label:hover { background-color: #f5f5f5; } .form-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 20px; } .cancel-btn { padding: 10px 16px; background-color: white; border: 1px solid #ddd; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: 500; transition: var(--transition); } .cancel-btn:hover { background-color: #f5f5f5; } .submit-btn { padding: 10px 20px; background-color: var(--accent); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: 500; transition: var(--transition); } .submit-btn:hover { background-color: var(--accent-hover); } .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 30px; text-align: center; height: 100%; display: none; } .empty-state img { width: 120px; margin-bottom: 20px; opacity: 0.8; } .empty-state h3 { font-size: 18px; font-weight: 600; margin-bottom: 10px; color: var(--primary); } .empty-state p { font-size: 14px; color: #777; max-width: 300px; margin: 0 auto; } .confetti { position: absolute; width: 10px; height: 10px; background-color: var(--accent); opacity: 0; animation: confetti 0.8s ease forwards; pointer-events: none; } @keyframes confetti { 0% { transform: translateY(0) rotate(0); opacity: 1; } 100% { transform: translateY(100px) rotate(720deg); opacity: 0; } } /* Responsive */ @media (max-width: 600px) { .container { width: 100%; border-radius: 0; box-shadow: none; height: calc(100vh - 40px); } .filter-bar { flex-direction: column; gap: 12px; align-items: flex-start; } .filter-buttons { width: 100%; overflow-x: auto; padding-bottom: 4px; } .search-bar { width: 100%; } .search-bar input { width: 100%; } .search-bar input:focus { width: 100%; } .task-actions { opacity: 1; } .form-row { flex-direction: column; gap: 8px; } } /* Scrollbar styling */ .task-list::-webkit-scrollbar { width: 6px; } .task-list::-webkit-scrollbar-track { background: #f1f1f1; } .task-list::-webkit-scrollbar-thumb { background: #ddd; border-radius: 3px; } .task-list::-webkit-scrollbar-thumb:hover { background: #ccc; } /* Loading animation */ .loader { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 48px; height: 48px; border: 5px solid rgba(0,0,0,0.1); border-radius: 50%; border-top-color: var(--accent); animation: spin 1s ease-in-out infinite; display: none; } @keyframes spin { to { transform: translate(-50%, -50%) rotate(360deg); } } .emphasis { font-weight: 600; color: var(--primary); } /* Task Hover Indicator */ .task-item::after { content: ''; position: absolute; bottom: -1px; left: 50%; transform: translateX(-50%); width: 0; height: 3px; background-color: var(--accent); transition: width 0.3s ease; border-radius: 2px; } .task-item:hover::after { width: 90%; } </style> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> </head> <body> <div class="container"> <div class="header"> <h1>Taskify Pro</h1> <p>Manage your tasks with clarity and focus</p> <div class="productivity-stats"> <div class="stat">Completed: <span id="completed-count">0</span></div> <div class="stat">Pending: <span id="pending-count">0</span></div> <div class="stat">Today's Focus: <span id="focus-tasks">3</span></div> </div> </div> <div class="filter-bar"> <div class="filter-buttons"> <button class="filter-button active" data-filter="all">All</button> <button class="filter-button" data-filter="today">Today</button> <button class="filter-button" data-filter="high">High Priority</button> <button class="filter-button" data-filter="completed">Completed</button> </div> <div class="search-bar"> <i class="fas fa-search"></i> <input type="text" id="search-input" placeholder="Search tasks..."> </div> </div> <div class="task-list" id="task-list"> <!-- Task items will be populated here --> </div> <div class="empty-state"> <img src="https://cdn-icons-png.flaticon.com/512/6195/6195678.png" alt="Empty tasks"> <h3>No tasks found</h3> <p>Start adding tasks to boost your productivity!</p> </div> <div class="loader"></div> <button class="add-task-btn" id="add-task-btn"> <i class="fas fa-plus"></i> </button> </div> <div class="add-task-form" id="add-task-form"> <div class="form-content"> <div class="form-header"> <h2>Add New Task</h2> <button class="close-form" id="close-form"> <i class="fas fa-times"></i> </button> </div> <div class="form-group"> <label for="task-title">Task Title</label> <input type="text" id="task-title" class="form-control" placeholder="e.g., Review project proposal"> </div> <div class="form-group"> <label for="task-description">Description (Optional)</label> <textarea id="task-description" class="form-control" rows="3" placeholder="Add more details about this task..."></textarea> </div> <div class="form-row"> <div class="form-group"> <label for="task-date">Due Date</label> <input type="date" id="task-date" class="form-control"> </div> <div class="form-group"> <label for="task-category">Category</label> <select id="task-category" class="form-control"> <option value="Work">Work</option> <option value="Personal">Personal</option> <option value="Health">Health</option> <option value="Finance">Finance</option> <option value="Learning">Learning</option> </select> </div> </div> <div class="form-group"> <label>Priority Level</label> <div class="priority-options"> <div class="priority-option"> <input type="radio" name="priority" id="high-priority" class="priority-input" value="high"> <label for="high-priority" class="priority-label high">High</label> </div> <div class="priority-option"> <input type="radio" name="priority" id="medium-priority" class="priority-input" value="medium" checked> <label for="medium-priority" class="priority-label medium">Medium</label> </div> <div class="priority-option"> <input type="radio" name="priority" id="low-priority" class="priority-input" value="low"> <label for="low-priority" class="priority-label low">Low</label> </div> </div> </div> <div class="form-actions"> <button class="cancel-btn" id="cancel-task">Cancel</button> <button class="submit-btn" id="submit-task">Add Task</button> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Sample task data const tasks = [ { id: 1, title: "Finalize Q3 marketing strategy", date: "2023-09-20", category: "Work", priority: "high", completed: false }, { id: 2, title: "Prepare slides for team presentation", date: "2023-09-15", category: "Work", priority: "medium", completed: false }, { id: 3, title: "Schedule dentist appointment", date: "2023-09-22", category: "Health", priority: "low", completed: true }, { id: 4, title: "Review budget allocation for Q4", date: todayDateString(), category: "Finance", priority: "high", completed: false }, { id: 5, title: "Complete UX certification module", date: todayDateString(), category: "Learning", priority: "medium", completed: false }, { id: 6, title: "Call mom for birthday wishes", date: todayDateString(), category: "Personal", priority: "high", completed: false } ]; // DOM Elements const taskList = document.getElementById('task-list'); const addTaskBtn = document.getElementById('add-task-btn'); const addTaskForm = document.getElementById('add-task-form'); const closeFormBtn = document.getElementById('close-form'); const cancelTaskBtn = document.getElementById('cancel-task'); const submitTaskBtn = document.getElementById('submit-task'); const searchInput = document.getElementById('search-input'); const filterButtons = document.querySelectorAll('.filter-button'); const emptyState = document.querySelector('.empty-state'); const loader = document.querySelector('.loader'); const completedCount = document.getElementById('completed-count'); const pendingCount = document.getElementById('pending-count'); // Current filter let currentFilter = 'all'; // Initialize the task list function initTaskList() { // Show loader briefly to simulate loading data showLoader(); setTimeout(() => { renderTasks(); updateCounters(); hideLoader(); }, 500); } // Render tasks based on current filter function renderTasks() { taskList.innerHTML = ''; let filteredTasks = [...tasks]; // Apply filters if (currentFilter === 'today') { filteredTasks = filteredTasks.filter(task => task.date === todayDateString()); } else if (currentFilter === 'high') { filteredTasks = filteredTasks.filter(task => task.priority === 'high'); } else if (currentFilter === 'completed') { filteredTasks = filteredTasks.filter(task => task.completed); } // Apply search filter if search input has value const searchTerm = searchInput.value.toLowerCase().trim(); if (searchTerm) { filteredTasks = filteredTasks.filter(task => task.title.toLowerCase().includes(searchTerm) || task.category.toLowerCase().includes(searchTerm) ); } // Show empty state if no tasks match filters if (filteredTasks.length === 0) { emptyState.style.display = 'flex'; return; } else { emptyState.style.display = 'none'; } // Render each task filteredTasks.forEach(task => { const taskItem = document.createElement('div'); taskItem.classList.add('task-item', `${task.priority}-priority`); if (task.completed) { taskItem.classList.add('completed'); } taskItem.setAttribute('data-id', task.id); // Format date const dateObj = new Date(task.date); const formattedDate = dateObj.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); const isToday = task.date === todayDateString(); const dateText = isToday ? 'Today' : formattedDate; taskItem.innerHTML = ` <label class="task-checkbox"> <input type="checkbox" class="checkbox-input" ${task.completed ? 'checked' : ''}> <span class="checkmark"></span> </label> <div class="task-content"> <h3>${task.title}</h3> <div class="task-meta"> <div class="task-date"> <i class="far fa-calendar-alt"></i> <span>${dateText}</span> </div> <div class="task-category"> <i class="fas fa-tag"></i> <span>${task.category}</span> </div> <span class="task-priority">${task.priority}</span> </div> </div> <div class="task-actions"> <button class="task-action-btn edit-btn" title="Edit task"> <i class="fas fa-pencil-alt"></i> </button> <button class="task-action-btn delete-btn" title="Delete task"> <i class="fas fa-trash-alt"></i> </button> </div> `; taskList.appendChild(taskItem); }); // Add event listeners to the newly created task items addTaskItemEventListeners(); } // Add event listeners to task items function addTaskItemEventListeners() { // Checkbox event listeners document.querySelectorAll('.checkbox-input').forEach(checkbox => { checkbox.addEventListener('change', function() { const taskItem = this.closest('.task-item'); const taskId = parseInt(taskItem.getAttribute('data-id')); const task = tasks.find(t => t.id === taskId); task.completed = this.checked; if (this.checked) { taskItem.classList.add('completed'); createConfetti(this); } else { taskItem.classList.remove('completed'); } updateCounters(); }); }); // Delete button event listeners document.querySelectorAll('.delete-btn').forEach(btn => { btn.addEventListener('click', function() { const taskItem = this.closest('.task-item'); const taskId = parseInt(taskItem.getAttribute('data-id')); // Animation for deletion taskItem.style.opacity = '0'; taskItem.style.transform = 'translateX(20px)'; setTimeout(() => { // Remove from the array const taskIndex = tasks.findIndex(t => t.id === taskId); if (taskIndex !== -1) { tasks.splice(taskIndex, 1); } // Re-render tasks and update counters renderTasks(); updateCounters(); }, 300); }); }); // Edit button event listeners (simplified for this example) document.querySelectorAll('.edit-btn').forEach(btn => { btn.addEventListener('click', function() { const taskItem = this.closest('.task-item'); const taskId = parseInt(taskItem.getAttribute('data-id')); // Just show a little animation to acknowledge the click taskItem.style.backgroundColor = '#f8f8f8'; setTimeout(() => { taskItem.style.backgroundColor = ''; }, 300); }); }); } // Update task counters function updateCounters() { const completed = tasks.filter(task => task.completed).length; const pending = tasks.length - completed; completedCount.textContent = completed; pendingCount.textContent = pending; } // Filter button event listeners filterButtons.forEach(button => { button.addEventListener('click', function() { // Remove active class from all buttons filterButtons.forEach(btn => btn.classList.remove('active')); // Add active class to clicked button this.classList.add('active'); // Update current filter currentFilter = this.getAttribute('data-filter'); // Re-render tasks renderTasks(); }); }); // Search input event listener searchInput.addEventListener('input', renderTasks); // Add task button event listener addTaskBtn.addEventListener('click', function() { addTaskForm.classList.add('active'); }); // Close form button event listener closeFormBtn.addEventListener('click', function() { addTaskForm.classList.remove('active'); }); // Cancel task button event listener cancelTaskBtn.addEventListener('click', function() { addTaskForm.classList.remove('active'); }); // Submit task button event listener submitTaskBtn.addEventListener('click', function() { const title = document.getElementById('task-title').value.trim(); const date = document.getElementById('task-date').value || todayDateString(); const category = document.getElementById('task-category').value; const priority = document.querySelector('input[name="priority"]:checked').value; if (!title) { // Simple validation document.getElementById('task-title').style.borderColor = 'red'; document.getElementById('task-title').focus(); return; } // Create a new task const newTask = { id: Date.now(), title, date, category, priority, completed: false }; // Add to the array tasks.unshift(newTask); // Clear form document.getElementById('task-title').value = ''; document.getElementById('task-description').value = ''; document.getElementById('task-date').value = ''; document.getElementById('medium-priority').checked = true; // Close form addTaskForm.classList.remove('active'); // Re-render tasks and update counters renderTasks(); updateCounters(); }); // Helper function to get today's date as a string function todayDateString() { const today = new Date(); return today.toISOString().split('T')[0]; } // Function to create confetti effect when task is completed function createConfetti(element) { const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; // Create multiple confetti pieces const colors = ['#F6B17A', '#7077A1', '#2D3250']; for (let i = 0; i < 15; i++) { const confetti = document.createElement('div'); confetti.classList.add('confetti'); // Randomize confetti properties confetti.style.left = `${centerX + (Math.random() * 60 - 30)}px`; confetti.style.top = `${centerY + (Math.random() * 60 - 30)}px`; confetti.style.width = `${Math.random() * 8 + 4}px`; confetti.style.height = `${Math.random() * 8 + 4}px`; confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; confetti.style.animationDuration = `${Math.random() * 0.8 + 0.6}s`; // Add random rotation const rotation = Math.random() * 360; confetti.style.transform = `rotate(${rotation}deg)`; document.body.appendChild(confetti); // Remove confetti after animation setTimeout(() => { document.body.removeChild(confetti); }, 1500); } } // Show/hide loader functions function showLoader() { loader.style.display = 'block'; taskList.style.opacity = '0.5'; } function hideLoader() { loader.style.display = 'none'; taskList.style.opacity = '1'; } // Initialize task list initTaskList(); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Lush Botanicals</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; } :root { --primary: #13654a; --primary-light: #e8f5f0; --accent: #ff6b6b; --text: #333; --text-light: #777; --light: #f8f9fa; --border: #eaeaea; --white: #ffffff; --shadow: 0 4px 12px rgba(0, 0, 0, 0.05); --hover-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } body { background-color: var(--light); color: var(--text); max-width: 700px; margin: 0 auto; height: 700px; overflow-y: auto; scrollbar-width: thin; padding: 0 20px; } /* Custom scrollbar */ body::-webkit-scrollbar { width: 8px; } body::-webkit-scrollbar-track { background: var(--light); } body::-webkit-scrollbar-thumb { background-color: var(--primary); border-radius: 20px; } .container { padding: 24px 0; } header { margin-bottom: 24px; } .store-name { font-size: 28px; font-weight: 700; color: var(--primary); margin-bottom: 6px; display: flex; align-items: center; } .store-name svg { margin-right: 8px; } .store-tagline { font-size: 14px; color: var(--text-light); margin-bottom: 16px; } .categories { display: flex; overflow-x: auto; padding-bottom: 12px; margin-bottom: 16px; scrollbar-width: none; -ms-overflow-style: none; } .categories::-webkit-scrollbar { display: none; } .category { padding: 8px 14px; margin-right: 10px; background-color: var(--white); border: 1px solid var(--border); border-radius: 30px; font-size: 13px; white-space: nowrap; cursor: pointer; transition: var(--transition); } .category:hover { border-color: var(--primary); color: var(--primary); } .category.active { background-color: var(--primary); color: var(--white); border-color: var(--primary); } .search-bar { display: flex; margin-bottom: 24px; } .search-input { flex: 1; padding: 12px 16px; border: 1px solid var(--border); border-radius: 8px; font-size: 14px; transition: var(--transition); } .search-input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-light); } .product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 20px; margin-bottom: 40px; } .product-card { background-color: var(--white); border-radius: 12px; overflow: hidden; box-shadow: var(--shadow); transition: var(--transition); position: relative; z-index: 1; } .product-card:hover { transform: translateY(-5px); box-shadow: var(--hover-shadow); } .product-image { position: relative; height: 150px; overflow: hidden; background-color: var(--primary-light); } .product-image img { width: 100%; height: 100%; object-fit: cover; transition: var(--transition); } .product-card:hover .product-image img { transform: scale(1.1); } .discount-badge { position: absolute; top: 10px; right: 10px; background-color: var(--accent); color: white; font-size: 12px; font-weight: 600; padding: 4px 8px; border-radius: 4px; opacity: 0; transform: translateX(10px); transition: var(--transition); } .product-card:hover .discount-badge { opacity: 1; transform: translateX(0); } .product-info { padding: 14px; } .product-title { font-size: 14px; font-weight: 600; margin-bottom: 6px; color: var(--text); line-height: 1.3; } .product-meta { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .product-price { font-size: 16px; font-weight: 700; color: var(--primary); } .product-rating { display: flex; align-items: center; font-size: 12px; color: var(--text-light); } .star { color: #ffbf00; margin-right: 2px; } .product-category { font-size: 11px; color: var(--text-light); text-transform: uppercase; letter-spacing: 0.5px; } .add-to-cart { margin-top: 12px; background-color: var(--primary-light); color: var(--primary); border: none; width: 100%; padding: 8px 0; font-size: 13px; font-weight: 600; border-radius: 6px; cursor: pointer; transition: var(--transition); opacity: 0; transform: translateY(5px); } .product-card:hover .add-to-cart { opacity: 1; transform: translateY(0); } .add-to-cart:hover { background-color: var(--primary); color: var(--white); } .quick-cart { position: fixed; bottom: 20px; right: 20px; background-color: var(--primary); color: white; border-radius: 50%; width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow); cursor: pointer; transition: var(--transition); z-index: 100; } .quick-cart:hover { transform: scale(1.1); } .cart-count { position: absolute; top: -5px; right: -5px; background-color: var(--accent); color: white; font-size: 12px; font-weight: bold; width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; } .cart-notification { position: fixed; top: 20px; right: 20px; background-color: var(--white); box-shadow: var(--shadow); border-left: 4px solid var(--primary); padding: 16px; border-radius: 8px; z-index: 1000; opacity: 0; transform: translateX(30px); transition: var(--transition); display: flex; align-items: center; } .cart-notification.active { opacity: 1; transform: translateX(0); } .notification-message { margin-left: 12px; } .notification-title { font-weight: 600; font-size: 14px; margin-bottom: 4px; } .notification-subtitle { font-size: 12px; color: var(--text-light); } .notification-icon { background-color: var(--primary-light); width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; } .notification-icon svg { color: var(--primary); } /* Filter bar */ .filter-bar { display: flex; align-items: center; margin-bottom: 24px; justify-content: space-between; } .filter-label { font-size: 13px; color: var(--text-light); } .view-options { display: flex; align-items: center; } .grid-view, .list-view { background: none; border: 1px solid var(--border); width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: var(--transition); } .grid-view { border-radius: 6px 0 0 6px; } .list-view { border-radius: 0 6px 6px 0; } .active-view { background-color: var(--primary); color: white; border-color: var(--primary); } .sort-select { padding: 8px 12px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px; margin-left: 10px; } /* List view styles */ .list-layout .product-grid { grid-template-columns: 1fr; } .list-layout .product-card { display: grid; grid-template-columns: 100px 1fr; height: auto; } .list-layout .product-image { height: 100%; } .list-layout .product-info { display: flex; flex-direction: column; justify-content: space-between; } .list-layout .add-to-cart { opacity: 1; transform: none; width: auto; align-self: flex-end; padding: 8px 16px; } @media (max-width: 480px) { .product-grid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 15px; } .list-layout .product-card { grid-template-columns: 80px 1fr; } .product-title { font-size: 13px; } .store-name { font-size: 24px; } } /* Animations */ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .product-card { animation: fadeIn 0.5s ease-out forwards; } .product-card:nth-child(2) { animation-delay: 0.1s; } .product-card:nth-child(3) { animation-delay: 0.2s; } .product-card:nth-child(4) { animation-delay: 0.3s; } .product-card:nth-child(5) { animation-delay: 0.4s; } .product-card:nth-child(6) { animation-delay: 0.5s; } /* Added pattern */ .pattern { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-image: radial-gradient(var(--primary-light) 2px, transparent 2px); background-size: 30px 30px; opacity: 0.4; z-index: -1; pointer-events: none; } </style> </head> <body> <div class="pattern"></div> <div class="container"> <header> <div class="store-name"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 6.5C10.2 6.5 8.5 6.9 7 7.5C5.5 8.1 4.5 9 4.5 10C4.5 11 5.5 11.9 7 12.5C8.5 13.1 10.2 13.5 12 13.5C13.8 13.5 15.5 13.1 17 12.5C18.5 11.9 19.5 11 19.5 10C19.5 9 18.5 8.1 17 7.5C15.5 6.9 13.8 6.5 12 6.5Z" stroke="#13654a" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M4.5 10V14C4.5 15 5.5 15.9 7 16.5C8.5 17.1 10.2 17.5 12 17.5C13.8 17.5 15.5 17.1 17 16.5C18.5 15.9 19.5 15 19.5 14V10" stroke="#13654a" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M4.5 14V18C4.5 19 5.5 19.9 7 20.5C8.5 21.1 10.2 21.5 12 21.5C13.8 21.5 15.5 21.1 17 20.5C18.5 19.9 19.5 19 19.5 18V14" stroke="#13654a" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 2.5V6.5" stroke="#13654a" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M15 4.5L12 2.5L9 4.5" stroke="#13654a" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> Lush Botanicals </div> <div class="store-tagline">Sustainable skincare products sourced from nature</div> <div class="categories"> <div class="category active">All Products</div> <div class="category">Cleansers</div> <div class="category">Serums</div> <div class="category">Moisturizers</div> <div class="category">Masks</div> <div class="category">Body Care</div> <div class="category">Gift Sets</div> </div> </header> <div class="search-bar"> <input type="text" placeholder="Search products..." class="search-input"> </div> <div class="filter-bar"> <div class="view-options"> <button class="grid-view active-view"> <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> <path d="M3 3h7v7H3V3zm11 0h7v7h-7V3zm0 11h7v7h-7v-7zm-11 0h7v7H3v-7z"></path> </svg> </button> <button class="list-view"> <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> <path d="M3 13h18v-2H3v2zm0-7h18V4H3v2zm0 12h18v-2H3v2z"></path> </svg> </button> </div> <div> <span class="filter-label">Sort by:</span> <select class="sort-select"> <option>Best Selling</option> <option>Price: Low to High</option> <option>Price: High to Low</option> <option>Newest</option> </select> </div> </div> <div class="product-grid"> <div class="product-card"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1556228578-0d85b1a4d571?w=300&auto=format&fit=crop&q=80" alt="Hydra Boost Facial Serum"> <div class="discount-badge">15% OFF</div> </div> <div class="product-info"> <div class="product-category">Serums</div> <div class="product-title">Hydra Boost Facial Serum</div> <div class="product-meta"> <div class="product-price">$42.99</div> <div class="product-rating"> <div class="star">★</div> 4.7 </div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1608248597279-f99d160bfcbc?w=300&auto=format&fit=crop&q=80" alt="Rose Cleansing Balm"> <div class="discount-badge">20% OFF</div> </div> <div class="product-info"> <div class="product-category">Cleansers</div> <div class="product-title">Rose Cleansing Balm</div> <div class="product-meta"> <div class="product-price">$38.50</div> <div class="product-rating"> <div class="star">★</div> 4.9 </div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1612817288484-6f916006741a?w=300&auto=format&fit=crop&q=80" alt="Avocado Night Cream"> </div> <div class="product-info"> <div class="product-category">Moisturizers</div> <div class="product-title">Avocado Night Cream</div> <div class="product-meta"> <div class="product-price">$45.00</div> <div class="product-rating"> <div class="star">★</div> 4.6 </div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1570194065650-d99fb4a8e0ef?w=300&auto=format&fit=crop&q=80" alt="Vitamin C Clay Mask"> <div class="discount-badge">10% OFF</div> </div> <div class="product-info"> <div class="product-category">Masks</div> <div class="product-title">Vitamin C Clay Mask</div> <div class="product-meta"> <div class="product-price">$29.99</div> <div class="product-rating"> <div class="star">★</div> 4.8 </div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1608248543803-ba4f8c70ae0b?w=300&auto=format&fit=crop&q=80" alt="Lavender Body Oil"> </div> <div class="product-info"> <div class="product-category">Body Care</div> <div class="product-title">Lavender Body Oil</div> <div class="product-meta"> <div class="product-price">$32.00</div> <div class="product-rating"> <div class="star">★</div> 4.5 </div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1617897903246-719242758050?w=300&auto=format&fit=crop&q=80" alt="Botanical Gift Set"> <div class="discount-badge">25% OFF</div> </div> <div class="product-info"> <div class="product-category">Gift Sets</div> <div class="product-title">Botanical Gift Set</div> <div class="product-meta"> <div class="product-price">$89.99</div> <div class="product-rating"> <div class="star">★</div> 4.9 </div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1611930022073-84f7bb5b9733?w=300&auto=format&fit=crop&q=80" alt="Aloe Vera Gel"> </div> <div class="product-info"> <div class="product-category">Body Care</div> <div class="product-title">Aloe Vera Gel</div> <div class="product-meta"> <div class="product-price">$18.50</div> <div class="product-rating"> <div class="star">★</div> 4.7 </div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> <div class="product-card"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1608248543803-ba4f8c70ae0b?w=300&auto=format&fit=crop&q=80" alt="Tea Tree Cleanser"> </div> <div class="product-info"> <div class="product-category">Cleansers</div> <div class="product-title">Tea Tree Cleanser</div> <div class="product-meta"> <div class="product-price">$26.99</div> <div class="product-rating"> <div class="star">★</div> 4.6 </div> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> </div> </div> <div class="quick-cart"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="9" cy="21" r="1"></circle> <circle cx="20" cy="21" r="1"></circle> <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path> </svg> <div class="cart-count">0</div> </div> <div class="cart-notification"> <div class="notification-icon"> <svg width="20" height="20" 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> <div class="notification-message"> <div class="notification-title">Item added to cart</div> <div class="notification-subtitle">Check your cart for details</div> </div> </div> <script> // Get elements const addToCartButtons = document.querySelectorAll('.add-to-cart'); const cartCount = document.querySelector('.cart-count'); const cartNotification = document.querySelector('.cart-notification'); const gridViewBtn = document.querySelector('.grid-view'); const listViewBtn = document.querySelector('.list-view'); const productGrid = document.querySelector('.product-grid'); const categories = document.querySelectorAll('.category'); const searchInput = document.querySelector('.search-input'); // Initialize cart count let count = 0; // Add to cart functionality addToCartButtons.forEach(button => { button.addEventListener('click', () => { // Increment cart count count++; cartCount.textContent = count; // Show notification cartNotification.classList.add('active'); // Get product title for notification const productTitle = button.closest('.product-info').querySelector('.product-title').textContent; cartNotification.querySelector('.notification-title').textContent = `${productTitle} added to cart`; // Hide notification after 3 seconds setTimeout(() => { cartNotification.classList.remove('active'); }, 3000); // Add ripple effect const ripple = document.createElement('span'); ripple.classList.add('ripple'); button.appendChild(ripple); setTimeout(() => { ripple.remove(); }, 600); }); }); // View switching functionality gridViewBtn.addEventListener('click', () => { productGrid.classList.remove('list-layout'); gridViewBtn.classList.add('active-view'); listViewBtn.classList.remove('active-view'); }); listViewBtn.addEventListener('click', () => { productGrid.classList.add('list-layout'); listViewBtn.classList.add('active-view'); gridViewBtn.classList.remove('active-view'); }); // Category selection categories.forEach(category => { category.addEventListener('click', () => { // Remove active class from all categories categories.forEach(c => c.classList.remove('active')); // Add active class to clicked category category.classList.add('active'); }); }); // Search functionality searchInput.addEventListener('keyup', (e) => { const searchTerm = e.target.value.toLowerCase(); const products = document.querySelectorAll('.product-card'); products.forEach(product => { const title = product.querySelector('.product-title').textContent.toLowerCase(); const category = product.querySelector('.product-category').textContent.toLowerCase(); if (title.includes(searchTerm) || category.includes(searchTerm)) { product.style.display = 'block'; } else { product.style.display = 'none'; } }); }); // Quick cart animation const quickCart = document.querySelector('.quick-cart'); quickCart.addEventListener('click', () => { quickCart.style.transform = 'scale(1.2)'; setTimeout(() => { quickCart.style.transform = 'scale(1)'; }, 200); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Social Media Notification List</title> <style> :root { --primary: #5b21e3; --secondary: #8e44ff; --accent: #ff3a7c; --background: #f8f9fc; --card: #ffffff; --text-primary: #333344; --text-secondary: #666677; --text-tertiary: #999aab; --success: #00d888; --error: #ff4757; --warning: #ffab2e; --info: #00c3ff; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } body { background: var(--background); color: var(--text-primary); display: flex; justify-content: center; align-items: center; min-height: 700px; padding: 16px; overflow-x: hidden; } .container { width: 100%; max-width: 700px; background: var(--card); border-radius: 16px; box-shadow: 0 8px 40px rgba(0, 0, 0, 0.06); overflow: hidden; position: relative; height: 680px; display: flex; flex-direction: column; } .header { padding: 24px; background: linear-gradient(135deg, var(--primary), var(--secondary)); color: white; position: relative; z-index: 2; } .header h1 { font-size: 24px; font-weight: 700; margin-bottom: 8px; display: flex; align-items: center; } .header h1 svg { margin-right: 12px; } .header p { font-size: 14px; opacity: 0.8; } .filters { display: flex; gap: 8px; padding: 8px 24px; overflow-x: auto; background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); scrollbar-width: none; } .filters::-webkit-scrollbar { display: none; } .filter-btn { background: rgba(255, 255, 255, 0.15); border: none; color: white; padding: 6px 16px; border-radius: 20px; font-size: 12px; font-weight: 500; cursor: pointer; white-space: nowrap; transition: all 0.2s ease; } .filter-btn.active { background: white; color: var(--primary); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); } .filter-btn:hover:not(.active) { background: rgba(255, 255, 255, 0.25); } .content { flex: 1; overflow-y: auto; padding: 8px 0; scrollbar-width: thin; scrollbar-color: var(--text-tertiary) transparent; } .content::-webkit-scrollbar { width: 6px; } .content::-webkit-scrollbar-track { background: transparent; } .content::-webkit-scrollbar-thumb { background-color: var(--text-tertiary); border-radius: 6px; } .notification-list { list-style: none; } .notification { padding: 16px 24px; border-bottom: 1px solid rgba(0, 0, 0, 0.05); position: relative; transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1); cursor: pointer; overflow: hidden; } .notification:hover { background-color: rgba(91, 33, 227, 0.03); } .notification.unread::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 4px; height: 60%; background: var(--primary); border-radius: 0 4px 4px 0; } .notification.expanded { background-color: rgba(91, 33, 227, 0.05); padding-bottom: 24px; } .notification-header { display: flex; align-items: flex-start; margin-bottom: 8px; } .avatar { width: 42px; height: 42px; border-radius: 50%; margin-right: 12px; position: relative; flex-shrink: 0; background-size: cover; background-position: center; } .avatar-status { position: absolute; bottom: 0; right: 0; width: 12px; height: 12px; border-radius: 50%; border: 2px solid white; } .avatar-status.online { background-color: var(--success); } .notification-icon { position: absolute; right: -2px; bottom: -2px; width: 18px; height: 18px; border-radius: 50%; background: var(--card); display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); font-size: 10px; } .notification-info { flex: 1; } .notification-meta { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; } .notification-name { font-weight: 600; font-size: 15px; color: var(--text-primary); } .notification-time { font-size: 12px; color: var(--text-tertiary); white-space: nowrap; } .notification-content { font-size: 14px; color: var(--text-secondary); line-height: 1.4; } .notification-preview { margin-top: 12px; border-radius: 8px; overflow: hidden; opacity: 0; max-height: 0; transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1); } .notification.expanded .notification-preview { opacity: 1; max-height: 300px; } .media-preview { border-radius: 12px; overflow: hidden; position: relative; } .media-preview img { width: 100%; height: auto; display: block; } .notification-actions { display: flex; gap: 8px; margin-top: 16px; opacity: 0; transform: translateY(10px); transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1); } .notification.expanded .notification-actions { opacity: 1; transform: translateY(0); } .action-btn { background: none; border: 1px solid rgba(0, 0, 0, 0.1); padding: 8px 12px; border-radius: 8px; font-size: 13px; font-weight: 500; cursor: pointer; display: flex; align-items: center; gap: 6px; transition: all 0.2s ease; } .action-btn:hover { background: rgba(0, 0, 0, 0.03); } .action-btn.primary { background: var(--primary); color: white; border: none; } .action-btn.primary:hover { background: var(--secondary); } .mention { color: var(--primary); font-weight: 500; } .tag { display: inline-block; padding: 2px 8px; background: rgba(91, 33, 227, 0.1); color: var(--primary); border-radius: 4px; font-size: 12px; font-weight: 500; margin-right: 4px; } .badge { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; background: var(--accent); color: white; font-size: 10px; font-weight: 600; margin-left: 8px; } .badge.comment { background: var(--info); } .badge.like { background: var(--accent); } .badge.share { background: var(--success); } .badge.mention { background: var(--warning); } .read-more { color: var(--primary); font-weight: 500; cursor: pointer; } .reaction-bar { display: flex; gap: 8px; margin-top: 12px; } .reaction { display: flex; align-items: center; padding: 4px 8px; background: rgba(0, 0, 0, 0.04); border-radius: 16px; font-size: 12px; gap: 4px; } .empty-state { display: none; flex-direction: column; align-items: center; justify-content: center; height: 100%; padding: 24px; text-align: center; } .empty-state svg { width: 100px; height: 100px; margin-bottom: 24px; color: var(--text-tertiary); } .empty-state h3 { font-size: 18px; margin-bottom: 8px; color: var(--text-primary); } .empty-state p { font-size: 14px; color: var(--text-secondary); max-width: 300px; margin: 0 auto 24px; } .empty-state button { background: var(--primary); color: white; border: none; padding: 10px 16px; border-radius: 8px; font-weight: 500; cursor: pointer; transition: background 0.2s; } .empty-state button:hover { background: var(--secondary); } .controls { display: flex; justify-content: space-between; align-items: center; padding: 16px 24px; border-top: 1px solid rgba(0, 0, 0, 0.05); background: var(--card); } .mark-all-read { background: none; border: none; color: var(--primary); font-size: 14px; font-weight: 500; cursor: pointer; display: flex; align-items: center; gap: 6px; } .mark-all-read:hover { color: var(--secondary); } .settings-btn { background: none; border: none; width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--text-secondary); transition: all 0.2s; } .settings-btn:hover { background: rgba(0, 0, 0, 0.05); color: var(--text-primary); } .notification-dot { position: absolute; top: 12px; right: 12px; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); } .time-divider { padding: 12px 24px 8px; font-size: 12px; font-weight: 600; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.05em; } /* Animation keyframes */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @keyframes slideIn { from { transform: translateX(30px); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .pulse-animation { animation: pulse 0.5s; } .notification { animation: slideIn 0.3s forwards; animation-delay: calc(var(--index) * 0.05s); opacity: 0; } /* Dark mode support */ @media (prefers-color-scheme: dark) { :root { --background: #121318; --card: #1e1f26; --text-primary: #e2e4f0; --text-secondary: #a0a3b8; --text-tertiary: #666980; } } /* Responsive adjustments */ @media (max-width: 500px) { .header { padding: 20px; } .notification { padding: 14px 20px; } .avatar { width: 38px; height: 38px; } .notification-name { font-size: 14px; } .notification-content { font-size: 13px; } } </style> </head> <body> <div class="container"> <div class="header"> <h1> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12.0001 2.83398C9.30328 2.83398 7.11644 5.02082 7.11644 7.71768V10.9631C7.11644 11.3335 6.94235 11.8577 6.76827 12.1694L5.91919 13.6253C5.49643 14.386 5.77435 15.2351 6.61494 15.5883C10.0148 16.9856 13.9855 16.9856 17.3854 15.5883C18.1674 15.2767 18.472 14.3318 18.0811 13.6253L17.232 12.1694C17.0579 11.8577 16.8839 11.3335 16.8839 10.9631V7.71768C16.8839 5.04932 14.6804 2.83398 12.0001 2.83398Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round"/> <path d="M13.5762 3.1001C13.3109 3.0391 13.0342 2.99243 12.7576 2.97827C11.8971 2.92743 11.0652 3.04326 10.2946 3.3001C10.5256 2.6051 11.1965 2.1001 12.0001 2.1001C12.8037 2.1001 13.4632 2.5901 13.5762 3.1001Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M15 16.5C15 18.157 13.657 19.5 12 19.5C11.1716 19.5 10.4216 19.157 9.90033 18.5861C9.379 18.0151 9.036 17.265 9 16.5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10"/> </svg> Notifications </h1> <p>Stay updated with your social connections</p> <div class="filters"> <button class="filter-btn active">All</button> <button class="filter-btn">Mentions</button> <button class="filter-btn">Comments</button> <button class="filter-btn">Likes</button> <button class="filter-btn">Shares</button> <button class="filter-btn">Friend Requests</button> </div> </div> <div class="content"> <div class="time-divider">Today</div> <ul class="notification-list"> <li class="notification unread" style="--index: 0;"> <div class="notification-dot"></div> <div class="notification-header"> <div class="avatar" style="background-image: url('https://images.unsplash.com/photo-1580489944761-15a19d654956?ixlib=rb-1.2.1&auto=format&fit=crop&w=100&q=80')"> <div class="avatar-status online"></div> <div class="notification-icon"> <svg width="10" height="10" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8.5 12.5H15.5" stroke="#5b21e3" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 9V16" stroke="#5b21e3" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M9 22H15C20 22 22 20 22 15V9C22 4 20 2 15 2H9C4 2 2 4 2 9V15C2 20 4 22 9 22Z" stroke="#5b21e3" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> </div> <div class="notification-info"> <div class="notification-meta"> <span class="notification-name">Sophia Chen</span> <span class="notification-time">2m ago</span> </div> <div class="notification-content"> <span class="mention">@you</span> I'm loving your latest photo from Tokyo! The composition with the Shibuya crossing in the background is just perfect. </div> <div class="notification-preview"> <div class="media-preview"> <img src="https://images.unsplash.com/photo-1542051841857-5f90071e7989?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80" alt="Tokyo Shibuya crossing"> </div> <div class="notification-actions"> <button class="action-btn"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7 7H15C17 7 18 8 18 10V17C18 19 17 20 15 20H7C5 20 4 19 4 17V10C4 8 5 7 7 7Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M19 7L13 11" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8 7V4" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M14 7V4" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> </svg> Reply </button> <button class="action-btn primary"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2C6.49 2 2 6.49 2 12C2 17.51 6.49 22 12 22C17.51 22 22 17.51 22 12C22 6.49 17.51 2 12 2ZM16 12.75H12.75V16C12.75 16.41 12.41 16.75 12 16.75C11.59 16.75 11.25 16.41 11.25 16V12.75H8C7.59 12.75 7.25 12.41 7.25 12C7.25 11.59 7.59 11.25 8 11.25H11.25V8C11.25 7.59 11.59 7.25 12 7.25C12.41 7.25 12.75 7.59 12.75 8V11.25H16C16.41 11.25 16.75 11.59 16.75 12C16.75 12.41 16.41 12.75 16 12.75Z" fill="currentColor"/> </svg> Follow Back </button> </div> </div> </div> </div> </li> <li class="notification unread" style="--index: 1;"> <div class="notification-dot"></div> <div class="notification-header"> <div class="avatar" style="background-image: url('https://images.unsplash.com/photo-1567515004624-219c11d31f2e?ixlib=rb-1.2.1&auto=format&fit=crop&w=100&q=80')"> <div class="notification-icon badge comment"> <svg width="10" height="10" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8.5 19H8C4 19 2 18 2 13V8C2 4 4 2 8 2H16C20 2 22 4 22 8V13C22 17 20 19 16 19H15.5C15.19 19 14.89 19.15 14.7 19.4L13.2 21.4C12.54 22.28 11.46 22.28 10.8 21.4L9.3 19.4C9.14 19.18 8.77 19 8.5 19Z" stroke="white" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M15.9965 11H16.0054" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M11.9955 11H12.0045" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M7.99451 11H8.00349" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> </div> <div class="notification-info"> <div class="notification-meta"> <span class="notification-name">James Wilson</span> <span class="notification-time">15m ago</span> </div> <div class="notification-content"> Commented on your post about <span class="tag">#AIPoweredDesign</span>: "Great insights on how AI is transforming the UX landscape. I'd love to hear more about practical applications." </div> <div class="notification-preview"> <div class="reaction-bar"> <div class="reaction"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12.62 20.81C12.28 20.93 11.72 20.93 11.38 20.81C8.48 19.82 2 15.69 2 8.69C2 5.6 4.49 3.1 7.56 3.1C9.38 3.1 10.99 3.98 12 5.34C13.01 3.98 14.63 3.1 16.44 3.1C19.51 3.1 22 5.6 22 8.69C22 15.69 15.52 19.82 12.62 20.81Z" fill="#ff3a7c"/> </svg> 4 </div> <div class="reaction"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8.5 19H8C4 19 2 18 2 13V8C2 4 4 2 8 2H16C20 2 22 4 22 8V13C22 17 20 19 16 19H15.5C15.19 19 14.89 19.15 14.7 19.4L13.2 21.4C12.54 22.28 11.46 22.28 10.8 21.4L9.3 19.4C9.14 19.18 8.77 19 8.5 19Z" stroke="#5b21e3" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> </svg> 2 </div> </div> <div class="notification-actions"> <button class="action-btn"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7 7H15C17 7 18 8 18 10V17C18 19 17 20 15 20H7C5 20 4 19 4 17V10C4 8 5 7 7 7Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M19 7L13 11" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8 7V4" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M14 7V4" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> </svg> Reply </button> <button class="action-btn"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12.62 20.81C12.28 20.93 11.72 20.93 11.38 20.81C8.48 19.82 2 15.69 2 8.69C2 5.6 4.49 3.1 7.56 3.1C9.38 3.1 10.99 3.98 12 5.34C13.01 3.98 14.63 3.1 16.44 3.1C19.51 3.1 22 5.6 22 8.69C22 15.69 15.52 19.82 12.62 20.81Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> Like </button> </div> </div> </div> </div> </li> <li class="notification" style="--index: 2;"> <div class="notification-header"> <div class="avatar" style="background-image: url('https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?ixlib=rb-1.2.1&auto=format&fit=crop&w=100&q=80')"> <div class="notification-icon badge like"> <svg width="10" height="10" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12.62 20.81C12.28 20.93 11.72 20.93 11.38 20.81C8.48 19.82 2 15.69 2 8.69C2 5.6 4.49 3.1 7.56 3.1C9.38 3.1 10.99 3.98 12 5.34C13.01 3.98 14.63 3.1 16.44 3.1C19.51 3.1 22 5.6 22 8.69C22 15.69 15.52 19.82 12.62 20.81Z" fill="white"/> </svg> </div> </div> <div class="notification-info"> <div class="notification-meta"> <span class="notification-name">Alex Rodriguez</span> <span class="notification-time">45m ago</span> </div> <div class="notification-content"> Liked your interactive prototype for the health tracking app. That animation for the heart rate monitor is smooth! </div> <div class="notification-preview"> <div class="notification-actions"> <button class="action-btn"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7.39999 6.32003L15.89 3.49003C19.7 2.22003 21.77 4.30003 20.51 8.11003L17.68 16.6C15.78 22.31 12.66 22.31 10.76 16.6L9.91999 14.08L7.39999 13.24C1.68999 11.34 1.68999 8.23003 7.39999 6.32003Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M10.11 13.6501L13.69 10.0601" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> Message </button> <button class="action-btn"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M17.5 12C17.5 15.04 15.04 17.5 12 17.5C8.96 17.5 6.5 15.04 6.5 12C6.5 8.96 8.96 6.5 12 6.5C15.04 6.5 17.5 8.96 17.5 12Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M20 12H17.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M6.5 12H4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 6.5V4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 20V17.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> View Project </button> </div> </div> </div> </div> </li> <li class="notification unread" style="--index: 3;"> <div class="notification-dot"></div> <div class="notification-header"> <div class="avatar" style="background-image: url('https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&auto=format&fit=crop&w=100&q=80')"> <div class="notification-icon badge share"> <svg width="10" height="10" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M16.44 8.9C20.04 9.21 21.51 11.06 21.51 15.11V15.24C21.51 19.71 19.72 21.5 15.25 21.5H8.73998C4.26998 21.5 2.47998 19.71 2.47998 15.24V15.11C2.47998 11.09 3.92998 9.24 7.46998 8.91" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 15V3.62" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M15.35 5.85L12 2.5L8.65002 5.85" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> </div> <div class="notification-info"> <div class="notification-meta"> <span class="notification-name">Sam Taylor</span> <span class="notification-time">1h ago</span> </div> <div class="notification-content"> Shared your article <span class="read-more">"Improving Mobile Form UX: 5 Essential Practices"</span> with their network. It's already gained 56 new views. </div> <div class="notification-preview"> <div class="reaction-bar"> <div class="reaction"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8.5 19H8C4 19 2 18 2 13V8C2 4 4 2 8 2H16C20 2 22 4 22 8V13C22 17 20 19 16 19H15.5C15.19 19 14.89 19.15 14.7 19.4L13.2 21.4
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Interactive Directory List</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; } :root { --primary: #4A6FFF; --primary-light: #EEF1FF; --text-primary: #1A2240; --text-secondary: #5B6987; --border-color: #E9ECEF; --background: #FFFFFF; --hover-bg: #F8F9FD; --card-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } body { background-color: var(--background); color: var(--text-primary); height: 700px; width: 700px; overflow: hidden; position: relative; } .container { display: grid; grid-template-columns: 1fr; height: 100%; width: 100%; position: relative; overflow: hidden; transition: var(--transition); } .directory-container { display: flex; flex-direction: column; height: 100%; width: 100%; background: var(--background); transition: var(--transition); position: relative; z-index: 1; } .header { padding: 24px 24px 12px; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: center; } .header h1 { font-size: 24px; font-weight: 700; color: var(--text-primary); margin-bottom: 4px; } .header p { font-size: 14px; color: var(--text-secondary); } .search-container { display: flex; padding: 12px 24px; position: relative; } .search-input { width: 100%; padding: 12px 16px 12px 40px; border: 1px solid var(--border-color); border-radius: 8px; font-size: 14px; transition: var(--transition); outline: none; } .search-input:focus { border-color: var(--primary); box-shadow: 0 0 0 2px rgba(74, 111, 255, 0.2); } .search-icon { position: absolute; left: 36px; top: 50%; transform: translateY(-50%); color: var(--text-secondary); } .directory-list { flex-grow: 1; overflow-y: auto; padding: 0 12px; scrollbar-width: thin; } .directory-list::-webkit-scrollbar { width: 5px; } .directory-list::-webkit-scrollbar-track { background: transparent; } .directory-list::-webkit-scrollbar-thumb { background-color: #D1D5DB; border-radius: 20px; } .directory-item { display: flex; align-items: center; padding: 16px 12px; border-bottom: 1px solid var(--border-color); cursor: pointer; transition: var(--transition); border-radius: 8px; position: relative; overflow: hidden; margin-bottom: 4px; } .directory-item:hover { background-color: var(--hover-bg); } .directory-item::before { content: ''; position: absolute; left: 0; top: 0; height: 100%; width: 4px; background-color: transparent; transition: var(--transition); } .directory-item.active { background-color: var(--primary-light); } .directory-item.active::before { background-color: var(--primary); } .avatar { width: 48px; height: 48px; border-radius: 50%; background-color: var(--primary-light); display: flex; align-items: center; justify-content: center; margin-right: 16px; font-weight: 600; color: var(--primary); flex-shrink: 0; position: relative; overflow: hidden; } .avatar img { width: 100%; height: 100%; object-fit: cover; } .avatar-online::after { content: ''; position: absolute; width: 12px; height: 12px; background-color: #10B981; border-radius: 50%; border: 2px solid white; bottom: 0; right: 0; } .item-details { flex-grow: 1; } .item-name { font-weight: 600; font-size: 16px; margin-bottom: 4px; color: var(--text-primary); } .item-position { font-size: 14px; color: var(--text-secondary); } .item-meta { display: flex; flex-direction: column; align-items: flex-end; margin-left: 12px; } .item-department { font-size: 12px; color: var(--text-secondary); padding: 4px 8px; border-radius: 16px; background-color: #F3F4F6; margin-bottom: 4px; } .item-department.engineering { background-color: #EEF1FF; color: var(--primary); } .item-department.design { background-color: #FCE7F3; color: #DB2777; } .item-department.marketing { background-color: #ECFDF5; color: #059669; } .item-department.product { background-color: #FEF3C7; color: #D97706; } .item-department.leadership { background-color: #EFF6FF; color: #2563EB; } .item-last-contact { font-size: 12px; color: var(--text-secondary); } .directory-filters { display: flex; padding: 12px 24px; overflow-x: auto; -ms-overflow-style: none; scrollbar-width: none; gap: 8px; } .directory-filters::-webkit-scrollbar { display: none; } .filter-pill { padding: 8px 16px; background-color: var(--hover-bg); border-radius: 20px; font-size: 14px; color: var(--text-secondary); cursor: pointer; white-space: nowrap; transition: var(--transition); border: 1px solid transparent; } .filter-pill:hover { background-color: var(--primary-light); color: var(--primary); } .filter-pill.active { background-color: var(--primary); color: white; } .detail-panel { position: absolute; top: 0; right: -100%; width: 100%; height: 100%; background-color: var(--background); box-shadow: var(--card-shadow); z-index: 2; transition: var(--transition); border-left: 1px solid var(--border-color); display: flex; flex-direction: column; } .detail-panel.active { right: 0; } .detail-header { display: flex; align-items: center; padding: 24px; border-bottom: 1px solid var(--border-color); } .back-btn { background: none; border: none; cursor: pointer; color: var(--text-secondary); padding: 8px; border-radius: 8px; margin-right: 12px; transition: var(--transition); } .back-btn:hover { background-color: var(--hover-bg); color: var(--text-primary); } .detail-title { font-size: 18px; font-weight: 600; } .detail-content { padding: 24px; overflow-y: auto; flex-grow: 1; } .detail-profile { display: flex; flex-direction: column; align-items: center; margin-bottom: 24px; } .detail-avatar { width: 100px; height: 100px; border-radius: 50%; margin-bottom: 16px; background-color: var(--primary-light); display: flex; align-items: center; justify-content: center; font-size: 32px; font-weight: 600; color: var(--primary); position: relative; overflow: hidden; } .detail-avatar img { width: 100%; height: 100%; object-fit: cover; } .detail-name { font-size: 24px; font-weight: 600; margin-bottom: 4px; text-align: center; } .detail-position { font-size: 16px; color: var(--text-secondary); margin-bottom: 12px; text-align: center; } .detail-badge { display: inline-block; padding: 4px 12px; border-radius: 16px; font-size: 14px; font-weight: 500; margin-bottom: 24px; } .section-title { font-size: 16px; font-weight: 600; margin-bottom: 16px; display: flex; align-items: center; gap: 8px; } .section-title svg { color: var(--primary); } .contact-info { margin-bottom: 32px; } .contact-item { display: flex; margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid var(--border-color); } .contact-item:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; } .contact-icon { width: 40px; height: 40px; border-radius: 8px; background-color: var(--primary-light); display: flex; align-items: center; justify-content: center; margin-right: 16px; color: var(--primary); flex-shrink: 0; } .contact-label { font-size: 14px; color: var(--text-secondary); margin-bottom: 4px; } .contact-value { font-size: 16px; font-weight: 500; } .contact-value a { color: var(--primary); text-decoration: none; transition: var(--transition); } .contact-value a:hover { text-decoration: underline; } .team-members { margin-bottom: 32px; } .team-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; } .team-item { display: flex; flex-direction: column; align-items: center; padding: 16px 8px; border-radius: 8px; transition: var(--transition); cursor: pointer; } .team-item:hover { background-color: var(--hover-bg); } .team-avatar { width: 48px; height: 48px; border-radius: 50%; margin-bottom: 8px; background-color: var(--primary-light); display: flex; align-items: center; justify-content: center; font-weight: 600; color: var(--primary); position: relative; overflow: hidden; } .team-avatar img { width: 100%; height: 100%; object-fit: cover; } .team-name { font-size: 14px; font-weight: 500; text-align: center; margin-bottom: 2px; } .team-position { font-size: 12px; color: var(--text-secondary); text-align: center; } .availability { margin-bottom: 32px; } .availability-chart { height: 80px; display: flex; gap: 4px; margin-bottom: 12px; } .day { flex: 1; height: 100%; display: flex; flex-direction: column; gap: 4px; } .hour { flex: 1; border-radius: 4px; background-color: var(--hover-bg); transition: var(--transition); } .hour.available { background-color: #D1FAE5; } .hour.busy { background-color: #FEE2E2; } .day-labels { display: flex; justify-content: space-between; margin-top: 8px; } .day-label { font-size: 12px; color: var(--text-secondary); flex: 1; text-align: center; } .legend { display: flex; gap: 16px; margin-top: 8px; } .legend-item { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-secondary); } .legend-color { width: 16px; height: 16px; border-radius: 4px; } .legend-color.available { background-color: #D1FAE5; } .legend-color.busy { background-color: #FEE2E2; } .legend-color.unavailable { background-color: var(--hover-bg); } .recent-activity { margin-bottom: 32px; } .activity-list { display: flex; flex-direction: column; gap: 16px; } .activity-item { padding: 16px; border-radius: 8px; border: 1px solid var(--border-color); background-color: white; transition: var(--transition); } .activity-item:hover { box-shadow: var(--card-shadow); transform: translateY(-2px); } .activity-header { display: flex; justify-content: space-between; margin-bottom: 8px; } .activity-type { font-size: 14px; font-weight: 500; color: var(--primary); } .activity-date { font-size: 12px; color: var(--text-secondary); } .activity-content { font-size: 14px; margin-bottom: 12px; } .activity-meta { display: flex; align-items: center; font-size: 12px; color: var(--text-secondary); } .activity-meta span:not(:last-child)::after { content: '•'; margin: 0 8px; } .quick-actions { display: flex; gap: 12px; } .action-button { flex: 1; padding: 12px 16px; border-radius: 8px; border: none; display: flex; flex-direction: column; align-items: center; justify-content: center; font-weight: 500; cursor: pointer; transition: var(--transition); } .action-button.primary { background-color: var(--primary); color: white; } .action-button.primary:hover { background-color: #3A5FE0; } .action-button.secondary { background-color: var(--hover-bg); color: var(--text-primary); } .action-button.secondary:hover { background-color: #E9ECEF; } .action-button svg { margin-bottom: 8px; } .animate-in { animation: fadeInSlideUp 0.5s forwards; } @keyframes fadeInSlideUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .pulse { animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @media (min-width: 768px) { .container { grid-template-columns: 1fr 1fr; } .directory-container { width: 100%; } .detail-panel { position: relative; right: 0; width: 100%; height: 100%; transform: translateX(100%); } .detail-panel.active { transform: translateX(0); } .directory-container.panel-active { transform: translateX(-20%); opacity: 0.8; } } </style> </head> <body> <div class="container"> <div class="directory-container" id="directoryContainer"> <div class="header"> <div> <h1>Directory</h1> <p>46 contacts in Pixelflow Inc.</p> </div> <div style="display: flex; gap: 8px;"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 5V19M5 12H19" stroke="#4A6FFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> </div> <div class="search-container"> <input type="text" class="search-input" placeholder="Search for name, position, or department..." id="searchInput"> <svg class="search-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M21 21L15 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div class="directory-filters" id="directoryFilters"> <div class="filter-pill active">All</div> <div class="filter-pill">Engineering</div> <div class="filter-pill">Design</div> <div class="filter-pill">Marketing</div> <div class="filter-pill">Product</div> <div class="filter-pill">Leadership</div> <div class="filter-pill">Recent</div> <div class="filter-pill">Favorites</div> </div> <div class="directory-list" id="directoryList"> <!-- Directory items will be populated here --> </div> </div> <div class="detail-panel" id="detailPanel"> <div class="detail-header"> <button class="back-btn" id="backButton"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M19 12H5M5 12L12 19M5 12L12 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> <div class="detail-title">Contact Details</div> </div> <div class="detail-content" id="detailContent"> <!-- Contact details will be populated here --> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const directoryContainer = document.getElementById('directoryContainer'); const directoryList = document.getElementById('directoryList'); const detailPanel = document.getElementById('detailPanel'); const detailContent = document.getElementById('detailContent'); const backButton = document.getElementById('backButton'); const searchInput = document.getElementById('searchInput'); const filterPills = document.querySelectorAll('.filter-pill'); // Sample data const contacts = [ { id: 1, name: 'Sophia Chen', position: 'Lead Product Designer', department: 'design', email: '[email protected]', phone: '+1 (415) 555-1234', location: 'San Francisco, CA', lastContact: '2 hours ago', image: 'https://randomuser.me/api/portraits/women/44.jpg', online: true, bio: 'Sophia leads the product design team, focusing on creating intuitive and accessible user experiences for enterprise software.', projects: ['Workspace Redesign', 'Mobile App'], availability: [ [1, 1, 1, 0, 2], [1, 1, 2, 2, 2], [0, 0, 2, 2, 2], [0, 0, 0, 0, 0], [1, 1, 1, 1, 0] ], activities: [ { type: 'Project Update', date: 'Today at 10:23 AM', content: 'Completed the wireframes for the new analytics dashboard feature.', meta: ['Design Team', 'Workspace Project'] }, { type: 'Meeting', date: 'Yesterday at 2:00 PM', content: 'Conducted user testing session with the marketing team for the new onboarding flow.', meta: ['User Research', '45 minutes'] } ], team: [ { name: 'Alex Kim', position: 'UI Designer', image: 'https://randomuser.me/api/portraits/men/32.jpg' }, { name: 'Maya Patel', position: 'UX Researcher', image: 'https://randomuser.me/api/portraits/women/65.jpg' }, { name: 'David Wu', position: 'Motion Designer', image: 'https://randomuser.me/api/portraits/men/11.jpg' } ] }, { id: 2, name: 'Marcus Johnson', position: 'VP of Engineering', department: 'leadership', email: '[email protected]', phone: '+1 (415) 555-8976', location: 'Seattle, WA', lastContact: '1 day ago', online: false, bio: 'Marcus oversees all engineering teams, aligning technical strategy with company goals and managing cross-functional collaboration.', projects: ['Platform Architecture', 'Security Upgrade'], team: [ { name: 'Sarah Lee', position: 'Engineering Manager', image: 'https://randomuser.me/api/portraits/women/22.jpg' }, { name: 'Raj Patel', position: 'Engineering Manager', image: 'https://randomuser.me/api/portraits/men/45.jpg' }, { name: 'Emma Wilson', position: 'QA Director', image: 'https://randomuser.me/api/portraits/women/36.jpg' } ] }, { id: 3, name: 'Elena Rodriguez', position: 'Senior Frontend Developer', department: 'engineering', email: '[email protected]', phone: '+1 (415) 555-6432', location: 'Remote - Barcelona', lastContact: '3 days ago', online: true, bio: 'Frontend specialist with expertise in React, component libraries, and accessibility standards.', projects: ['Component System', 'Accessibility Initiative'] }, { id: 4, name: 'James Wilson', position: 'Growth Marketing Manager', department: 'marketing', email: '[email protected]', phone: '+1 (415) 555-7890', location: 'New York, NY', lastContact: '5 days ago', online: false, bio: 'Focuses on conversion optimization, user acquisition, and retention strategies for our SaaS products.' }, { id: 5, name: 'Aisha Hassan', position: 'Product Manager', department: 'product', email: '[email protected]', phone: '+1 (415) 555-2345', location: 'Chicago, IL', lastContact: '1 week ago', image: 'https://randomuser.me/api/portraits/women/28.jpg', online: true }, { id: 6, name: 'Takashi Nakamura', position: 'Backend Engineer', department: 'engineering', email: '[email protected]', phone: '+1 (415) 555-3698', location: 'Remote - Tokyo', lastContact: '3 hours ago', image: 'https://randomuser.me/api/portraits/men/23.jpg', online: false }, { id: 7, name: 'Olivia Martinez', position: 'Chief Marketing Officer', department: 'leadership', email: '[email protected]', phone: '+1 (415) 555-9087', location: 'Austin, TX', lastContact: '2 days ago', image: 'https://randomuser.me/api/portraits/women/12.jpg', online: true }, { id: 8, name: 'Daniel Park', position: 'UX Designer', department: 'design', email: '[email protected]', phone: '+1 (415) 555-5476', location: 'San Francisco, CA', lastContact: '4 days ago', online: false } ]; // Initialize directory function initializeDirectory() { populateDirectoryList(contacts); addEventListeners(); } // Populate directory list function populateDirectoryList(contacts) { directoryList.innerHTML = ''; contacts.forEach((contact, index) => { const departmentClassMap = { 'engineering': 'engineering', 'design': 'design', 'marketing': 'marketing', 'product': 'product', 'leadership': 'leadership' }; const departmentClass = departmentClassMap[contact.department] || ''; // Create initials for avatar if no image const initials = contact.name.split(' ').map(n => n[0]).join(''); const contactElement = document.createElement('div'); contactElement.classList.add('directory-item'); contactElement.classList.add('animate-in'); contactElement.style.animationDelay = `${index * 0.05}s`; contactElement.dataset.id = contact.id; contactElement.innerHTML = ` <div class="avatar ${contact.online ? 'avatar-online' : ''}"> ${contact.image ? `<img src="${contact.image}" alt="${contact.name}">` : initials} </div> <div class="item-details"> <div class="item-name">${contact.name}</div> <div class="item-position">${contact.position}</div> </div> <div class="item-meta"> <div class="item-department ${departmentClass}">${contact.department}</div> <div class="item-last-contact">${contact.lastContact}</div> </div> `; directoryList.appendChild(contactElement); }); } // Show contact details function showContactDetails(contactId) { const contact = contacts.find(c => c.id === parseInt(contactId)); if (contact) { // Show panel detailPanel.classList.add('active'); directoryContainer.classList.add('panel-active'); // Create initials for avatar if no image const initials = contact.name.split(' ').map(n => n[0]).join(''); // Populate details detailContent.innerHTML = ` <div class="detail-profile animate-in"> <div class="detail-avatar ${contact.online ? 'avatar-online' : ''}"> ${contact.image ? `<img src="${contact.image}" alt="${contact.name}">` : initials} </div> <div class="detail-name">${contact.name}</div> <div class="detail-position">${contact.position}</div> <div class="detail-badge" style="${getDepartmentStyle(contact.department)}">${capitalizeFirstLetter(contact.department)}</div> </div> <div class="contact-info animate-in" style="animation-delay: 0.1s"> <div class="section-title"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M3 8L10.8906 13.2604C11.5624 13.7083 12.4376 13.7083 13.1094 13.2604L21 8M5 19H19C20.1046 19 21 18.1046 21 17V7C21 5.89543 20.1046 5 19 5H5C3.89543 5 3 5.89543 3 7V17C3 18.1046 3.89543 19 5 19Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> Contact Information </div> <div class="contact-item"> <div class="contact-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M3 8L10.8906 13.2604C11.5624 13.7083 12.4376 13.7083 13.1094 13.2604L21 8M5 19H19C20.1046 19 21 18.1046 21 17V7C21 5.89543 20.1046 5 19 5H5C3.89543 5 3 5.89543 3 7V17C3 18.1046 3.89543 19 5 19Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div> <div class="contact-label">Email</div> <div class="contact-value"><a href="mailto:${contact.email}">${contact.email}</a></div> </div> </div> <div class="contact-item"> <div class="contact-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M3 5.5C3 14.0604 9.93959 21 18.5 21C18.8862 21 19.2691 20.9859 19.6483 20.9581C20.0834 20.9262 20.3009 20.9103 20.499 20.7963C20.663 20.7019 20.8185 20.5345 20.9007 20.364C21 20.1582 21 19.9181 21 19.438V16.6207C21 16.2169 21 16.015 20.9335 15.842C20.8749 15.6891 20.7795 15.553 20.6559 15.4456C20.516 15.324 20.3262 15.255 19.9468 15.117L16.74 13.9329C16.2985 13.7822 16.0777 13.7069 15.8683 13.7071C15.6836 13.7073 15.5059 13.7652 15.3647 13.8701C15.2032 13.9915 15.0941 14.197 14.8758 14.608L14.1758 15.8939C12.9935 15.2982 11.932 14.4467 11.0814 13.4222C10.0569 12.5716 9.20543 11.5101 8.60971 10.3278L9.89563 9.62781C10.3066 9.40953 10.5121 9.30039 10.6335 9.13891C10.7384 8.99768 10.7963 8.81997 10.7965 8.63522C10.7967 8.42584 10.7214 8.20509 10.5707 7.7636L9.38652 4.55681C9.24855 4.17739 9.17957 3.98768 9.05792 3.8478C8.95056 3.72418 8.81448 3.62884 8.66162 3.5702C8.48857 3.5037 8.28663 3.5037 7.88276 3.5037H5.06618C4.58595 3.5037 4.34584 3.5037 4.14005 3.603C3.96952 3.68518 3.80221 3.84073 3.70774 4.00473C3.5937 4.20284 3.57786 4.42034 3.54617 4.85534C3.51837 5.23446 3.5043 5.61736 3.5043 6.00359" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div> <div class="contact-label">Phone</div> <div class="contact-value"><a href="tel:${contact.phone}">${contact.phone}</a></div> </div> </div> <div class="contact-item"> <div class="contact-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Whispr Messaging</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f8f9fa; display: flex; justify-content: center; align-items: center; min-height: 700px; overflow: hidden; } .chat-container { width: 100%; max-width: 700px; height: 700px; background-color: #ffffff; border-radius: 24px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); overflow: hidden; display: flex; flex-direction: column; } .header { padding: 20px; background: linear-gradient(to right, #a18cd1, #fbc2eb); color: white; display: flex; justify-content: space-between; align-items: center; position: relative; } .header h1 { font-size: 24px; font-weight: 600; } .search-container { margin: 15px 20px; position: relative; } .search-icon { position: absolute; left: 15px; top: 50%; transform: translateY(-50%); color: #adb5bd; } .search-input { width: 100%; padding: 14px 14px 14px 45px; border: none; background-color: #f1f3f5; border-radius: 20px; font-size: 14px; transition: all 0.3s; } .search-input:focus { outline: none; box-shadow: 0 0 0 2px rgba(161, 140, 209, 0.3); } .chat-filters { display: flex; gap: 10px; padding: 0 20px; margin-bottom: 10px; } .filter-btn { background: none; border: none; padding: 8px 16px; border-radius: 16px; font-size: 14px; cursor: pointer; color: #6c757d; transition: all 0.3s; } .filter-btn.active { background-color: #a18cd1; color: white; } .filter-btn:hover:not(.active) { background-color: #f1f3f5; } .chat-list { flex: 1; overflow-y: auto; padding: 0 0 20px 0; } .chat-item { display: flex; align-items: center; padding: 15px 20px; border-radius: 16px; margin: 0 10px 8px 10px; cursor: pointer; transition: transform 0.3s, background-color 0.3s; position: relative; overflow: hidden; background-color: white; } .chat-item:hover { background-color: #f8f9fa; transform: translateX(5px); } .avatar-container { position: relative; margin-right: 15px; } .avatar { width: 55px; height: 55px; border-radius: 50%; object-fit: cover; border: 2px solid transparent; transition: border 0.3s; } .chat-item:hover .avatar { border-color: #a18cd1; } .status-indicator { position: absolute; bottom: 2px; right: 2px; width: 14px; height: 14px; border-radius: 50%; border: 2px solid white; } .status-online { background-color: #40c057; } .status-away { background-color: #fd7e14; } .status-offline { background-color: #adb5bd; } .chat-content { flex: 1; overflow: hidden; } .chat-title { display: flex; justify-content: space-between; margin-bottom: 5px; } .chat-name { font-weight: 600; color: #212529; } .chat-time { font-size: 12px; color: #adb5bd; } .chat-message { display: flex; justify-content: space-between; align-items: center; } .message-preview { font-size: 14px; color: #6c757d; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 70%; } .unread-indicator { background-color: #a18cd1; color: white; font-size: 12px; width: 20px; height: 20px; border-radius: 50%; display: flex; justify-content: center; align-items: center; } .typing-indicator { font-size: 14px; color: #a18cd1; font-style: italic; } .swipe-actions { position: absolute; top: 0; right: 0; height: 100%; display: flex; transform: translateX(100%); transition: transform 0.3s; } .archive-btn, .mute-btn { display: flex; align-items: center; justify-content: center; width: 70px; height: 100%; color: white; font-size: 20px; } .archive-btn { background-color: #20c997; } .mute-btn { background-color: #6c757d; } .chat-item.swiped { transform: translateX(-140px); } .chat-item.swiped .swipe-actions { transform: translateX(0); } .action-menu { position: absolute; bottom: 15px; left: 0; right: 0; background-color: white; border-radius: 20px 20px 0 0; padding: 20px; z-index: 100; box-shadow: 0 -5px 20px rgba(0, 0, 0, 0.1); transform: translateY(100%); transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .action-menu.active { transform: translateY(0); } .action-menu-header { display: flex; justify-content: space-between; margin-bottom: 15px; } .action-menu-title { font-weight: 600; font-size: 18px; } .close-action-menu { background: none; border: none; color: #adb5bd; font-size: 18px; cursor: pointer; } .action-menu-options { display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; } .action-option { display: flex; flex-direction: column; align-items: center; gap: 8px; cursor: pointer; } .action-icon { width: 50px; height: 50px; border-radius: 50%; display: flex; justify-content: center; align-items: center; color: white; font-size: 20px; } .action-label { font-size: 12px; text-align: center; } /* Custom scrollbar */ .chat-list::-webkit-scrollbar { width: 6px; } .chat-list::-webkit-scrollbar-track { background: #f1f3f5; } .chat-list::-webkit-scrollbar-thumb { background-color: #adb5bd; border-radius: 20px; } /* Animations */ @keyframes pulse { 0% { opacity: 0.6; } 50% { opacity: 1; } 100% { opacity: 0.6; } } .typing-indicator { animation: pulse 1.5s infinite; } @keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .chat-item { animation: slideIn 0.3s forwards; } .chat-item:nth-child(1) { animation-delay: 0.1s; } .chat-item:nth-child(2) { animation-delay: 0.2s; } .chat-item:nth-child(3) { animation-delay: 0.3s; } .chat-item:nth-child(4) { animation-delay: 0.4s; } .chat-item:nth-child(5) { animation-delay: 0.5s; } .chat-item:nth-child(6) { animation-delay: 0.6s; } /* Responsive adjustments */ @media (max-width: 480px) { .chat-container { border-radius: 0; height: 100vh; } .action-menu-options { grid-template-columns: repeat(3, 1fr); } } /* Theme toggle button */ .theme-toggle { background: none; border: none; color: white; font-size: 20px; cursor: pointer; transition: transform 0.3s; } .theme-toggle:hover { transform: rotate(30deg); } /* Create chat fab button */ .fab { position: absolute; bottom: 20px; right: 20px; width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(to right, #a18cd1, #fbc2eb); color: white; display: flex; justify-content: center; align-items: center; font-size: 24px; box-shadow: 0 4px 15px rgba(161, 140, 209, 0.4); cursor: pointer; transition: all 0.3s; } .fab:hover { transform: translateY(-5px); box-shadow: 0 8px 20px rgba(161, 140, 209, 0.6); } .backdrop { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); z-index: 90; opacity: 0; pointer-events: none; transition: opacity 0.3s; } .backdrop.active { opacity: 1; pointer-events: all; } /* Dark theme */ body.dark-theme { background-color: #1a1a2e; } body.dark-theme .chat-container { background-color: #222237; } body.dark-theme .search-input { background-color: #2d2d42; color: #e9ecef; } body.dark-theme .chat-item { background-color: #2d2d42; } body.dark-theme .chat-item:hover { background-color: #373756; } body.dark-theme .chat-name { color: #f8f9fa; } body.dark-theme .message-preview { color: #adb5bd; } body.dark-theme .action-menu { background-color: #222237; } body.dark-theme .action-menu-title { color: #f8f9fa; } body.dark-theme .action-label { color: #e9ecef; } body.dark-theme .filter-btn { color: #adb5bd; } body.dark-theme .filter-btn:hover:not(.active) { background-color: #2d2d42; } </style> </head> <body> <div class="chat-container"> <div class="header"> <h1>Whispr</h1> <button class="theme-toggle" id="themeToggle"> <i class="fas fa-moon"></i> </button> </div> <div class="search-container"> <div class="search-icon"> <i class="fas fa-search"></i> </div> <input type="text" class="search-input" placeholder="Search conversations..."> </div> <div class="chat-filters"> <button class="filter-btn active">All</button> <button class="filter-btn">Unread (4)</button> <button class="filter-btn">Groups</button> <button class="filter-btn">Favorites</button> </div> <div class="chat-list"> <div class="chat-item" data-id="1"> <div class="avatar-container"> <img src="https://images.unsplash.com/photo-1580489944761-15a19d654956?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="Profile" class="avatar"> <div class="status-indicator status-online"></div> </div> <div class="chat-content"> <div class="chat-title"> <div class="chat-name">Sophia Chen</div> <div class="chat-time">11:42 AM</div> </div> <div class="chat-message"> <div class="typing-indicator">typing...</div> </div> </div> <div class="swipe-actions"> <div class="archive-btn"> <i class="fas fa-archive"></i> </div> <div class="mute-btn"> <i class="fas fa-bell-slash"></i> </div> </div> </div> <div class="chat-item" data-id="2"> <div class="avatar-container"> <img src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="Profile" class="avatar"> <div class="status-indicator status-online"></div> </div> <div class="chat-content"> <div class="chat-title"> <div class="chat-name">Design Team</div> <div class="chat-time">10:15 AM</div> </div> <div class="chat-message"> <div class="message-preview">Noah: The new wireframes look amazing! Can we discuss...</div> <div class="unread-indicator">3</div> </div> </div> <div class="swipe-actions"> <div class="archive-btn"> <i class="fas fa-archive"></i> </div> <div class="mute-btn"> <i class="fas fa-bell-slash"></i> </div> </div> </div> <div class="chat-item" data-id="3"> <div class="avatar-container"> <img src="https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="Profile" class="avatar"> <div class="status-indicator status-away"></div> </div> <div class="chat-content"> <div class="chat-title"> <div class="chat-name">Jackson Wright</div> <div class="chat-time">Yesterday</div> </div> <div class="chat-message"> <div class="message-preview">Can you send me that project brief we discussed?</div> <div class="unread-indicator">1</div> </div> </div> <div class="swipe-actions"> <div class="archive-btn"> <i class="fas fa-archive"></i> </div> <div class="mute-btn"> <i class="fas fa-bell-slash"></i> </div> </div> </div> <div class="chat-item" data-id="4"> <div class="avatar-container"> <img src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="Profile" class="avatar"> <div class="status-indicator status-offline"></div> </div> <div class="chat-content"> <div class="chat-title"> <div class="chat-name">Ava Rodriguez</div> <div class="chat-time">Yesterday</div> </div> <div class="chat-message"> <div class="message-preview">Thanks for your help with the presentation! The client loved it ✨</div> </div> </div> <div class="swipe-actions"> <div class="archive-btn"> <i class="fas fa-archive"></i> </div> <div class="mute-btn"> <i class="fas fa-bell-slash"></i> </div> </div> </div> <div class="chat-item" data-id="5"> <div class="avatar-container"> <img src="https://images.unsplash.com/photo-1539571696357-5a69c17a67c6?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="Profile" class="avatar"> <div class="status-indicator status-offline"></div> </div> <div class="chat-content"> <div class="chat-title"> <div class="chat-name">Coffee Crew ☕</div> <div class="chat-time">Tuesday</div> </div> <div class="chat-message"> <div class="message-preview">Ethan: Anyone up for a coffee break at 3? I found this cool new place nearby</div> </div> </div> <div class="swipe-actions"> <div class="archive-btn"> <i class="fas fa-archive"></i> </div> <div class="mute-btn"> <i class="fas fa-bell-slash"></i> </div> </div> </div> <div class="chat-item" data-id="6"> <div class="avatar-container"> <img src="https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="Profile" class="avatar"> <div class="status-indicator status-offline"></div> </div> <div class="chat-content"> <div class="chat-title"> <div class="chat-name">Dev Standup</div> <div class="chat-time">Monday</div> </div> <div class="chat-message"> <div class="message-preview">Meeting link for tomorrow's standup: whispr.meet/dev-team-324</div> </div> </div> <div class="swipe-actions"> <div class="archive-btn"> <i class="fas fa-archive"></i> </div> <div class="mute-btn"> <i class="fas fa-bell-slash"></i> </div> </div> </div> </div> <div class="fab" id="createChat"> <i class="fas fa-plus"></i> </div> <div class="backdrop" id="backdrop"></div> <div class="action-menu" id="actionMenu"> <div class="action-menu-header"> <div class="action-menu-title">Chat Options</div> <button class="close-action-menu" id="closeActionMenu"> <i class="fas fa-times"></i> </button> </div> <div class="action-menu-options"> <div class="action-option"> <div class="action-icon" style="background-color: #4dabf7;"> <i class="fas fa-video"></i> </div> <div class="action-label">Video Call</div> </div> <div class="action-option"> <div class="action-icon" style="background-color: #51cf66;"> <i class="fas fa-phone-alt"></i> </div> <div class="action-label">Voice Call</div> </div> <div class="action-option"> <div class="action-icon" style="background-color: #ff922b;"> <i class="fas fa-file"></i> </div> <div class="action-label">Files</div> </div> <div class="action-option"> <div class="action-icon" style="background-color: #f06595;"> <i class="fas fa-image"></i> </div> <div class="action-label">Photos</div> </div> <div class="action-option"> <div class="action-icon" style="background-color: #845ef7;"> <i class="fas fa-cog"></i> </div> <div class="action-label">Settings</div> </div> <div class="action-option"> <div class="action-icon" style="background-color: #20c997;"> <i class="fas fa-star"></i> </div> <div class="action-label">Favorite</div> </div> <div class="action-option"> <div class="action-icon" style="background-color: #fa5252;"> <i class="fas fa-trash"></i> </div> <div class="action-label">Delete</div> </div> <div class="action-option"> <div class="action-icon" style="background-color: #339af0;"> <i class="fas fa-bell-slash"></i> </div> <div class="action-label">Mute</div> </div> </div> </div> </div> <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script> <script> document.addEventListener('DOMContentLoaded', function() { // Initialize variables const chatItems = document.querySelectorAll('.chat-item'); const actionMenu = document.getElementById('actionMenu'); const backdrop = document.getElementById('backdrop'); const closeActionMenu = document.getElementById('closeActionMenu'); const themeToggle = document.getElementById('themeToggle'); const createChatBtn = document.getElementById('createChat'); let startX, moveX, currentX, initialX, xDiff; let swipedItem = null; // Load icons alternatively since FontAwesome CDN might not work in all contexts const iconFallback = () => { document.querySelectorAll('.fas').forEach(icon => { const className = icon.className; if (className.includes('fa-search')) icon.innerHTML = '🔍'; if (className.includes('fa-moon')) icon.innerHTML = '🌙'; if (className.includes('fa-archive')) icon.innerHTML = '📦'; if (className.includes('fa-bell-slash')) icon.innerHTML = '🔕'; if (className.includes('fa-plus')) icon.innerHTML = '+'; if (className.includes('fa-times')) icon.innerHTML = '✕'; if (className.includes('fa-video')) icon.innerHTML = '📹'; if (className.includes('fa-phone-alt')) icon.innerHTML = '📞'; if (className.includes('fa-file')) icon.innerHTML = '📄'; if (className.includes('fa-image')) icon.innerHTML = '🖼️'; if (className.includes('fa-cog')) icon.innerHTML = '⚙️'; if (className.includes('fa-star')) icon.innerHTML = '⭐'; if (className.includes('fa-trash')) icon.innerHTML = '🗑️'; }); }; // Call icon fallback in case FontAwesome doesn't load setTimeout(iconFallback, 1000); // Toggle Dark Theme themeToggle.addEventListener('click', function() { document.body.classList.toggle('dark-theme'); const icon = themeToggle.querySelector('i'); if (document.body.classList.contains('dark-theme')) { icon.className = 'fas fa-sun'; icon.innerHTML = '☀️'; // Fallback } else { icon.className = 'fas fa-moon'; icon.innerHTML = '🌙'; // Fallback } }); // Swipe functionality for chat items chatItems.forEach(item => { // Touch start event item.addEventListener('touchstart', e => { startX = e.touches[0].clientX; initialX = item.getBoundingClientRect().left; // Reset any previously swiped item if (swipedItem && swipedItem !== item) { swipedItem.classList.remove('swiped'); } }); // Touch move event item.addEventListener('touchmove', e => { moveX = e.touches[0].clientX; xDiff = startX - moveX; // Only allow swiping left if (xDiff > 0) { currentX = initialX - xDiff; item.style.transform = `translateX(${-xDiff}px)`; } }); // Touch end event item.addEventListener('touchend', e => { item.style.transform = ''; if (xDiff > 80) { // Threshold to trigger swipe item.classList.add('swiped'); swipedItem = item; } else { item.classList.remove('swiped'); } }); // Mouse events for desktop let isMouseDown = false; item.addEventListener('mousedown', e => { isMouseDown = true; startX = e.clientX; initialX = item.getBoundingClientRect().left; // Reset any previously swiped item if (swipedItem && swipedItem !== item) { swipedItem.classList.remove('swiped'); } }); document.addEventListener('mousemove', e => { if (!isMouseDown) return; moveX = e.clientX; xDiff = startX - moveX; // Only allow swiping left if (xDiff > 0) { currentX = initialX - xDiff; item.style.transform = `translateX(${-xDiff}px)`; } }); document.addEventListener('mouseup', e => { if (!isMouseDown) return; isMouseDown = false; item.style.transform = ''; if (xDiff > 80) { // Threshold to trigger swipe item.classList.add('swiped'); swipedItem = item; } else { item.classList.remove('swiped'); } }); // Click event to open chat options item.addEventListener('click', e => { if (!item.classList.contains('swiped')) { // Prevent opening action menu when clicking archive or mute buttons if (e.target.closest('.swipe-actions')) return; actionMenu.classList.add('active'); backdrop.classList.add('active'); } }); // Archive and mute functionality const archiveBtn = item.querySelector('.archive-btn'); const muteBtn = item.querySelector('.mute-btn'); archiveBtn.addEventListener('click', e => { e.stopPropagation(); item.style.transform = 'translateX(-100%)'; item.style.opacity = '0'; setTimeout(() => { item.remove(); }, 300); }); muteBtn.addEventListener('click', e => { e.stopPropagation(); muteBtn.innerHTML = muteBtn.innerHTML.includes('slash') ? '<i class="fas fa-bell"></i>' : '<i class="fas fa-bell-slash"></i>'; item.classList.remove('swiped'); }); }); // Close action menu closeActionMenu.addEventListener('click', () => { actionMenu.classList.remove('active'); backdrop.classList.remove('active'); }); backdrop.addEventListener('click', () => { actionMenu.classList.remove('active'); backdrop.classList.remove('active'); }); // Create chat button createChatBtn.addEventListener('click', () => { const pulse = document.createElement('div'); pulse.style.position = 'absolute'; pulse.style.width = '100%'; pulse.style.height = '100%'; pulse.style.borderRadius = '50%'; pulse.style.backgroundColor = 'rgba(255, 255, 255, 0.3)'; pulse.style.animation = 'pulse 0.8s forwards'; createChatBtn.appendChild(pulse); setTimeout(() => { pulse.remove(); actionMenu.classList.add('active'); backdrop.classList.add('active'); }, 300); }); // Filter buttons const filterBtns = document.querySelectorAll('.filter-btn'); filterBtns.forEach(btn => { btn.addEventListener('click', () => { filterBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); }); }); // Search functionality const searchInput = document.querySelector('.search-input'); searchInput.addEventListener('input', () => { const searchTerm = searchInput.value.toLowerCase(); chatItems.forEach(item => { const name = item.querySelector('.chat-name').textContent.toLowerCase(); const message = item.querySelector('.message-preview')?.textContent.toLowerCase() || ''; if (name.includes(searchTerm) || message.includes(searchTerm)) { item.style.display = 'flex'; } else { item.style.display = 'none'; } }); }); // Simulating real-time typing indicator animation const typingIndicator = document.querySelector('.typing-indicator'); let typingDots = 0; setInterval(() => { typingDots = (typingDots + 1) % 4; let dots = ''; for (let i = 0; i < typingDots; i++) { dots += '.'; } typingIndicator.textContent = 'typing' + dots; }, 500); // Simulating new message arriving setTimeout(() => { const firstChat = document.querySelector('.chat-item[data-id="1"]'); const chatMessage = firstChat.querySelector('.chat-message'); // Replace typing indicator with actual message chatMessage.innerHTML = ` <div class="message-preview">Just sent you the Q3 marketing plan. Let me know your thoughts!</div> <div class="unread-indicator">1</div> `; // Add highlight animation firstChat.style.animation = 'none'; firstChat.offsetHeight; // Trigger reflow firstChat.style.animation = 'pulse 1.5s'; firstChat.style.backgroundColor = 'rgba(161, 140, 209, 0.1)'; setTimeout(() => { firstChat.style.backgroundColor = ''; }, 2000); }, 5000); // Action option interactions const actionOptions = document.querySelectorAll('.action-option'); actionOptions.forEach(option => { option.addEventListener('click', () => { const label = option.querySelector('.action-label').textContent; const icon = option.querySelector('.action-icon'); // Simulate action feedback icon.style.transform = 'scale(0.8)'; setTimeout(() => { icon.style.transform = 'scale(1)'; setTimeout(() => { actionMenu.classList.remove('active'); backdrop.classList.remove('active'); }, 200); }, 200); }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Terrazzo - Seasonal Mediterranean</title> <style> /* Font imports */ @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Work+Sans:wght@300;400;500;600&display=swap'); :root { --color-earth: #A97C50; --color-olive: #696C40; --color-sage: #C2C5AA; --color-cream: #F5F1E9; --color-terracotta: #C06D44; --color-rust: #9A4B31; --transition: all 0.35s cubic-bezier(0.25, 1, 0.5, 1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Work Sans', sans-serif; background-color: var(--color-cream); color: #333; padding: 0; overflow-x: hidden; max-width: 700px; margin: 0 auto; height: 100vh; display: flex; flex-direction: column; } .container { padding: 20px; overflow-y: auto; scrollbar-width: thin; flex: 1; } .container::-webkit-scrollbar { width: 8px; } .container::-webkit-scrollbar-track { background: transparent; } .container::-webkit-scrollbar-thumb { background-color: var(--color-earth); border-radius: 20px; } .header { text-align: center; margin-bottom: 25px; position: relative; } .logo { font-family: 'Playfair Display', serif; font-size: 2.5rem; font-weight: 700; color: var(--color-earth); margin-bottom: 5px; letter-spacing: 1px; } .tagline { font-size: 0.95rem; font-weight: 400; letter-spacing: 2px; color: var(--color-olive); text-transform: uppercase; } .divider { display: flex; align-items: center; margin: 15px 0; } .divider-line { flex: 1; height: 1px; background-color: var(--color-earth); opacity: 0.3; } .divider-icon { margin: 0 15px; color: var(--color-earth); font-size: 0.8rem; } .menu-nav { display: flex; justify-content: center; margin-bottom: 30px; position: sticky; top: 0; background-color: var(--color-cream); padding: 15px 0; z-index: 10; border-bottom: 1px solid rgba(169, 124, 80, 0.2); } .nav-item { margin: 0 15px; font-weight: 500; font-size: 0.95rem; color: var(--color-olive); cursor: pointer; position: relative; transition: var(--transition); text-transform: uppercase; letter-spacing: 1px; } .nav-item:after { content: ""; position: absolute; bottom: -5px; left: 0; height: 2px; width: 0; background-color: var(--color-terracotta); transition: var(--transition); } .nav-item:hover, .nav-item.active { color: var(--color-terracotta); } .nav-item:hover:after, .nav-item.active:after { width: 100%; } .menu-section { margin-bottom: 40px; display: none; } .menu-section.active { display: block; animation: fadeIn 0.5s ease-in-out; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .section-title { font-family: 'Playfair Display', serif; font-size: 1.8rem; margin-bottom: 20px; color: var(--color-rust); position: relative; display: inline-block; } .section-title:after { content: ""; position: absolute; bottom: -5px; left: 0; height: 2px; width: 40%; background-color: var(--color-terracotta); } .menu-items { display: grid; grid-template-columns: 1fr; gap: 20px; } .menu-item { background-color: white; border-radius: 8px; overflow: hidden; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); transition: var(--transition); position: relative; cursor: pointer; } .menu-item:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); } .item-header { padding: 18px; padding-bottom: 0; display: flex; justify-content: space-between; align-items: flex-start; } .item-name { font-family: 'Playfair Display', serif; font-size: 1.3rem; margin-bottom: 5px; color: var(--color-earth); transition: var(--transition); } .menu-item:hover .item-name { color: var(--color-terracotta); } .item-price { font-weight: 600; font-size: 1.1rem; color: var(--color-terracotta); background-color: var(--color-cream); padding: 5px 12px; border-radius: 20px; } .item-desc { padding: 0 18px; margin-bottom: 12px; font-size: 0.95rem; line-height: 1.5; color: #666; } .item-icons { padding: 0 18px 18px; display: flex; gap: 10px; } .icon { padding: 5px 10px; border-radius: 15px; font-size: 0.8rem; font-weight: 500; background-color: var(--color-sage); color: var(--color-olive); white-space: nowrap; } .item-details { max-height: 0; overflow: hidden; transition: max-height 0.5s ease; background-color: var(--color-cream); border-top: 1px solid rgba(169, 124, 80, 0.1); } .item-details-inner { padding: 18px; } .details-title { font-family: 'Playfair Display', serif; font-size: 1rem; margin-bottom: 10px; color: var(--color-olive); } .ingredients-list { list-style-type: none; margin-bottom: 15px; columns: 2; } .ingredients-list li { font-size: 0.9rem; margin-bottom: 5px; position: relative; padding-left: 15px; } .ingredients-list li:before { content: "•"; position: absolute; left: 0; color: var(--color-terracotta); } .customization { margin-top: 15px; } .options-list { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; } .option-item { background-color: white; border: 1px solid var(--color-sage); border-radius: 20px; padding: 5px 12px; font-size: 0.9rem; cursor: pointer; transition: var(--transition); } .option-item:hover { background-color: var(--color-sage); color: var(--color-olive); } .option-item.selected { background-color: var(--color-olive); color: white; border-color: var(--color-olive); } .add-button { display: block; width: 100%; padding: 12px; background-color: var(--color-earth); color: white; border: none; border-radius: 4px; margin-top: 15px; font-weight: 600; cursor: pointer; transition: var(--transition); font-family: 'Work Sans', sans-serif; } .add-button:hover { background-color: var(--color-terracotta); } .expanded .item-details { max-height: 500px; } .cart-button { position: fixed; bottom: 20px; right: 20px; width: 60px; height: 60px; border-radius: 50%; background-color: var(--color-terracotta); display: flex; justify-content: center; align-items: center; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); cursor: pointer; transition: var(--transition); z-index: 100; } .cart-button:hover { transform: scale(1.05); background-color: var(--color-rust); } .cart-icon { color: white; font-size: 1.5rem; } .cart-count { position: absolute; top: -5px; right: -5px; background-color: var(--color-olive); color: white; width: 25px; height: 25px; border-radius: 50%; display: flex; justify-content: center; align-items: center; font-size: 0.8rem; font-weight: 600; } .toast { position: fixed; top: 20px; left: 50%; transform: translateX(-50%) translateY(-100px); background-color: var(--color-earth); color: white; padding: 12px 20px; border-radius: 4px; font-weight: 500; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); z-index: 1000; opacity: 0; transition: transform 0.5s ease, opacity 0.5s ease; } .toast.show { transform: translateX(-50%) translateY(0); opacity: 1; } /* Seasonal tag */ .seasonal-tag { position: absolute; top: 12px; right: -30px; background-color: var(--color-terracotta); color: white; padding: 5px 30px; font-size: 0.8rem; font-weight: 500; transform: rotate(45deg); z-index: 1; } /* Media Queries */ @media (min-width: 520px) { .menu-items { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 520px) { .logo { font-size: 2rem; } .tagline { font-size: 0.85rem; } .menu-nav { overflow-x: auto; justify-content: flex-start; padding-bottom: 10px; } .nav-item { margin: 0 10px; font-size: 0.85rem; white-space: nowrap; } .section-title { font-size: 1.5rem; } .item-name { font-size: 1.2rem; } .ingredients-list { columns: 1; } } </style> </head> <body> <div class="container"> <div class="header"> <h1 class="logo">Terrazzo</h1> <p class="tagline">Seasonal Mediterranean</p> <div class="divider"> <div class="divider-line"></div> <div class="divider-icon">✽</div> <div class="divider-line"></div> </div> </div> <div class="menu-nav"> <div class="nav-item active" data-target="starters">Starters</div> <div class="nav-item" data-target="mains">Mains</div> <div class="nav-item" data-target="pastas">Pastas</div> <div class="nav-item" data-target="desserts">Desserts</div> <div class="nav-item" data-target="drinks">Drinks</div> </div> <div class="menu-section active" id="starters"> <h2 class="section-title">Starters</h2> <div class="menu-items"> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Burrata di Stagione</h3> <span class="item-price">$16</span> </div> <p class="item-desc">Fresh burrata with seasonal heirloom tomatoes, peach slices, crushed pistachios, and basil oil.</p> <div class="item-icons"> <span class="icon">Vegetarian</span> <span class="icon">Gluten-Free</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Fresh burrata cheese</li> <li>Heirloom tomatoes</li> <li>Ripe peaches</li> <li>Sicilian pistachios</li> <li>Maldon sea salt</li> <li>Cold-pressed olive oil</li> <li>House-made basil oil</li> <li>Aged balsamic reduction</li> </ul> <div class="customization"> <h4 class="details-title">Customization</h4> <div class="options-list" data-option-group="add-on"> <div class="option-item" data-option="prosciutto">Add Prosciutto (+$5)</div> <div class="option-item" data-option="extra-burrata">Extra Burrata (+$7)</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> <div class="menu-item"> <div class="seasonal-tag">Seasonal</div> <div class="item-header"> <h3 class="item-name">Octopus Carpaccio</h3> <span class="item-price">$18</span> </div> <p class="item-desc">Thinly sliced, sous-vide octopus with preserved lemon, calabrian chilies, capers, and smoked paprika oil.</p> <div class="item-icons"> <span class="icon">Gluten-Free</span> <span class="icon">Protein-Rich</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Spanish octopus</li> <li>Preserved Meyer lemon</li> <li>Calabrian chilies</li> <li>Capers from Pantelleria</li> <li>Smoked paprika oil</li> <li>Microgreens</li> <li>Cracked black pepper</li> <li>Fleur de sel</li> </ul> <div class="customization"> <h4 class="details-title">Spice Level</h4> <div class="options-list" data-option-group="spice"> <div class="option-item selected" data-option="mild">Mild</div> <div class="option-item" data-option="medium">Medium</div> <div class="option-item" data-option="spicy">Spicy</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Zucchini Fritti</h3> <span class="item-price">$14</span> </div> <p class="item-desc">Lightly battered zucchini strips with lemon-garlic aioli, fresh mint, and Parmigiano shavings.</p> <div class="item-icons"> <span class="icon">Vegetarian</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Local zucchini</li> <li>Tempura batter</li> <li>House-made aioli</li> <li>Organic lemon zest</li> <li>Garlic confit</li> <li>Parmigiano Reggiano</li> <li>Fresh mint leaves</li> <li>Aleppo pepper</li> </ul> <div class="customization"> <h4 class="details-title">Dipping Sauce</h4> <div class="options-list" data-option-group="sauce"> <div class="option-item selected" data-option="lemon-aioli">Lemon-Garlic Aioli</div> <div class="option-item" data-option="harissa">Harissa Dip</div> <div class="option-item" data-option="yogurt">Herb Yogurt</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Arancini Siciliani</h3> <span class="item-price">$15</span> </div> <p class="item-desc">Saffron risotto croquettes filled with wild mushrooms, fontina, and black truffle pesto.</p> <div class="item-icons"> <span class="icon">Vegetarian</span> <span class="icon">House Favorite</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Carnaroli rice</li> <li>Saffron threads</li> <li>Wild mushroom blend</li> <li>Fontina Val d'Aosta</li> <li>Black truffle pesto</li> <li>Panko breadcrumbs</li> <li>San Marzano tomato sauce</li> <li>Fresh basil</li> </ul> <div class="customization"> <h4 class="details-title">Serving Size</h4> <div class="options-list" data-option-group="size"> <div class="option-item" data-option="small">Small (3 pieces)</div> <div class="option-item selected" data-option="regular">Regular (5 pieces)</div> <div class="option-item" data-option="large">Large (8 pieces +$6)</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> </div> </div> <div class="menu-section" id="mains"> <h2 class="section-title">Mains</h2> <div class="menu-items"> <div class="menu-item"> <div class="seasonal-tag">Seasonal</div> <div class="item-header"> <h3 class="item-name">Branzino al Cartoccio</h3> <span class="item-price">$32</span> </div> <p class="item-desc">Mediterranean sea bass baked in parchment with fennel, olives, preserved lemon, and white wine.</p> <div class="item-icons"> <span class="icon">Gluten-Free</span> <span class="icon">Protein-Rich</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Line-caught sea bass</li> <li>Fennel bulb</li> <li>Castelvetrano olives</li> <li>Preserved Meyer lemon</li> <li>Fresh thyme</li> <li>Dry white wine</li> <li>Baby potatoes</li> <li>Cherry tomatoes</li> </ul> <div class="customization"> <h4 class="details-title">Side Options</h4> <div class="options-list" data-option-group="side"> <div class="option-item selected" data-option="potatoes">Herbed Potatoes</div> <div class="option-item" data-option="polenta">Creamy Polenta</div> <div class="option-item" data-option="grains">Ancient Grains</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Osso Buco Milanese</h3> <span class="item-price">$36</span> </div> <p class="item-desc">Slow-braised veal shanks with saffron risotto, gremolata, and roasted bone marrow.</p> <div class="item-icons"> <span class="icon">Chef's Special</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Pasture-raised veal shank</li> <li>Mirepoix vegetables</li> <li>San Marzano tomatoes</li> <li>Red wine reduction</li> <li>Saffron risotto</li> <li>Lemon-parsley gremolata</li> <li>Bone marrow</li> <li>Veal demi-glace</li> </ul> <div class="customization"> <h4 class="details-title">Doneness</h4> <div class="options-list" data-option-group="doneness"> <div class="option-item" data-option="medium">Medium</div> <div class="option-item selected" data-option="tender">Fall-off-the-bone</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Eggplant Parmigiana</h3> <span class="item-price">$24</span> </div> <p class="item-desc">Layered fried eggplant with San Marzano tomato sauce, fior di latte, basil, and Parmigiano-Reggiano.</p> <div class="item-icons"> <span class="icon">Vegetarian</span> <span class="icon">House Favorite</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Sicilian eggplant</li> <li>San Marzano tomatoes</li> <li>Fior di latte mozzarella</li> <li>Parmigiano-Reggiano</li> <li>Fresh basil</li> <li>Garlic confit</li> <li>Extra virgin olive oil</li> <li>Sea salt</li> </ul> <div class="customization"> <h4 class="details-title">Add Protein</h4> <div class="options-list" data-option-group="protein"> <div class="option-item selected" data-option="none">None</div> <div class="option-item" data-option="chicken">Chicken (+$6)</div> <div class="option-item" data-option="sausage">Italian Sausage (+$5)</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Moroccan Spiced Rack of Lamb</h3> <span class="item-price">$38</span> </div> <p class="item-desc">Herb-crusted rack of lamb with harissa rub, cumin-scented couscous, roasted vegetables, and mint yogurt.</p> <div class="item-icons"> <span class="icon">Protein-Rich</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>New Zealand rack of lamb</li> <li>Moroccan spice blend</li> <li>Harissa paste</li> <li>Fresh herb crust</li> <li>Couscous</li> <li>Seasonal vegetables</li> <li>Preserved lemon</li> <li>Mint-yogurt sauce</li> </ul> <div class="customization"> <h4 class="details-title">Cooking Temperature</h4> <div class="options-list" data-option-group="temp"> <div class="option-item" data-option="medium-rare">Medium Rare</div> <div class="option-item selected" data-option="medium">Medium</div> <div class="option-item" data-option="medium-well">Medium Well</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> </div> </div> <div class="menu-section" id="pastas"> <h2 class="section-title">Pastas</h2> <div class="menu-items"> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Tagliatelle al Tartufo</h3> <span class="item-price">$28</span> </div> <p class="item-desc">Hand-rolled egg tagliatelle with black truffle butter, Parmigiano Reggiano, and fresh black truffle shavings.</p> <div class="item-icons"> <span class="icon">Vegetarian</span> <span class="icon">House Favorite</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>House-made egg pasta</li> <li>Black truffle butter</li> <li>Black truffle shavings</li> <li>Parmigiano Reggiano</li> <li>Chives</li> <li>Black pepper</li> <li>Garlic-infused olive oil</li> <li>Sea salt</li> </ul> <div class="customization"> <h4 class="details-title">Add Protein</h4> <div class="options-list" data-option-group="protein"> <div class="option-item selected" data-option="none">None</div> <div class="option-item" data-option="chicken">Grilled Chicken (+$6)</div> <div class="option-item" data-option="shrimp">Garlic Shrimp (+$8)</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> <div class="menu-item"> <div class="seasonal-tag">Seasonal</div> <div class="item-header"> <h3 class="item-name">Pappardelle al Cinghiale</h3> <span class="item-price">$26</span> </div> <p class="item-desc">Wide ribbon pasta with slow-braised wild boar ragù, juniper berries, rosemary, and aged pecorino.</p> <div class="item-icons"> <span class="icon">Chef's Special</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Fresh pappardelle pasta</li> <li>Wild boar shoulder</li> <li>Chianti wine</li> <li>San Marzano tomatoes</li> <li>Juniper berries</li> <li>Fresh rosemary</li> <li>Mirepoix vegetables</li> <li>Aged pecorino cheese</li> </ul> <div class="customization"> <h4 class="details-title">Pasta Options</h4> <div class="options-list" data-option-group="pasta"> <div class="option-item selected" data-option="regular">Regular Pasta</div> <div class="option-item" data-option="gluten-free">Gluten-Free (+$3)</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Linguine alle Vongole</h3> <span class="item-price">$25</span> </div> <p class="item-desc">Linguine with fresh clams, white wine, garlic, parsley, chili flakes, and lemon zest in a light sauce.</p> <div class="item-icons"> <span class="icon">Seafood</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>House-made linguine</li> <li>Fresh Manila clams</li> <li>Dry white wine</li> <li>Garlic</li> <li>Italian parsley</li> <li>Calabrian chili</li> <li>Lemon zest</li> <li>Extra virgin olive oil</li> </ul> <div class="customization"> <h4 class="details-title">Preparation Style</h4> <div class="options-list" data-option-group="style"> <div class="option-item selected" data-option="bianco">Bianco (White Wine)</div> <div class="option-item" data-option="rosso">Rosso (Tomato)</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Rigatoni alla Norma</h3> <span class="item-price">$22</span> </div> <p class="item-desc">Tube pasta with fried eggplant, tomato sauce, fresh basil, and ricotta salata in traditional Sicilian style.</p> <div class="item-icons"> <span class="icon">Vegetarian</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Bronze-die rigatoni</li> <li>Italian eggplant</li> <li>San Marzano tomatoes</li> <li>Garlic</li> <li>Fresh basil</li> <li>Ricotta salata</li> <li>Chili flakes</li> <li>Extra virgin olive oil</li> </ul> <div class="customization"> <h4 class="details-title">Spice Level</h4> <div class="options-list" data-option-group="spice"> <div class="option-item selected" data-option="mild">Mild</div> <div class="option-item" data-option="medium">Medium</div> <div class="option-item" data-option="spicy">Spicy</div> </div> </div> <button class="add-button">Add to Order</button> </div> </div> </div> </div> </div> <div class="menu-section" id="desserts"> <h2 class="section-title">Desserts</h2> <div class="menu-items"> <div class="menu-item"> <div class="item-header"> <h3 class="item-name">Tiramisu Classico</h3> <span class="item-price">$12</span> </div> <p class="item-desc">Traditional tiramisu with mascarpone cream, espresso-soaked ladyfingers, and cocoa dusting.</p> <div class="item-icons"> <span class="icon">Vegetarian</span> <span class="icon">House Favorite</span> </div> <div class="item-details"> <div class="item-details-inner"> <h4 class="details-title">Ingredients</h4> <ul class="ingredients-list"> <li>Italian mascarpone</li> <li>Free-range eggs</li> <li>Savoiardi ladyfingers</li> <li>Espresso</li> <li>Marsala wine</li> <li>Raw cane sugar</li> <li>Valrhona cocoa powder</li> <li>Dark chocolate shavings</li> </ul> <div class="customization">
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Sonic Stream - Music Playlist</title> <style> :root { --bg-color: #121212; --text-color: #e0e0e0; --accent-color: #1db954; --secondary-color: #535353; --hover-color: #282828; --card-color: #181818; --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } * { margin: 0; padding: 0; box-sizing: border-box; } body { background-color: var(--bg-color); color: var(--text-color); font-family: var(--font-family); display: flex; flex-direction: column; height: 100vh; width: 100%; max-width: 700px; margin: 0 auto; overflow: hidden; } .container { display: flex; flex-direction: column; height: 100%; max-height: 700px; overflow: hidden; position: relative; padding: 0 0 15px 0; } .header { display: flex; justify-content: space-between; align-items: center; padding: 20px; position: relative; z-index: 2; background: linear-gradient(180deg, rgba(18,18,18,1) 0%, rgba(18,18,18,0.9) 90%, rgba(18,18,18,0) 100%); } .header h1 { font-size: 24px; font-weight: 700; margin: 0; background: linear-gradient(90deg, var(--accent-color), #8a2be2); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; text-fill-color: transparent; } .theme-toggle { background: var(--secondary-color); border: none; color: var(--text-color); width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s ease; } .theme-toggle:hover { transform: scale(1.05); background: #444; } .search-container { margin: 0 20px 15px; position: relative; } .search-input { width: 100%; padding: 12px 45px 12px 15px; border-radius: 8px; border: none; background-color: var(--secondary-color); color: var(--text-color); font-size: 14px; outline: none; transition: all 0.3s ease; } .search-input::placeholder { color: #aaa; } .search-input:focus { background-color: #3a3a3a; box-shadow: 0 0 0 2px rgba(29, 185, 84, 0.3); } .search-icon { position: absolute; right: 15px; top: 50%; transform: translateY(-50%); color: #aaa; pointer-events: none; } .playlist-header { display: grid; grid-template-columns: 40px 1fr 120px 80px; padding: 0 20px 8px; border-bottom: 1px solid #333; margin: 0 20px 10px; color: #aaa; font-size: 12px; text-transform: uppercase; letter-spacing: 1px; } .playlist-container { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 0 20px; -ms-overflow-style: none; scrollbar-width: none; } .playlist-container::-webkit-scrollbar { width: 8px; } .playlist-container::-webkit-scrollbar-track { background: transparent; } .playlist-container::-webkit-scrollbar-thumb { background-color: #333; border-radius: 10px; } .track { display: grid; grid-template-columns: 40px 1fr 120px 80px; align-items: center; padding: 12px 15px; margin-bottom: 6px; border-radius: 6px; background-color: var(--card-color); cursor: grab; transition: transform 0.2s ease, background-color 0.3s ease; position: relative; overflow: hidden; } .track::before { content: ""; position: absolute; top: 0; left: 0; height: 100%; width: 3px; background-color: transparent; transition: background-color 0.3s ease; } .track.active { background-color: #2a2a2a; } .track.active::before { background-color: var(--accent-color); } .track:hover { transform: translateY(-2px); background-color: var(--hover-color); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); } .track.dragging { opacity: 0.8; background-color: #333; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.4); z-index: 10; cursor: grabbing; } .track-number { font-size: 14px; font-weight: 500; color: #aaa; text-align: center; } .active .track-number { color: var(--accent-color); } .track-info { padding-right: 10px; } .track-name { font-size: 15px; font-weight: 500; margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .track-artist { font-size: 13px; color: #aaa; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .track-album { font-size: 13px; color: #aaa; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .track-duration { font-size: 14px; color: #aaa; text-align: right; } .active .track-duration { color: var(--accent-color); } .now-playing { background: rgba(18, 18, 18, 0.9); backdrop-filter: blur(10px); padding: 15px 20px; display: flex; align-items: center; border-top: 1px solid #333; position: relative; z-index: 2; } .album-art { width: 50px; height: 50px; border-radius: 4px; margin-right: 15px; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3); } .now-playing-info { flex: 1; overflow: hidden; } .now-playing-name { font-size: 14px; font-weight: 600; margin-bottom: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .now-playing-artist { font-size: 12px; color: #aaa; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .controls { display: flex; align-items: center; } .control-btn { background: transparent; border: none; color: var(--text-color); font-size: 20px; margin-left: 15px; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; } .control-btn:hover { color: var(--accent-color); transform: scale(1.1); } .play-btn { width: 36px; height: 36px; border-radius: 50%; background-color: var(--accent-color); color: black; display: flex; align-items: center; justify-content: center; } .play-btn:hover { transform: scale(1.05); background-color: #1ed760; color: black; } .progress-container { height: 4px; background-color: var(--secondary-color); border-radius: 2px; margin: 0 20px 15px; position: relative; cursor: pointer; } .progress-bar { height: 100%; background-color: var(--accent-color); width: 35%; border-radius: 2px; position: relative; transition: width 0.2s ease; } .progress-handle { position: absolute; right: -6px; top: 50%; transform: translateY(-50%); width: 12px; height: 12px; border-radius: 50%; background-color: var(--accent-color); box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); opacity: 0; transition: opacity 0.2s ease; } .progress-container:hover .progress-handle { opacity: 1; } .progress-time { display: flex; justify-content: space-between; font-size: 11px; color: #aaa; margin: -10px 20px 10px; } .visualizer { display: flex; align-items: flex-end; height: 30px; justify-content: center; gap: 3px; margin-left: 15px; } .visualizer-bar { width: 3px; background-color: var(--accent-color); border-radius: 1px; animation: visualize 0.8s infinite ease; } .visualizer-bar:nth-child(1) { animation-delay: 0.0s; height: 15px; } .visualizer-bar:nth-child(2) { animation-delay: 0.2s; height: 22px; } .visualizer-bar:nth-child(3) { animation-delay: 0.4s; height: 13px; } .visualizer-bar:nth-child(4) { animation-delay: 0.1s; height: 20px; } @keyframes visualize { 0% { transform: scaleY(0.6); } 50% { transform: scaleY(1); } 100% { transform: scaleY(0.6); } } .empty-placeholder { width: 100%; height: 100%; display: none; flex-direction: column; align-items: center; justify-content: center; padding: 20px; text-align: center; } .empty-icon { font-size: 60px; margin-bottom: 20px; color: var(--secondary-color); } .empty-title { font-size: 20px; font-weight: 600; margin-bottom: 10px; } .empty-text { color: #aaa; max-width: 300px; margin-bottom: 20px; } .add-button { background-color: var(--accent-color); color: black; border: none; padding: 10px 20px; border-radius: 30px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; } .add-button:hover { background-color: #1ed760; transform: scale(1.05); } /* Light Theme */ .light-theme { --bg-color: #f5f5f5; --text-color: #121212; --accent-color: #1db954; --secondary-color: #e0e0e0; --hover-color: #ebebeb; --card-color: #ffffff; } .light-theme .search-input { background-color: #e0e0e0; color: #121212; } .light-theme .search-input::placeholder { color: #777; } .light-theme .search-input:focus { background-color: #d0d0d0; } .light-theme .track-artist, .light-theme .track-album, .light-theme .track-duration, .light-theme .track-number, .light-theme .now-playing-artist { color: #666; } .light-theme .header { background: linear-gradient(180deg, rgba(245,245,245,1) 0%, rgba(245,245,245,0.9) 90%, rgba(245,245,245,0) 100%); } .light-theme .now-playing { background: rgba(245, 245, 245, 0.9); border-top: 1px solid #e0e0e0; } .light-theme .playlist-header { border-bottom: 1px solid #e0e0e0; color: #666; } /* Animation for track insertion */ @keyframes insertTrack { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } /* Pulse animation for active track */ @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(29, 185, 84, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(29, 185, 84, 0); } 100% { box-shadow: 0 0 0 0 rgba(29, 185, 84, 0); } } .track.active { animation: pulse 2s infinite; } /* Responsive styles */ @media (max-width: 600px) { .playlist-header, .track { grid-template-columns: 30px 1fr 70px; } .playlist-header div:nth-child(3), .track div:nth-child(3) { display: none; } .header h1 { font-size: 20px; } .search-input { padding: 10px 40px 10px 12px; } .controls { margin-left: auto; } .album-art { width: 40px; height: 40px; } } @media (max-width: 400px) { .playlist-header, .track { grid-template-columns: 20px 1fr 60px; padding: 10px; } .header, .search-container, .playlist-header, .playlist-container, .now-playing { padding-left: 10px; padding-right: 10px; } .track-name { font-size: 14px; } .track-artist { font-size: 12px; } .track-duration, .track-number { font-size: 12px; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>Sonic Stream</h1> <button class="theme-toggle" id="themeToggle"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path> </svg> </button> </div> <div class="search-container"> <input type="text" class="search-input" id="searchInput" placeholder="Search in playlist..."> <div class="search-icon"> <svg xmlns="http://www.w3.org/2000/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="11" cy="11" r="8"></circle> <line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </div> </div> <div class="playlist-header"> <div>#</div> <div>Track</div> <div>Album</div> <div>Duration</div> </div> <div class="playlist-container" id="playlistContainer"> <!-- Tracks will be added here dynamically --> </div> <div class="empty-placeholder" id="emptyPlaylist"> <div class="empty-icon">🎵</div> <div class="empty-title">Your playlist is empty</div> <div class="empty-text">Start adding some tracks to create your perfect vibe</div> <button class="add-button">Add Tracks</button> </div> <div class="progress-container" id="progressContainer"> <div class="progress-bar" id="progressBar"> <div class="progress-handle"></div> </div> </div> <div class="progress-time"> <span>1:45</span> <span>4:12</span> </div> <div class="now-playing"> <img src="https://source.unsplash.com/random/100x100/?album-cover" alt="Album Art" class="album-art"> <div class="now-playing-info"> <div class="now-playing-name">Midnight Sky</div> <div class="now-playing-artist">Miley Cyrus</div> </div> <div class="visualizer"> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> <div class="visualizer-bar"></div> </div> <div class="controls"> <button class="control-btn"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polygon points="19 20 9 12 19 4 19 20"></polygon> <line x1="5" y1="19" x2="5" y2="5"></line> </svg> </button> <button class="control-btn play-btn" id="playButton"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="playIcon"> <polygon points="5 3 19 12 5 21 5 3"></polygon> </svg> </button> <button class="control-btn"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polygon points="5 4 15 12 5 20 5 4"></polygon> <line x1="19" y1="5" x2="19" y2="19"></line> </svg> </button> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Sample playlist data const playlist = [ { id: 1, name: "Midnight Sky", artist: "Miley Cyrus", album: "Plastic Hearts", duration: "3:43", isActive: true }, { id: 2, name: "Blinding Lights", artist: "The Weeknd", album: "After Hours", duration: "3:20" }, { id: 3, name: "Levitating", artist: "Dua Lipa ft. DaBaby", album: "Future Nostalgia", duration: "3:23" }, { id: 4, name: "drivers license", artist: "Olivia Rodrigo", album: "SOUR", duration: "4:02" }, { id: 5, name: "Peaches", artist: "Justin Bieber ft. Daniel Caesar, Giveon", album: "Justice", duration: "3:18" }, { id: 6, name: "Save Your Tears", artist: "The Weeknd & Ariana Grande", album: "After Hours (Remix)", duration: "3:11" }, { id: 7, name: "Montero (Call Me By Your Name)", artist: "Lil Nas X", album: "Montero", duration: "2:17" }, { id: 8, name: "Kiss Me More", artist: "Doja Cat ft. SZA", album: "Planet Her", duration: "3:29" } ]; // DOM elements const playlistContainer = document.getElementById('playlistContainer'); const themeToggle = document.getElementById('themeToggle'); const body = document.body; const searchInput = document.getElementById('searchInput'); const playButton = document.getElementById('playButton'); const playIcon = document.getElementById('playIcon'); const progressBar = document.getElementById('progressBar'); const progressContainer = document.getElementById('progressContainer'); const emptyPlaylist = document.getElementById('emptyPlaylist'); // Initialize the playlist function initPlaylist() { if (playlist.length === 0) { emptyPlaylist.style.display = 'flex'; playlistContainer.style.display = 'none'; } else { emptyPlaylist.style.display = 'none'; playlistContainer.style.display = 'block'; renderPlaylist(playlist); } } // Render the playlist function renderPlaylist(tracks) { playlistContainer.innerHTML = ''; tracks.forEach((track, index) => { const trackElement = document.createElement('div'); trackElement.className = 'track'; trackElement.draggable = true; trackElement.dataset.id = track.id; if (track.isActive) { trackElement.classList.add('active'); } trackElement.innerHTML = ` <div class="track-number">${index + 1}</div> <div class="track-info"> <div class="track-name">${track.name}</div> <div class="track-artist">${track.artist}</div> </div> <div class="track-album">${track.album}</div> <div class="track-duration">${track.duration}</div> `; trackElement.style.animation = `insertTrack 0.3s ease ${index * 0.05}s both`; // Click event for tracks trackElement.addEventListener('click', () => { setActiveTrack(track.id); }); // Drag and drop functionality trackElement.addEventListener('dragstart', handleDragStart); trackElement.addEventListener('dragover', handleDragOver); trackElement.addEventListener('dragleave', handleDragLeave); trackElement.addEventListener('drop', handleDrop); trackElement.addEventListener('dragend', handleDragEnd); playlistContainer.appendChild(trackElement); }); } // Set active track function setActiveTrack(id) { playlist.forEach(track => { track.isActive = track.id === id; }); renderPlaylist(playlist); // Update now playing info const activeTrack = playlist.find(track => track.id === id); if (activeTrack) { document.querySelector('.now-playing-name').textContent = activeTrack.name; document.querySelector('.now-playing-artist').textContent = activeTrack.artist; } } // Search functionality searchInput.addEventListener('input', () => { const searchTerm = searchInput.value.toLowerCase(); const filteredPlaylist = playlist.filter(track => track.name.toLowerCase().includes(searchTerm) || track.artist.toLowerCase().includes(searchTerm) || track.album.toLowerCase().includes(searchTerm) ); renderPlaylist(filteredPlaylist); }); // Theme toggle themeToggle.addEventListener('click', () => { body.classList.toggle('light-theme'); // Update button icon if (body.classList.contains('light-theme')) { themeToggle.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> `; } else { themeToggle.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path> </svg> `; } }); // Play/Pause button let isPlaying = true; playButton.addEventListener('click', () => { isPlaying = !isPlaying; if (isPlaying) { playIcon.innerHTML = `<polygon points="5 3 19 12 5 21 5 3"></polygon>`; document.querySelectorAll('.visualizer-bar').forEach(bar => { bar.style.animationPlayState = 'running'; }); } else { playIcon.innerHTML = ` <rect x="6" y="4" width="4" height="16"></rect> <rect x="14" y="4" width="4" height="16"></rect> `; document.querySelectorAll('.visualizer-bar').forEach(bar => { bar.style.animationPlayState = 'paused'; }); } }); // Progress bar interaction progressContainer.addEventListener('click', (e) => { const width = progressContainer.clientWidth; const clickX = e.offsetX; const percentage = (clickX / width) * 100; progressBar.style.width = `${percentage}%`; }); // Drag and drop functionality let draggedItem = null; function handleDragStart(e) { this.classList.add('dragging'); draggedItem = this; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/html', this.innerHTML); } function handleDragOver(e) { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; this.classList.add('drag-over'); return false; } function handleDragLeave() { this.classList.remove('drag-over'); } function handleDrop(e) { e.stopPropagation(); if (draggedItem !== this) { // Get the track IDs const fromId = parseInt(draggedItem.dataset.id); const toId = parseInt(this.dataset.id); // Find the positions in the playlist array const fromIndex = playlist.findIndex(track => track.id === fromId); const toIndex = playlist.findIndex(track => track.id === toId); // Reorder the playlist const [movedItem] = playlist.splice(fromIndex, 1); playlist.splice(toIndex, 0, movedItem); // Re-render the playlist renderPlaylist(playlist); } this.classList.remove('drag-over'); return false; } function handleDragEnd() { this.classList.remove('dragging'); document.querySelectorAll('.track').forEach(track => { track.classList.remove('drag-over'); }); } // Initialize the playlist initPlaylist(); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Project Management Dashboard</title> <style> :root { --primary: #3445de; --secondary: #ff7052; --success: #2ace7e; --warning: #ffbe0b; --danger: #ff5252; --light: #f8f9fa; --dark: #212529; --gray: #6c757d; --gray-light: #e9ecef; --border-radius: 8px; --shadow: 0 4px 12px rgba(0, 0, 0, 0.08); --transition: all 0.3s ease; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background-color: #f5f7ff; color: var(--dark); font-size: 14px; line-height: 1.5; height: 100vh; overflow: hidden; } .container { max-width: 700px; height: 700px; margin: 0 auto; padding: 20px; display: flex; flex-direction: column; } header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; position: relative; } h1 { font-size: 24px; font-weight: 700; color: var(--dark); margin-bottom: 5px; } .subtitle { color: var(--gray); font-size: 14px; margin-bottom: 15px; } .filters { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 10px; } .search-bar { position: relative; flex: 1; min-width: 180px; } .search-bar input { width: 100%; padding: 10px 10px 10px 35px; border: 1px solid var(--gray-light); border-radius: var(--border-radius); background-color: #fff; font-size: 14px; transition: var(--transition); } .search-bar input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(52, 69, 222, 0.1); } .search-bar i { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--gray); } .filter-buttons { display: flex; gap: 10px; } .btn { padding: 8px 16px; border-radius: var(--border-radius); border: none; font-weight: 500; cursor: pointer; transition: var(--transition); display: flex; align-items: center; gap: 5px; } .btn-light { background-color: #fff; color: var(--dark); border: 1px solid var(--gray-light); } .btn-light:hover { background-color: var(--gray-light); } .btn-primary { background-color: var(--primary); color: #fff; } .btn-primary:hover { background-color: #2937c5; } .btn-icon { width: 38px; height: 38px; padding: 0; display: flex; align-items: center; justify-content: center; } .projects-container { flex: 1; overflow-y: auto; padding-right: 5px; } .projects-container::-webkit-scrollbar { width: 6px; } .projects-container::-webkit-scrollbar-track { background: var(--gray-light); border-radius: 10px; } .projects-container::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 10px; } .projects-container::-webkit-scrollbar-thumb:hover { background: var(--gray); } .project-card { background-color: #fff; border-radius: var(--border-radius); padding: 16px; margin-bottom: 12px; box-shadow: var(--shadow); transition: var(--transition); position: relative; border-left: 4px solid transparent; display: flex; flex-direction: column; gap: 12px; } .project-card:hover { transform: translateY(-2px); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); } .project-card.priority-high { border-left-color: var(--danger); } .project-card.priority-medium { border-left-color: var(--warning); } .project-card.priority-low { border-left-color: var(--success); } .project-header { display: flex; justify-content: space-between; align-items: flex-start; } .project-title { font-weight: 600; font-size: 16px; color: var(--dark); margin-bottom: 5px; cursor: pointer; } .project-title:hover { color: var(--primary); } .project-actions { display: flex; gap: 5px; } .action-btn { width: 28px; height: 28px; border-radius: 6px; background-color: transparent; border: none; color: var(--gray); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: var(--transition); } .action-btn:hover { background-color: var(--gray-light); color: var(--dark); } .project-description { color: var(--gray); font-size: 14px; margin-bottom: 5px; } .project-progress { display: flex; flex-direction: column; gap: 5px; } .progress-info { display: flex; justify-content: space-between; font-size: 12px; } .progress-bar { height: 6px; background-color: var(--gray-light); border-radius: 10px; overflow: hidden; } .progress-value { height: 100%; border-radius: 10px; background: linear-gradient(90deg, var(--primary), #5a6afb); transition: width 0.6s ease-out; } .project-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 5px; } .project-meta { display: flex; align-items: center; gap: 15px; } .meta-item { display: flex; align-items: center; gap: 5px; color: var(--gray); font-size: 12px; } .meta-item i { font-size: 14px; } .team-members { display: flex; align-items: center; } .member-avatar { width: 28px; height: 28px; border-radius: 50%; background-size: cover; background-position: center; border: 2px solid white; margin-left: -8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); transition: transform 0.2s ease; } .member-avatar:first-child { margin-left: 0; } .member-avatar:hover { transform: translateY(-3px); z-index: 2; } .priority-badge { font-size: 11px; padding: 3px 8px; border-radius: 12px; font-weight: 500; } .priority-high { background-color: #ffe5e5; color: var(--danger); } .priority-medium { background-color: #fff5e5; color: var(--warning); } .priority-low { background-color: #e5f9ef; color: var(--success); } .status-badge { font-size: 11px; padding: 3px 8px; border-radius: 12px; font-weight: 500; } .status-completed { background-color: #e5f9ef; color: var(--success); } .status-in-progress { background-color: #e5eeff; color: var(--primary); } .status-pending { background-color: #f8f9fa; color: var(--gray); } .status-at-risk { background-color: #ffe5e5; color: var(--danger); } .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 300px; text-align: center; color: var(--gray); } .empty-state i { font-size: 48px; margin-bottom: 15px; color: var(--gray-light); } .add-project-form { background-color: #fff; border-radius: var(--border-radius); padding: 20px; margin-top: 15px; box-shadow: var(--shadow); display: none; } .form-group { margin-bottom: 15px; } .form-label { display: block; margin-bottom: 5px; font-weight: 500; } .form-control { width: 100%; padding: 10px; border: 1px solid var(--gray-light); border-radius: var(--border-radius); font-size: 14px; transition: var(--transition); } .form-control:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(52, 69, 222, 0.1); } .form-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; } .task-dropdown { position: absolute; top: 45px; right: 0; background-color: #fff; border-radius: var(--border-radius); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); width: 200px; z-index: 100; overflow: hidden; display: none; } .dropdown-item { padding: 10px 15px; cursor: pointer; transition: var(--transition); display: flex; align-items: center; gap: 8px; } .dropdown-item:hover { background-color: var(--gray-light); } .dropdown-item i { font-size: 14px; width: 16px; } .dropdown-divider { height: 1px; background-color: var(--gray-light); margin: 5px 0; } .toast { position: fixed; bottom: 20px; right: 20px; background-color: #fff; border-radius: var(--border-radius); padding: 16px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); display: flex; align-items: center; gap: 12px; transform: translateY(100px); opacity: 0; transition: all 0.3s ease; z-index: 1000; max-width: 350px; } .toast.show { transform: translateY(0); opacity: 1; } .toast-icon { width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; color: #fff; } .toast-success .toast-icon { background-color: var(--success); } .toast-error .toast-icon { background-color: var(--danger); } .toast-content { flex: 1; } .toast-title { font-weight: 600; margin-bottom: 3px; font-size: 14px; } .toast-message { color: var(--gray); font-size: 12px; } .toast-close { background: none; border: none; color: var(--gray); cursor: pointer; font-size: 16px; } @media (max-width: 600px) { .filters { flex-direction: column; align-items: stretch; } .search-bar { width: 100%; } .filter-buttons { width: 100%; justify-content: space-between; } .project-footer { flex-direction: column; align-items: flex-start; gap: 10px; } .team-members { margin-top: 10px; } } /* Animation */ @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(52, 69, 222, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(52, 69, 222, 0); } 100% { box-shadow: 0 0 0 0 rgba(52, 69, 222, 0); } } .btn-primary { animation: pulse 2s infinite; } /* Loading animation */ .loading-bar { height: 3px; width: 100%; background: linear-gradient(90deg, var(--primary) 0%, var(--secondary) 100%); position: absolute; top: 0; left: 0; transform: scaleX(0); transform-origin: left; transition: transform 0.3s ease; display: none; } .loading .loading-bar { display: block; animation: loadingAnimation 1.5s infinite ease-in-out; } @keyframes loadingAnimation { 0% { transform: scaleX(0); transform-origin: left; } 50% { transform: scaleX(1); transform-origin: left; } 50.1% { transform-origin: right; } 100% { transform: scaleX(0); transform-origin: right; } } /* Cool hover effect for task items */ .project-card::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: var(--border-radius); background: linear-gradient(45deg, transparent, rgba(52, 69, 222, 0.03), transparent); background-size: 200% 200%; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; z-index: 0; } .project-card:hover::before { opacity: 1; animation: shimmer 1.5s infinite; } @keyframes shimmer { 0% { background-position: 0% 0%; } 100% { background-position: 200% 200%; } } /* Checkbox styling */ .task-checkbox { appearance: none; -webkit-appearance: none; width: 18px; height: 18px; border: 2px solid var(--gray-light); border-radius: 4px; margin-right: 10px; position: relative; cursor: pointer; transition: var(--transition); } .task-checkbox:checked { background-color: var(--primary); border-color: var(--primary); } .task-checkbox:checked::after { content: '✓'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-size: 12px; } .task-checkbox:focus { outline: none; box-shadow: 0 0 0 3px rgba(52, 69, 222, 0.2); } /* For the completed tasks */ .completed .project-title { text-decoration: line-through; color: var(--gray); } /* Dropdown toggle animation */ .dropdown-toggle { position: relative; } .dropdown-toggle::after { content: ''; display: inline-block; margin-left: 5px; vertical-align: middle; border-top: 4px solid; border-right: 4px solid transparent; border-left: 4px solid transparent; transition: transform 0.3s ease; } .dropdown-toggle.active::after { transform: rotate(180deg); } /* Mini badge for tasks count */ .task-count { font-size: 10px; background-color: var(--gray-light); color: var(--gray); border-radius: 10px; padding: 2px 6px; margin-left: 5px; } .priority-selector { display: flex; gap: 8px; margin-top: 5px; } .priority-option { width: 20px; height: 20px; border-radius: 50%; cursor: pointer; transition: var(--transition); border: 2px solid transparent; } .priority-option.high { background-color: var(--danger); } .priority-option.medium { background-color: var(--warning); } .priority-option.low { background-color: var(--success); } .priority-option.selected { transform: scale(1.2); border-color: white; box-shadow: 0 0 0 2px currentColor; } /* Notification badge */ .notification-badge { position: absolute; top: -5px; right: -5px; background-color: var(--danger); color: white; border-radius: 50%; width: 18px; height: 18px; font-size: 10px; display: flex; align-items: center; justify-content: center; font-weight: bold; } .fade-in { animation: fadeIn 0.3s ease-in-out; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } /* Task Edit Mode */ .edit-mode .project-title-text { display: none; } .edit-mode .project-title-input { display: block; } .project-title-input { display: none; width: 100%; border: none; border-bottom: 2px solid var(--primary); font-size: 16px; font-weight: 600; padding: 0 0 5px 0; margin-bottom: 5px; background-color: transparent; } .project-title-input:focus { outline: none; } </style> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"> </head> <body> <div class="container"> <div class="loading-bar"></div> <header> <div> <h1>Project Dashboard</h1> <p class="subtitle">Launch Week Q2 - 8 active tasks</p> </div> <div class="dropdown-toggle" id="taskDropdownToggle"> <button class="btn btn-primary" id="addTaskBtn"> <i class="fas fa-plus"></i> New Task </button> <div class="task-dropdown" id="taskDropdown"> <div class="dropdown-item" id="addProjectBtn"> <i class="fas fa-briefcase"></i> New Project </div> <div class="dropdown-item"> <i class="fas fa-tasks"></i> New Task </div> <div class="dropdown-divider"></div> <div class="dropdown-item"> <i class="fas fa-file-import"></i> Import Tasks </div> <div class="dropdown-item"> <i class="fas fa-file-export"></i> Export Tasks </div> </div> </div> </header> <div class="filters"> <div class="search-bar"> <i class="fas fa-search"></i> <input type="text" placeholder="Search tasks..." id="searchInput"> </div> <div class="filter-buttons"> <button class="btn btn-light dropdown-toggle" id="sortDropdownToggle"> <i class="fas fa-sort"></i> Sort </button> <button class="btn btn-light dropdown-toggle" id="filterDropdownToggle"> <i class="fas fa-filter"></i> Filter </button> <button class="btn btn-light btn-icon view-toggle" title="Change view"> <i class="fas fa-th-list"></i> </button> </div> </div> <div class="projects-container" id="projectsContainer"> <!-- Project cards will be dynamically inserted here --> </div> <div class="add-project-form" id="addProjectForm"> <div class="form-group"> <label class="form-label" for="projectTitle">Project Title</label> <input type="text" class="form-control" id="projectTitle" placeholder="Enter project title"> </div> <div class="form-group"> <label class="form-label" for="projectDescription">Description</label> <textarea class="form-control" id="projectDescription" rows="3" placeholder="Enter project description"></textarea> </div> <div class="form-group"> <label class="form-label">Priority</label> <div class="priority-selector"> <div class="priority-option high" data-priority="high"></div> <div class="priority-option medium selected" data-priority="medium"></div> <div class="priority-option low" data-priority="low"></div> </div> </div> <div class="form-group"> <label class="form-label" for="dueDate">Due Date</label> <input type="date" class="form-control" id="dueDate"> </div> <div class="form-actions"> <button class="btn btn-light" id="cancelProjectBtn">Cancel</button> <button class="btn btn-primary" id="saveProjectBtn">Save Project</button> </div> </div> </div> <div class="toast" id="toast"> <div class="toast-icon"> <i class="fas fa-check"></i> </div> <div class="toast-content"> <div class="toast-title">Success!</div> <div class="toast-message">Your project has been created successfully.</div> </div> <button class="toast-close" id="toastClose"> <i class="fas fa-times"></i> </button> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Sample project data const projectsData = [ { id: 1, title: "Website Redesign", description: "Complete overhaul of the marketing site with new brand guidelines", progress: 75, priority: "high", status: "in-progress", dueDate: "2023-06-15", tasks: 12, completed: 9, members: [ { id: 1, name: "Alex Kim", avatar: "https://randomuser.me/api/portraits/men/32.jpg" }, { id: 2, name: "Sarah Chen", avatar: "https://randomuser.me/api/portraits/women/44.jpg" }, { id: 3, name: "Miguel Rodriguez", avatar: "https://randomuser.me/api/portraits/men/46.jpg" } ] }, { id: 2, title: "Mobile App Development", description: "Finalize UI/UX designs and begin implementation for iOS platform", progress: 40, priority: "medium", status: "in-progress", dueDate: "2023-07-20", tasks: 18, completed: 7, members: [ { id: 4, name: "Priya Sharma", avatar: "https://randomuser.me/api/portraits/women/65.jpg" }, { id: 5, name: "David Wilson", avatar: "https://randomuser.me/api/portraits/men/22.jpg" } ] }, { id: 3, title: "Q2 Analytics Report", description: "Compile user engagement metrics and prepare presentation for stakeholders", progress: 90, priority: "medium", status: "at-risk", dueDate: "2023-06-10", tasks: 8, completed: 7, members: [ { id: 6, name: "Emma Johnson", avatar: "https://randomuser.me/api/portraits/women/33.jpg" }, { id: 7, name: "Jamal Brooks", avatar: "https://randomuser.me/api/portraits/men/64.jpg" } ] }, { id: 4, title: "Product Launch Preparation", description: "Coordinate with Marketing to finalize launch materials and campaign schedule", progress: 60, priority: "high", status: "in-progress", dueDate: "2023-06-28", tasks: 15, completed: 9, members: [ { id: 8, name: "Olivia Martinez", avatar: "https://randomuser.me/api/portraits/women/24.jpg" }, { id: 9, name: "Liam Wang", avatar: "https://randomuser.me/api/portraits/men/34.jpg" }, { id: 10, name: "Sophia Patel", avatar: "https://randomuser.me/api/portraits/women/57.jpg" } ] }, { id: 5, title: "User Testing Sessions", description: "Conduct usability tests for new feature set with selected beta users", progress: 100, priority: "low", status: "completed", dueDate: "2023-06-05", tasks: 6, completed: 6, members: [ { id: 11, name: "Noah Garcia", avatar: "https://randomuser.me/api/portraits/men/52.jpg" }, { id: 12, name: "Isabella Lee", avatar: "https://randomuser.me/api/portraits/women/78.jpg" } ] }, { id: 6, title: "Infrastructure Upgrade", description: "Migrate servers to new cloud architecture with zero downtime", progress: 35, priority: "high", status: "pending", dueDate: "2023-07-15", tasks: 20, completed: 7, members: [ { id: 13, name: "Ethan Brown", avatar: "https://randomuser.me/api/portraits/men/75.jpg" }, { id: 14, name: "Mia Davis", avatar: "https://randomuser.me/api/portraits/women/89.jpg" }, { id: 15, name: "James Wilson", avatar: "https://randomuser.me/api/portraits/men/42.jpg" } ] } ]; const projectsContainer = document.getElementById('projectsContainer'); const addTaskBtn = document.getElementById('addTaskBtn'); const taskDropdown = document.getElementById('taskDropdown'); const taskDropdownToggle = document.getElementById('taskDropdownToggle'); const addProjectBtn = document.getElementById('addProjectBtn'); const addProjectForm = document.getElementById('addProjectForm'); const cancelProjectBtn = document.getElementById('cancelProjectBtn'); const saveProjectBtn = document.getElementById('saveProjectBtn'); const toast = document.getElementById('toast'); const toastClose = document.getElementById('toastClose'); const searchInput = document.getElementById('searchInput'); const sortDropdownToggle = document.getElementById('sortDropdownToggle'); const filterDropdownToggle = document.getElementById('filterDropdownToggle'); // Render projects function renderProjects(projects = projectsData) { projectsContainer.innerHTML = ''; if (projects.length === 0) { projectsContainer.innerHTML = ` <div class="empty-state"> <i class="fas fa-clipboard-list"></i> <h3>No tasks found</h3> <p>Try changing your search or filter criteria.</p> </div> `; return; } projects.forEach(project => { const projectCard = document.createElement('div'); projectCard.className = `project-card priority-${project.priority} fade-in`; projectCard.dataset.id = project.id; // Format due date const dueDate = new Date(project.dueDate); const formattedDate = dueDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); // Calculate days remaining const today = new Date(); const diffTime = dueDate - today; const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); const daysText = diffDays > 0 ? `${diffDays} days left` : diffDays === 0 ? "Due today" : "Overdue"; projectCard.innerHTML = ` <div class="project-header"> <div> <div class="project-title"> <span class="project-title-text">${project.title}</span> <input type="text" class="project-title-input" value="${project.title}"> </div> <div class="project-description">${project.description}</div> </div> <div class="project-actions"> <button class="action-btn edit-btn" title="Edit task"> <i class="fas fa-edit"></i> </button> <button class="action-btn delete-btn" title="Delete task"> <i class="fas fa-trash-alt"></i> </button> </div> </div> <div class="project-progress"> <div class="progress-info"> <span>Progress</span> <span>${project.progress}%</span> </div> <div class="progress-bar"> <div class="progress-value" style="width: ${project.progress}%"></div> </div> </div> <div class="project-footer"> <div class="project-meta"> <span class="meta-item"> <i class="fas fa-calendar"></i> ${formattedDate} </span> <span class="meta-item ${diffDays < 0 ? 'priority-high' : ''}"> <i class="fas fa-clock"></i> ${daysText} </span> <span class="meta-item"> <i class="fas fa-tasks"></i> ${project.completed}/${project.tasks} </span> <span class="status-badge status-${project.status}">${capitalizeFirstLetter(project.status.replace('-', ' '))}</span> </div> <div class="team-members"> ${project.members.map((member, index) => `<div class="member-avatar" style="background-image: url('${member.avatar}');" title="${member.name}" data-id="${member.id}"></div>` ).join('')} </div> </div> `; projectsContainer.appendChild(projectCard); // Add animation with delay for staggered effect setTimeout(() => { projectCard.style.opacity = '1'; projectCard.style.transform = 'translateY(0)'; }, 50 * projectsContainer.children.length); }); // Add event listeners to the newly created elements addProjectCardEventListeners(); } function addProjectCardEventListeners() { const editButtons = document.querySelectorAll('.edit-btn'); const deleteButtons = document.querySelectorAll('.delete-btn'); const projectTitles = document.querySelectorAll('.project-title'); editButtons.forEach(btn => { btn.addEventListener('click', handleEditClick); }); deleteButtons.forEach(btn => { btn.addEventListener('click', handleDeleteClick); }); projectTitles.forEach(title => { title.addEventListener('click', function(e) { if (e.target.classList.contains('project-title-text')) { const projectCard = e.target.closest('.project-card'); toggleProjectDetails(projectCard); } }); }); } function handleEditClick(e) { const projectCard = e.target.closest('.project-card'); projectCard.classList.toggle('edit-mode'); const titleInput = projectCard.querySelector('.project-title-input'); if (projectCard.classList.contains('edit-mode')) { titleInput.focus(); // Listen for Enter key to save changes titleInput.addEventListener('keydown', function(e) { if (e.key === 'Enter') { saveProjectEdit(projectCard); } }); // Listen for click outside to save changes document.addEventListener('click', function saveOnClickOutside(e) { if (!projectCard.contains(e.target)) { saveProjectEdit(projectCard); document.removeEventListener('click', saveOnClickOutside); } }); } } function saveProjectEdit(projectCard) { const titleInput = projectCard.querySelector('.project-title-input'); const titleText = projectCard.querySelector('.project-title-text'); if (titleInput.value.trim() !== '') { titleText.textContent = titleInput.value; // Update the data const projectId = parseInt(projectCard.dataset.id); const projectIndex = projectsData.findIndex(project => project.id === projectId); if (projectIndex !== -1) { projectsData[projectIndex].title = titleInput.value; } } projectCard.classList.remove('edit-mode'); showToast('success', 'Task updated successfully!'); } function handleDeleteClick(e) { const projectCard = e.target.closest('.project-card');
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Smart Home Support FAQ</title> <style> :root { --primary: #5b8ff9; --primary-light: #d4e4ff; --secondary: #ff7875; --text: #333; --text-light: #6e6e6e; --bg: #f9fbff; --radius: 12px; --shadow: 0 4px 16px rgba(91, 143, 249, 0.1); --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: var(--bg); color: var(--text); padding: 2rem 1rem; max-width: 700px; margin: 0 auto; height: 100vh; overflow-y: auto; } .faq-container { display: flex; flex-direction: column; gap: 1.5rem; max-width: 650px; margin: 0 auto; } .header { text-align: center; margin-bottom: 1.5rem; position: relative; } .header h1 { font-size: 2rem; margin-bottom: 0.5rem; background: linear-gradient(135deg, var(--primary), var(--secondary)); -webkit-background-clip: text; background-clip: text; color: transparent; position: relative; } .header p { color: var(--text-light); max-width: 500px; margin: 0 auto; font-size: 1rem; line-height: 1.5; } .search-container { margin: 1.5rem auto; position: relative; max-width: 500px; } .search-container input { width: 100%; padding: 0.75rem 1rem 0.75rem 3rem; border: 2px solid var(--primary-light); border-radius: var(--radius); font-size: 1rem; background-color: white; transition: var(--transition); outline: none; } .search-container input:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(91, 143, 249, 0.25); } .search-icon { position: absolute; left: 1rem; top: 50%; transform: translateY(-50%); color: var(--text-light); } .faq-item { background-color: white; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); transition: var(--transition); border: 2px solid transparent; } .faq-item:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(91, 143, 249, 0.15); } .faq-question { display: flex; align-items: center; justify-content: space-between; padding: 1.25rem 1.5rem; cursor: pointer; font-weight: 600; user-select: none; position: relative; } .faq-question::before { content: ""; position: absolute; left: 0; top: 0; width: 4px; height: 0; background: linear-gradient(to bottom, var(--primary), var(--secondary)); transition: var(--transition); } .faq-item.active .faq-question::before { height: 100%; } .faq-question h3 { font-size: 1.1rem; font-weight: 600; margin-right: 1rem; } .indicator { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; transition: var(--transition); flex-shrink: 0; position: relative; } .indicator::before, .indicator::after { content: ""; position: absolute; background-color: var(--primary); border-radius: 2px; transition: var(--transition); } .indicator::before { width: 16px; height: 2px; } .indicator::after { width: 2px; height: 16px; } .faq-item.active .indicator::after { transform: rotate(90deg); opacity: 0; } .faq-answer { max-height: 0; overflow: hidden; transition: max-height 0.5s cubic-bezier(0, 1, 0, 1); padding: 0 1.5rem; color: var(--text-light); line-height: 1.6; } .faq-item.active .faq-answer { max-height: 1000px; transition: max-height 1s ease-in-out; padding-bottom: 1.5rem; } .faq-item.active { border-color: var(--primary-light); } .faq-item.active .faq-question { color: var(--primary); } .faq-tag { display: inline-block; padding: 0.25rem 0.75rem; border-radius: 999px; font-size: 0.75rem; font-weight: 500; margin-right: 0.5rem; margin-top: 0.25rem; } .tag-setup { background-color: #e6f7ff; color: #1890ff; } .tag-connectivity { background-color: #f6ffed; color: #52c41a; } .tag-account { background-color: #fff7e6; color: #fa8c16; } .tag-troubleshooting { background-color: #fff2f0; color: #ff4d4f; } .tag-privacy { background-color: #f9f0ff; color: #722ed1; } .faq-answer a { color: var(--primary); text-decoration: none; font-weight: 500; position: relative; } .faq-answer a::after { content: ""; position: absolute; bottom: -2px; left: 0; width: 100%; height: 1px; background-color: var(--primary); transform: scaleX(0); transform-origin: left; transition: transform 0.3s ease; } .faq-answer a:hover::after { transform: scaleX(1); } .faq-answer p { margin-bottom: 1rem; } .faq-answer p:last-child { margin-bottom: 0; } .faq-answer ul { margin: 0.75rem 0; padding-left: 1.5rem; } .faq-answer li { margin-bottom: 0.5rem; } .no-results { text-align: center; padding: 2rem; color: var(--text-light); background-color: white; border-radius: var(--radius); display: none; } .no-results img { width: 120px; margin-bottom: 1rem; opacity: 0.7; } @media (max-width: 500px) { .header h1 { font-size: 1.75rem; } .faq-question { padding: 1rem; } .faq-question h3 { font-size: 1rem; } .faq-answer { padding: 0 1rem; } .faq-item.active .faq-answer { padding-bottom: 1rem; } } .waves { position: absolute; top: 0; left: 0; width: 100%; height: 10px; z-index: -1; opacity: 0.6; } .wave { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, var(--primary), var(--secondary)); opacity: 0.5; } .wave:nth-child(1) { animation: wave 8s linear infinite; } .wave:nth-child(2) { animation: wave 10s linear infinite; animation-delay: -2s; opacity: 0.3; } @keyframes wave { 0% { transform: translateX(-50%) scaleY(0.5); } 50% { transform: translateX(0%) scaleY(1); } 100% { transform: translateX(50%) scaleY(0.5); } } .highlight { background-color: #ffef9f; padding: 0 3px; border-radius: 3px; } </style> </head> <body> <div class="header"> <div class="waves"> <div class="wave"></div> <div class="wave"></div> </div> <h1>HomeHub Smart Support</h1> <p>Find answers to the most common questions about your HomeHub smart devices and services.</p> </div> <div class="search-container"> <svg class="search-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M11 19C15.4183 19 19 15.4183 19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M21 21L16.65 16.65" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> <input type="text" id="faq-search" placeholder="Search for your question..."> </div> <div class="faq-container"> <div class="faq-item"> <div class="faq-question"> <h3>How do I set up my HomeHub Smart Speaker?</h3> <div class="indicator"></div> </div> <div class="faq-answer"> <span class="faq-tag tag-setup">Setup</span> <p>Setting up your HomeHub Smart Speaker is simple:</p> <ul> <li>Plug in your speaker and wait for the light ring to turn blue</li> <li>Download the HomeHub app from the App Store or Google Play</li> <li>Open the app and select "Add Device" from the menu</li> <li>Select "Smart Speaker" and follow the in-app instructions</li> <li>Connect your speaker to your Wi-Fi network</li> </ul> <p>The setup typically takes less than 5 minutes. If you encounter issues, try positioning your speaker closer to your Wi-Fi router during setup.</p> </div> </div> <div class="faq-item"> <div class="faq-question"> <h3>My HomeHub devices won't connect to Wi-Fi</h3> <div class="indicator"></div> </div> <div class="faq-answer"> <span class="faq-tag tag-connectivity">Connectivity</span> <span class="faq-tag tag-troubleshooting">Troubleshooting</span> <p>If your HomeHub devices are having trouble connecting to Wi-Fi, try these common solutions:</p> <ul> <li>Ensure your Wi-Fi network is functioning properly by testing it with another device</li> <li>Verify your HomeHub device is within range of your Wi-Fi router (ideally within 30 feet)</li> <li>Check if your router is using a supported network configuration (2.4GHz networks are most reliable)</li> <li>Restart both your router and HomeHub device</li> <li>Try resetting your HomeHub device by pressing and holding the reset button for 10 seconds</li> </ul> <p>If the issue persists, your router may have MAC filtering or firewall settings blocking the connection. Check your router settings or contact our <a href="#">technical support team</a>.</p> </div> </div> <div class="faq-item"> <div class="faq-question"> <h3>How do I link my music streaming services?</h3> <div class="indicator"></div> </div> <div class="faq-answer"> <span class="faq-tag tag-account">Account</span> <p>You can link popular music streaming services like Spotify, Apple Music, Amazon Music, and more:</p> <ol> <li>Open the HomeHub mobile app</li> <li>Go to Settings > Services</li> <li>Select "Music" from the categories</li> <li>Choose your preferred streaming service</li> <li>Log in with your credentials for that service</li> <li>Confirm the account linking</li> </ol> <p>Once linked, you can use voice commands like "Play my Discover Weekly on Spotify" or "Play relaxing jazz on Apple Music." Most premium streaming services require an active subscription.</p> </div> </div> <div class="faq-item"> <div class="faq-question"> <h3>Does HomeHub record all of my conversations?</h3> <div class="indicator"></div> </div> <div class="faq-answer"> <span class="faq-tag tag-privacy">Privacy</span> <p>No, HomeHub devices are designed with your privacy in mind. They only begin recording audio when you use the wake word (like "Hey HomeHub"). The light ring will always illuminate when the device is listening.</p> <p>Key privacy features include:</p> <ul> <li>Dedicated mute button that physically disconnects the microphones</li> <li>Option to delete your voice history via the app or voice command</li> <li>Ability to review and manage all stored recordings</li> <li>End-to-end encryption for sensitive communications</li> </ul> <p>You can manage all privacy settings in the HomeHub app under Settings > Privacy. For more details, visit our <a href="#">Privacy Center</a>.</p> </div> </div> <div class="faq-item"> <div class="faq-question"> <h3>How can I control multiple HomeHub devices together?</h3> <div class="indicator"></div> </div> <div class="faq-answer"> <span class="faq-tag tag-setup">Setup</span> <p>You can group your HomeHub devices for synchronized playback or create custom routines:</p> <p><strong>For Multi-Room Audio:</strong></p> <ol> <li>Open the HomeHub app</li> <li>Go to Devices > Groups</li> <li>Select "Create New Group"</li> <li>Choose the devices you want to include</li> <li>Name your group (e.g., "Downstairs" or "Whole House")</li> </ol> <p><strong>For Smart Home Routines:</strong></p> <ol> <li>Go to the Routines section in the app</li> <li>Tap "Create Routine"</li> <li>Set a trigger (time, voice command, or device action)</li> <li>Add the actions you want to happen (lights, music, announcements)</li> </ol> <p>You can control up to 32 devices in a single group and create up to 50 different routines per account.</p> </div> </div> <div class="faq-item"> <div class="faq-question"> <h3>My HomeHub Smart Display screen is frozen</h3> <div class="indicator"></div> </div> <div class="faq-answer"> <span class="faq-tag tag-troubleshooting">Troubleshooting</span> <p>If your HomeHub Smart Display screen is frozen or unresponsive, follow these steps:</p> <ol> <li>Perform a basic restart by pressing and holding the power button for 10 seconds</li> <li>After the device powers off, wait 30 seconds before turning it back on</li> <li>If that doesn't work, try a factory reset by: <ul> <li>Press and hold both volume buttons simultaneously for 15 seconds</li> <li>When prompted, select "Factory Reset" on the screen</li> </ul> </li> </ol> <p>Note that a factory reset will erase all your settings and preferences. You'll need to set up your device again.</p> <p>If these steps don't resolve the issue, there may be a hardware problem. Contact <a href="#">customer support</a> for assistance.</p> </div> </div> <div class="faq-item"> <div class="faq-question"> <h3>How do I update my HomeHub device firmware?</h3> <div class="indicator"></div> </div> <div class="faq-answer"> <span class="faq-tag tag-setup">Setup</span> <p>HomeHub devices automatically download and install firmware updates when connected to Wi-Fi. However, you can manually check for updates:</p> <ol> <li>Open the HomeHub app</li> <li>Select your device</li> <li>Go to Device Settings > About</li> <li>Tap "Check for Updates"</li> </ol> <p>During updates, your device may restart and temporarily be unavailable. The light ring will display a spinning white pattern during updates.</p> <p>For best performance, we recommend keeping your devices plugged in and connected to Wi-Fi overnight, as most updates are scheduled during off-peak hours (2AM-4AM local time).</p> </div> </div> <div class="no-results"> <svg width="120" height="120" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M19 12H5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 19L5 12L12 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> <h3>No matching questions found</h3> <p>Try searching with different keywords or browse all questions above</p> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const faqItems = document.querySelectorAll('.faq-item'); const searchInput = document.getElementById('faq-search'); const noResults = document.querySelector('.no-results'); // Toggle FAQ items faqItems.forEach(item => { const question = item.querySelector('.faq-question'); question.addEventListener('click', () => { // Close other open items faqItems.forEach(otherItem => { if (otherItem !== item && otherItem.classList.contains('active')) { otherItem.classList.remove('active'); } }); // Toggle the clicked item item.classList.toggle('active'); // Add a little bounce animation when opening if (item.classList.contains('active')) { item.style.animation = 'none'; setTimeout(() => { item.style.animation = 'bounce 0.5s'; }, 10); } }); }); // Search functionality searchInput.addEventListener('input', performSearch); function performSearch() { const searchTerm = searchInput.value.toLowerCase().trim(); let hasResults = false; if (!searchTerm) { // If search is empty, show all items faqItems.forEach(item => { item.style.display = 'block'; // Remove any highlights const questionText = item.querySelector('.faq-question h3'); const answerText = item.querySelector('.faq-answer'); questionText.innerHTML = questionText.innerText; answerText.innerHTML = answerText.innerHTML.replace(/<span class="highlight">(.*?)<\/span>/g, '$1'); }); noResults.style.display = 'none'; return; } faqItems.forEach(item => { const questionText = item.querySelector('.faq-question h3').innerText.toLowerCase(); const answerText = item.querySelector('.faq-answer').innerText.toLowerCase(); if (questionText.includes(searchTerm) || answerText.includes(searchTerm)) { item.style.display = 'block'; hasResults = true; // Highlight matching text highlightMatches(item, searchTerm); } else { item.style.display = 'none'; } }); // Show/hide no results message noResults.style.display = hasResults ? 'none' : 'block'; } function highlightMatches(item, searchTerm) { const questionEl = item.querySelector('.faq-question h3'); const answerEl = item.querySelector('.faq-answer'); // Function to highlight text function addHighlights(text, term) { const regex = new RegExp(`(${term})`, 'gi'); return text.replace(regex, '<span class="highlight">$1</span>'); } // Only highlight if not already highlighted (prevents doubling up) if (!questionEl.innerHTML.includes('<span class="highlight">')) { const highlightedQuestion = addHighlights(questionEl.innerText, searchTerm); questionEl.innerHTML = highlightedQuestion; } // For answer, we need to be careful not to disrupt HTML tags const originalHTML = answerEl.innerHTML; // Remove any existing highlights first const cleanHTML = originalHTML.replace(/<span class="highlight">(.*?)<\/span>/g, '$1'); // Simple approach - only highlight text nodes const nodes = answerEl.childNodes; nodes.forEach(node => { if (node.nodeType === Node.TEXT_NODE) { const newNode = document.createElement('span'); newNode.innerHTML = addHighlights(node.textContent, searchTerm); if (node.parentNode) { node.parentNode.replaceChild(newNode, node); } } }); } // Animation to create "ripple" effect on first load faqItems.forEach((item, index) => { item.style.opacity = '0'; item.style.transform = 'translateY(20px)'; setTimeout(() => { item.style.transition = 'opacity 0.5s ease, transform 0.5s ease'; item.style.opacity = '1'; item.style.transform = 'translateY(0)'; }, 100 + (index * 100)); }); // Keyboard navigation document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { // Close all open FAQs on ESC key faqItems.forEach(item => { item.classList.remove('active'); }); } else if (e.key === 'Tab' && document.activeElement === searchInput) { // If Tab is pressed after search, focus the first visible FAQ const visibleItems = Array.from(faqItems).filter(item => window.getComputedStyle(item).display !== 'none'); if (visibleItems.length > 0) { const firstVisibleQuestion = visibleItems[0].querySelector('.faq-question'); if (firstVisibleQuestion) { e.preventDefault(); firstVisibleQuestion.focus(); } } } }); // Add keydown support for the FAQ questions faqItems.forEach(item => { const question = item.querySelector('.faq-question'); question.setAttribute('tabindex', '0'); question.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); question.click(); } }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Financial Transaction List</title> <style> :root { --primary: #2c3e50; --secondary: #34495e; --income: #27ae60; --expense: #e74c3c; --background: #f9f9fb; --card: #ffffff; --border: #eaeaea; --text-primary: #333333; --text-secondary: #777777; --hover: #f5f7fa; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background-color: var(--background); color: var(--text-primary); padding: 20px; max-width: 700px; max-height: 700px; margin: 0 auto; overflow-x: hidden; } .container { background-color: var(--card); border-radius: 16px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05); overflow: hidden; height: 660px; display: flex; flex-direction: column; } .header { padding: 24px; background-color: var(--primary); color: white; position: relative; overflow: hidden; } .header h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 8px; position: relative; z-index: 2; } .header p { font-size: 0.9rem; opacity: 0.85; margin-bottom: 16px; position: relative; z-index: 2; } .balance { font-size: 2rem; font-weight: 700; margin-bottom: 4px; position: relative; z-index: 2; } .balance-label { font-size: 0.85rem; opacity: 0.8; position: relative; z-index: 2; } .header::after { content: ''; position: absolute; top: -50px; right: -50px; width: 200px; height: 200px; background: rgba(255, 255, 255, 0.05); border-radius: 50%; z-index: 1; } .header::before { content: ''; position: absolute; bottom: -80px; left: -80px; width: 250px; height: 250px; background: rgba(255, 255, 255, 0.03); border-radius: 50%; z-index: 1; } .filters { display: flex; padding: 16px 24px; border-bottom: 1px solid var(--border); background-color: white; gap: 12px; overflow-x: auto; position: relative; } .filters::-webkit-scrollbar { display: none; } .filter-btn { background: none; border: 1px solid var(--border); border-radius: 30px; padding: 8px 16px; font-size: 0.85rem; color: var(--text-secondary); cursor: pointer; white-space: nowrap; transition: all 0.2s ease; } .filter-btn:hover { background-color: var(--hover); } .filter-btn.active { background-color: var(--primary); color: white; border-color: var(--primary); } .search-container { position: relative; margin-left: auto; } .search-input { border: 1px solid var(--border); border-radius: 30px; padding: 8px 16px 8px 36px; font-size: 0.85rem; outline: none; transition: all 0.3s ease; } .search-input:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(44, 62, 80, 0.1); } .search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--text-secondary); font-size: 0.85rem; } .transactions { flex: 1; overflow-y: auto; padding: 8px 0; } .transactions::-webkit-scrollbar { width: 8px; } .transactions::-webkit-scrollbar-track { background: transparent; } .transactions::-webkit-scrollbar-thumb { background-color: rgba(0, 0, 0, 0.1); border-radius: 20px; } .transaction { padding: 16px 24px; border-bottom: 1px solid var(--border); display: flex; align-items: center; cursor: pointer; transition: all 0.2s ease; position: relative; overflow: hidden; } .transaction:hover { background-color: var(--hover); } .transaction-icon { width: 40px; height: 40px; border-radius: 12px; display: flex; align-items: center; justify-content: center; margin-right: 16px; color: white; flex-shrink: 0; } .income .transaction-icon { background-color: var(--income); } .expense .transaction-icon { background-color: var(--expense); } .transaction-details { flex: 1; } .transaction-title { font-weight: 600; margin-bottom: 4px; font-size: 0.95rem; } .transaction-date { font-size: 0.8rem; color: var(--text-secondary); } .transaction-amount { font-weight: 600; font-size: 1rem; } .income .transaction-amount { color: var(--income); } .expense .transaction-amount { color: var(--expense); } .transaction-expand { margin-left: 8px; color: var(--text-secondary); transform: rotate(0deg); transition: transform 0.3s ease; } .transaction.expanded .transaction-expand { transform: rotate(180deg); } .transaction-extra { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; background-color: var(--hover); margin-top: 12px; border-radius: 8px; font-size: 0.85rem; } .transaction.expanded .transaction-extra { max-height: 200px; padding: 12px; margin-top: 16px; } .transaction-extra-row { display: flex; justify-content: space-between; margin-bottom: 8px; } .transaction-extra-row:last-child { margin-bottom: 0; } .transaction-extra-label { color: var(--text-secondary); } .transaction-extra-value { font-weight: 500; } .date-separator { padding: 16px 24px 8px; font-weight: 600; font-size: 0.85rem; color: var(--text-secondary); background-color: var(--background); position: sticky; top: 0; z-index: 2; } .tooltip { position: absolute; background-color: var(--primary); color: white; padding: 6px 12px; border-radius: 4px; font-size: 0.75rem; bottom: 100%; left: 50%; transform: translateX(-50%); opacity: 0; pointer-events: none; transition: opacity 0.2s ease; white-space: nowrap; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); z-index: 10; } .tooltip::after { content: ''; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: var(--primary) transparent transparent transparent; } .transaction:hover .tooltip { opacity: 1; } .pulse { position: absolute; top: 14px; right: 12px; width: 8px; height: 8px; border-radius: 50%; background-color: var(--income); animation: pulse-animation 2s infinite; } @keyframes pulse-animation { 0% { transform: scale(0.8); box-shadow: 0 0 0 0 rgba(39, 174, 96, 0.7); } 70% { transform: scale(1); box-shadow: 0 0 0 10px rgba(39, 174, 96, 0); } 100% { transform: scale(0.8); box-shadow: 0 0 0 0 rgba(39, 174, 96, 0); } } .footer { padding: 16px 24px; border-top: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; background-color: white; } .summary { display: flex; gap: 24px; } .summary-item { display: flex; flex-direction: column; } .summary-label { font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 4px; } .summary-value { font-weight: 600; font-size: 1rem; } .summary-income { color: var(--income); } .summary-expense { color: var(--expense); } .export-btn { background-color: var(--primary); color: white; border: none; border-radius: 8px; padding: 8px 16px; font-size: 0.85rem; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; gap: 8px; } .export-btn:hover { background-color: var(--secondary); } /* Animation for new transactions */ @keyframes slideIn { from { transform: translateX(-20px); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .new-transaction { animation: slideIn 0.3s ease forwards; } /* Empty state */ .empty-state { display: none; flex-direction: column; align-items: center; justify-content: center; padding: 40px; text-align: center; height: 100%; } .empty-state svg { width: 120px; height: 120px; margin-bottom: 24px; color: var(--text-secondary); opacity: 0.5; } .empty-state h3 { font-size: 1.2rem; margin-bottom: 8px; color: var(--text-primary); } .empty-state p { color: var(--text-secondary); font-size: 0.9rem; max-width: 300px; margin-bottom: 24px; } .add-transaction-btn { background-color: var(--primary); color: white; border: none; border-radius: 8px; padding: 10px 20px; font-size: 0.9rem; cursor: pointer; transition: all 0.2s ease; } .add-transaction-btn:hover { background-color: var(--secondary); } /* Responsive styles */ @media (max-width: 500px) { .header { padding: 20px; } .filters, .transaction { padding: 12px 16px; } .date-separator { padding: 12px 16px 6px; } .footer { padding: 12px 16px; flex-direction: column; gap: 16px; align-items: flex-start; } .transaction-icon { width: 36px; height: 36px; margin-right: 12px; } .transaction-title { font-size: 0.9rem; } .transaction-amount { font-size: 0.9rem; } .search-container { width: 100%; margin-left: 0; margin-top: 12px; } .search-input { width: 100%; } .filters { flex-wrap: nowrap; } } </style> </head> <body> <div class="container"> <div class="header"> <div class="pulse"></div> <h1>Your Finances</h1> <p>Checking Account (••••4873)</p> <div class="balance">$7,245.38</div> <div class="balance-label">Available Balance</div> </div> <div class="filters"> <button class="filter-btn active" data-filter="all">All Transactions</button> <button class="filter-btn" data-filter="income">Income</button> <button class="filter-btn" data-filter="expense">Expenses</button> <button class="filter-btn" data-filter="pending">Pending</button> <div class="search-container"> <span class="search-icon">🔍</span> <input type="text" class="search-input" placeholder="Search transactions..."> </div> </div> <div class="transactions"> <div class="date-separator">Today, April 12</div> <div class="transaction expense" data-type="expense" data-category="food"> <div class="transaction-icon">🍔</div> <div class="transaction-details"> <div class="transaction-title">Uber Eats</div> <div class="transaction-date">Today, 1:34 PM</div> <div class="transaction-extra"> <div class="transaction-extra-row"> <span class="transaction-extra-label">Category</span> <span class="transaction-extra-value">Food & Dining</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Status</span> <span class="transaction-extra-value">Completed</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Reference</span> <span class="transaction-extra-value">TXN84759234</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Note</span> <span class="transaction-extra-value">Lunch with coworkers</span> </div> </div> </div> <div class="transaction-amount">-$24.85</div> <span class="transaction-expand">▼</span> <div class="tooltip">Click to see details</div> </div> <div class="transaction expense" data-type="expense" data-category="shopping"> <div class="transaction-icon">🛍️</div> <div class="transaction-details"> <div class="transaction-title">Amazon</div> <div class="transaction-date">Today, 10:15 AM</div> <div class="transaction-extra"> <div class="transaction-extra-row"> <span class="transaction-extra-label">Category</span> <span class="transaction-extra-value">Shopping</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Status</span> <span class="transaction-extra-value">Completed</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Reference</span> <span class="transaction-extra-value">AMZ-58472-XJ</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Note</span> <span class="transaction-extra-value">Wireless earbuds</span> </div> </div> </div> <div class="transaction-amount">-$129.99</div> <span class="transaction-expand">▼</span> <div class="tooltip">Click to see details</div> </div> <div class="date-separator">Yesterday, April 11</div> <div class="transaction income" data-type="income" data-category="salary"> <div class="transaction-icon">💼</div> <div class="transaction-details"> <div class="transaction-title">Paycheck - Acme Inc</div> <div class="transaction-date">Yesterday, 9:00 AM</div> <div class="transaction-extra"> <div class="transaction-extra-row"> <span class="transaction-extra-label">Category</span> <span class="transaction-extra-value">Salary & Wages</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Status</span> <span class="transaction-extra-value">Completed</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Reference</span> <span class="transaction-extra-value">DD-23845-APR</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Note</span> <span class="transaction-extra-value">Bi-weekly paycheck</span> </div> </div> </div> <div class="transaction-amount">+$2,358.42</div> <span class="transaction-expand">▼</span> <div class="tooltip">Click to see details</div> </div> <div class="transaction expense" data-type="expense" data-category="utilities"> <div class="transaction-icon">💡</div> <div class="transaction-details"> <div class="transaction-title">Electric Company</div> <div class="transaction-date">Yesterday, 3:21 PM</div> <div class="transaction-extra"> <div class="transaction-extra-row"> <span class="transaction-extra-label">Category</span> <span class="transaction-extra-value">Utilities</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Status</span> <span class="transaction-extra-value">Completed</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Reference</span> <span class="transaction-extra-value">UTIL-38591</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Note</span> <span class="transaction-extra-value">Monthly electricity bill</span> </div> </div> </div> <div class="transaction-amount">-$87.32</div> <span class="transaction-expand">▼</span> <div class="tooltip">Click to see details</div> </div> <div class="date-separator">April 10</div> <div class="transaction expense" data-type="expense" data-category="transport"> <div class="transaction-icon">🚗</div> <div class="transaction-details"> <div class="transaction-title">Shell Gas Station</div> <div class="transaction-date">Apr 10, 5:45 PM</div> <div class="transaction-extra"> <div class="transaction-extra-row"> <span class="transaction-extra-label">Category</span> <span class="transaction-extra-value">Transportation</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Status</span> <span class="transaction-extra-value">Completed</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Reference</span> <span class="transaction-extra-value">SHL-94752</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Note</span> <span class="transaction-extra-value">Fill-up for road trip</span> </div> </div> </div> <div class="transaction-amount">-$48.67</div> <span class="transaction-expand">▼</span> <div class="tooltip">Click to see details</div> </div> <div class="transaction expense" data-type="expense" data-category="health"> <div class="transaction-icon">💊</div> <div class="transaction-details"> <div class="transaction-title">City Pharmacy</div> <div class="transaction-date">Apr 10, 11:18 AM</div> <div class="transaction-extra"> <div class="transaction-extra-row"> <span class="transaction-extra-label">Category</span> <span class="transaction-extra-value">Healthcare</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Status</span> <span class="transaction-extra-value">Completed</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Reference</span> <span class="transaction-extra-value">PHR-7632198</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Note</span> <span class="transaction-extra-value">Prescription refill</span> </div> </div> </div> <div class="transaction-amount">-$32.50</div> <span class="transaction-expand">▼</span> <div class="tooltip">Click to see details</div> </div> <div class="date-separator">April 8</div> <div class="transaction income" data-type="income" data-category="refund"> <div class="transaction-icon">↩️</div> <div class="transaction-details"> <div class="transaction-title">Return - Best Buy</div> <div class="transaction-date">Apr 8, 2:37 PM</div> <div class="transaction-extra"> <div class="transaction-extra-row"> <span class="transaction-extra-label">Category</span> <span class="transaction-extra-value">Refunds & Returns</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Status</span> <span class="transaction-extra-value">Completed</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Reference</span> <span class="transaction-extra-value">BBY-RET-4875</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Note</span> <span class="transaction-extra-value">Headphones return</span> </div> </div> </div> <div class="transaction-amount">+$89.99</div> <span class="transaction-expand">▼</span> <div class="tooltip">Click to see details</div> </div> </div> <div class="empty-state"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /> </svg> <h3>No transactions found</h3> <p>There are no transactions matching your search criteria.</p> <button class="add-transaction-btn">Reset Filters</button> </div> <div class="footer"> <div class="summary"> <div class="summary-item"> <div class="summary-label">Income (Apr)</div> <div class="summary-value summary-income">$4,758.42</div> </div> <div class="summary-item"> <div class="summary-label">Expenses (Apr)</div> <div class="summary-value summary-expense">$1,895.64</div> </div> </div> <button class="export-btn"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> Export </button> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Transaction expansion const transactions = document.querySelectorAll('.transaction'); transactions.forEach(transaction => { transaction.addEventListener('click', function() { this.classList.toggle('expanded'); }); }); // Filter transactions const filterButtons = document.querySelectorAll('.filter-btn'); const allTransactions = document.querySelectorAll('.transaction'); const emptyState = document.querySelector('.empty-state'); const transactionsContainer = document.querySelector('.transactions'); function updateFilters(filterType) { // Update active button filterButtons.forEach(btn => { if (btn.dataset.filter === filterType) { btn.classList.add('active'); } else { btn.classList.remove('active'); } }); // Filter transactions let visibleCount = 0; allTransactions.forEach(transaction => { if (filterType === 'all' || transaction.dataset.type === filterType) { transaction.style.display = 'flex'; visibleCount++; } else { transaction.style.display = 'none'; } }); // Show empty state if no transactions match if (visibleCount === 0) { emptyState.style.display = 'flex'; transactionsContainer.style.display = 'none'; } else { emptyState.style.display = 'none'; transactionsContainer.style.display = 'block'; } // Hide/show date separators based on visible transactions updateDateSeparators(); } function updateDateSeparators() { const dateSeparators = document.querySelectorAll('.date-separator'); dateSeparators.forEach(separator => { // Get the next element after the date separator let nextElement = separator.nextElementSibling; let visibleTransactionsInGroup = false; // Check all elements until the next date separator while (nextElement && !nextElement.classList.contains('date-separator')) { if (nextElement.style.display !== 'none' && nextElement.classList.contains('transaction')) { visibleTransactionsInGroup = true; break; } nextElement = nextElement.nextElementSibling; } // Hide separator if no visible transactions in its group if (visibleTransactionsInGroup) { separator.style.display = 'block'; } else { separator.style.display = 'none'; } }); } filterButtons.forEach(button => { button.addEventListener('click', function() { updateFilters(this.dataset.filter); }); }); // Search functionality const searchInput = document.querySelector('.search-input'); searchInput.addEventListener('input', function() { const searchTerm = this.value.toLowerCase().trim(); const activeFilter = document.querySelector('.filter-btn.active').dataset.filter; let visibleCount = 0; allTransactions.forEach(transaction => { const title = transaction.querySelector('.transaction-title').textContent.toLowerCase(); const type = transaction.dataset.type; const category = transaction.dataset.category || ''; const matchesSearch = title.includes(searchTerm) || category.includes(searchTerm); const matchesFilter = activeFilter === 'all' || type === activeFilter; if (matchesSearch && matchesFilter) { transaction.style.display = 'flex'; visibleCount++; } else { transaction.style.display = 'none'; } }); if (visibleCount === 0) { emptyState.style.display = 'flex'; transactionsContainer.style.display = 'none'; } else { emptyState.style.display = 'none'; transactionsContainer.style.display = 'block'; } updateDateSeparators(); }); // Reset button functionality const resetButton = document.querySelector('.add-transaction-btn'); resetButton.addEventListener('click', function() { searchInput.value = ''; updateFilters('all'); }); // Export button functionality const exportBtn = document.querySelector('.export-btn'); exportBtn.addEventListener('click', function() { this.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M5 12h14"></path> <path d="M12 5l7 7-7 7"></path> </svg> Downloading... `; setTimeout(() => { this.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" 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> Downloaded `; setTimeout(() => { this.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> Export `; }, 2000); }, 1500); }); // Animation for new transactions function simulateNewTransaction() { setTimeout(() => { // Create new transaction element const newTransaction = document.createElement('div'); newTransaction.className = 'transaction income new-transaction'; newTransaction.dataset.type = 'income'; newTransaction.dataset.category = 'transfer'; newTransaction.innerHTML = ` <div class="transaction-icon">🏦</div> <div class="transaction-details"> <div class="transaction-title">Transfer from Savings</div> <div class="transaction-date">Just now</div> <div class="transaction-extra"> <div class="transaction-extra-row"> <span class="transaction-extra-label">Category</span> <span class="transaction-extra-value">Transfers</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Status</span> <span class="transaction-extra-value">Completed</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Reference</span> <span class="transaction-extra-value">TRF-2847593</span> </div> <div class="transaction-extra-row"> <span class="transaction-extra-label">Note</span> <span class="transaction-extra-value">Monthly savings transfer</span> </div> </div> </div> <div class="transaction-amount">+$500.00</div> <span class="transaction-expand">▼</span> <div class="tooltip">Click to see details</div> `; // Insert after first date separator const firstDateSeparator = document.querySelector('.date-separator'); firstDateSeparator.insertAdjacentElement('afterend', newTransaction); // Add click event for expansion newTransaction.addEventListener('click', function() { this.classList.toggle('expanded'); }); // Update balance const balanceEl = document.querySelector('.balance'); const currentBalance = parseFloat(balanceEl.textContent.replace('$', '').replace(',', '')); const newBalance = (currentBalance + 500).toFixed(2); balanceEl.textContent = '$' + numberWithCommas(newBalance); // Highlight the balance with a subtle animation balanceEl.style.transition = 'color 0.3s ease'; balanceEl.style.color = '#27ae60'; setTimeout(() => { balanceEl.style.color = ''; }, 1500); }, 5000); // Simulate after 5 seconds } // Simulate a new transaction coming in simulateNewTransaction(); // Helper function to format numbers with commas function numberWithCommas(x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } }); </script> </body> </html>