Small Icons On Desktop Guide

// ---- Context menu (right-click) for icon removal ---- function onIconContextMenu(e, icon) e.preventDefault(); removeContextMenu(); // remove existing const menu = document.createElement('div'); menu.className = 'context-menu'; // position near cursor menu.style.left = `$e.clientXpx`; menu.style.top = `$e.clientYpx`; const removeOption = document.createElement('div'); removeOption.className = 'context-menu-item'; removeOption.innerHTML = 'ðŸ—‘ï¸ Remove icon'; removeOption.addEventListener('click', (ev) => ev.stopPropagation(); deleteIconById(icon.id); removeContextMenu(); ); const infoOption = document.createElement('div'); infoOption.className = 'context-menu-item'; infoOption.innerHTML = 'â„¹ï¸ About'; infoOption.addEventListener('click', (ev) => ev.stopPropagation(); showToast(`$icon.name — small desktop icon ); const divider = document.createElement('div'); divider.className = 'context-menu-divider'; const resetOption = document.createElement('div'); resetOption.className = 'context-menu-item'; resetOption.innerHTML = '🔄 Reset all positions'; resetOption.addEventListener('click', (ev) => ev.stopPropagation(); resetToDefaultGrid(); removeContextMenu(); ); menu.appendChild(removeOption); menu.appendChild(infoOption); menu.appendChild(divider); menu.appendChild(resetOption); document.body.appendChild(menu); activeContextMenu = menu; // click outside to close const closeHandler = (clickEvent) => if (!menu.contains(clickEvent.target)) removeContextMenu(); document.removeEventListener('click', closeHandler); ; setTimeout(() => document.addEventListener('click', closeHandler), 10); // ---- Render all icons from iconsState ---- function renderAllIcons() if (!desktopEl) return; desktopEl.innerHTML = ''; // clear all iconsState.forEach(icon => const iconDiv = document.createElement('div'); iconDiv.className = 'desktop-icon'; iconDiv.setAttribute('data-id', icon.id); iconDiv.style.left = `$icon.xpx`; iconDiv.style.top = `$icon.ypx`; iconDiv.style.zIndex = 10; // graphic container const graphicDiv = document.createElement('div'); graphicDiv.className = 'icon-graphic'; // use emoji or custom svg text const emojiSpan = document.createElement('span'); emojiSpan.style.fontSize = '32px'; emojiSpan.style.filter = `drop-shadow(0 2px 4px rgba(0,0,0,0.4))`; emojiSpan.textContent = icon.emoji; graphicDiv.appendChild(emojiSpan); const labelSpan = document.createElement('span'); labelSpan.className = 'icon-label'; labelSpan.textContent = icon.name; iconDiv.appendChild(graphicDiv); iconDiv.appendChild(labelSpan); // attach event listeners iconDiv.addEventListener('mousedown', (e) => onMouseDown(e, icon)); iconDiv.addEventListener('dblclick', (e) => e.stopPropagation(); onDoubleClickIcon(icon); ); iconDiv.addEventListener('contextmenu', (e) => onIconContextMenu(e, icon)); desktopEl.appendChild(iconDiv); ); // ---- initialize icons: build state, load stored positions or default grid ---- function initIcons() // build iconsState from DB iconsState = ICON_DB.map(db => ( id: db.id, name: db.name, emoji: db.emoji, colorTint: db.colorTint, x: 0, y: 0 )); // get container dimensions const rect = desktopEl.getBoundingClientRect(); const defaultMarginX = 40; const defaultMarginY = 40; const colStep = 110; const rowStep = 120; const cols = 3; iconsState.forEach((icon, idx) => const col = idx % cols; const row = Math.floor(idx / cols); icon.x = defaultMarginX + col * colStep; icon.y = defaultMarginY + row * rowStep; ); // try load stored positions after creating default grid const hasStored = loadStoredPositions(); // if stored positions are loaded, they overwrite defaults // but also ensure they are in bounds after loading clampIconPositions(); // will adjust if needed and re-render renderAllIcons(); if (!hasStored) // initially persist default grid persistPositions(); // ---- global desktop right click: reset menu or add? ---- function onDesktopContextMenu(e) e.preventDefault(); removeContextMenu(); const menu = document.createElement('div'); menu.className = 'context-menu'; menu.style.left = `$e.clientXpx`; menu.style.top = `$e.clientYpx`; const resetPos = document.createElement('div'); resetPos.className = 'context-menu-item'; resetPos.innerHTML = '📌 Reset icon positions'; resetPos.addEventListener('click', () => resetToDefaultGrid(); removeContextMenu(); ); const refreshHint = document.createElement('div'); refreshHint.className = 'context-menu-item'; refreshHint.innerHTML = 'ðŸ–±ï¸ Double-click any icon'; refreshHint.addEventListener('click', () => showToast('Double-click icons to open apps! Right-click to remove.', 1500); removeContextMenu(); ); menu.appendChild(resetPos); menu.appendChild(refreshHint); document.body.appendChild(menu); activeContextMenu = menu; const closeHandler = (ce) => if (!menu.contains(ce.target)) removeContextMenu(); document.removeEventListener('click', closeHandler); ; setTimeout(() => document.addEventListener('click', closeHandler), 10); // ---- resize handler to keep icons visible ---- function handleResize() if (!desktopEl) return; clampIconPositions(); // re-render to refresh positions from updated state renderAllIcons(); // ---- set up event listeners, prevent default context menu on desktop ---- function bindGlobalEvents() desktopEl.addEventListener('contextmenu', onDesktopContextMenu); window.addEventListener('resize', () => handleResize(); ); // clicking anywhere outside context menu: handled but also any click on desktop removes menu window.addEventListener('click', (e) => if (activeContextMenu && !activeContextMenu.contains(e.target)) removeContextMenu(); ); // optional: disable default drag behaviour on images window.addEventListener('dragstart', (e) => e.preventDefault()); // ready to launch function launchDesktop() initIcons(); bindGlobalEvents(); // extra: initial clamp after fonts loaded setTimeout(() => handleResize(), 50); launchDesktop(); </script> </body> </html>

// show temporary toast message function showToast(message, duration = 1800) const existingToast = document.querySelector('.toast-msg'); if(existingToast) existingToast.remove(); const toast = document.createElement('div'); toast.className = 'toast-msg'; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => if(toast.parentNode) toast.remove(); , duration);

/* DESKTOP CONTAINER — absolute positioning for icons */ .desktop position: relative; width: 100%; height: 100%; overflow: hidden; background: transparent; cursor: default; small icons on desktop

// -------- Icon dataset: name, icon (emoji or SVG path), default positions -------- const ICON_DB = [ id: "folder_docs", name: "Documents", emoji: "ðŸ“", colorTint: "#5b8c5a" , id: "folder_pics", name: "Gallery", emoji: "🖼ï¸", colorTint: "#b97f44" , id: "app_music", name: "Music Player", emoji: "🎵", colorTint: "#4f7a9e" , id: "app_terminal", name: "Terminal", emoji: "💻", colorTint: "#3c6e47" , id: "app_settings", name: "Settings", emoji: "âš™ï¸", colorTint: "#5f6c7a" , id: "trash_bin", name: "Trash", emoji: "🗑ï¸", colorTint: "#9e5e5e" ];

<div class="desktop" id="desktopContainer"></div> <div class="status-note">✨ Right-click icon → remove | Double‑click to open</div> // ---- Context menu (right-click) for icon removal

body background: radial-gradient(circle at 20% 30%, #1a3c2c, #0a1f1a); min-height: 100vh; font-family: 'Segoe UI', 'SF Pro Text', 'Roboto', system-ui, -apple-system, sans-serif; overflow: hidden; position: relative; height: 100vh; width: 100vw;

.context-menu-divider height: 1px; background: rgba(255,255,200,0.2); margin: 6px 0; menu.className = 'context-menu'

// reset positions to a nice grid (based on current desktop size) function resetToDefaultGrid() const containerRect = desktopEl.getBoundingClientRect(); const marginX = 35; const marginY = 35; const colSpacing = 110; const rowSpacing = 120; const columns = 3; iconsState.forEach((icon, idx) => const col = idx % columns; const row = Math.floor(idx / columns); let x = marginX + col * colSpacing; let y = marginY + row * rowSpacing; // ensure within viewport borders const maxX = Math.max(20, containerRect.width - 100); const maxY = Math.max(20, containerRect.height - 90); x = Math.min(maxX, Math.max(10, x)); y = Math.min(maxY, Math.max(10, y)); icon.x = x; icon.y = y; ); persistPositions(); renderAllIcons(); showToast("✨ Icons rearranged to default grid", 1200);