Tree views are essential for organizing and displaying hierarchical data in a clear and intuitive manner. They allow users to navigate complex structures with ease, making them a staple in modern UI design.
In this article, we will explore 10 exemplary tree view implementations that showcase various design approaches and functionalities. These examples will provide inspiration and insights for creating your own efficient and visually appealing tree views.
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
Subframe's drag-and-drop interface and intuitive, responsive canvas make it effortless to design pixel-perfect tree views. Loved by designers and developers alike, Subframe ensures your UI is both stunning and functional.
Start for free and experience the ease of creating beautiful tree views with Subframe 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 design game? With Subframe, you can create pixel-perfect interfaces, including tree views, in no time. Our drag-and-drop editor and beautifully crafted components make the process efficient and enjoyable.
Start for free and begin designing stunning UIs immediately. Experience the ease and power of Subframe today!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Modern File Explorer</title> <style> :root { --primary-color: #4a6cff; --primary-light: #eef1ff; --secondary-color: #6c757d; --bg-color: #f8f9fa; --folder-color: #ffbb3a; --document-color: #5fbafd; --image-color: #ff5c87; --audio-color: #32c682; --video-color: #ae5cff; --shadow-color: rgba(0, 0, 0, 0.1); --border-radius: 8px; --transition-speed: 0.2s; --font-primary: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: var(--font-primary); background-color: var(--bg-color); color: #333; display: flex; flex-direction: column; height: 100vh; overflow: hidden; padding: 20px; } .file-explorer { display: grid; grid-template-columns: 240px 1fr; gap: 20px; height: 100%; max-width: 700px; width: 100%; margin: 0 auto; background: white; border-radius: 12px; box-shadow: 0 8px 30px var(--shadow-color); overflow: hidden; } .sidebar { background-color: #f5f7fa; padding: 16px; border-right: 1px solid #eaedf1; height: 100%; overflow-y: auto; transition: all var(--transition-speed) ease; } .main-content { padding: 16px; overflow-y: auto; background: white; position: relative; } .explorer-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid #eaedf1; } .explorer-title { font-size: 18px; font-weight: 600; } .search-bar { display: flex; align-items: center; background-color: #f5f7fa; border-radius: 6px; padding: 8px 12px; margin-bottom: 16px; transition: all var(--transition-speed) ease; } .search-bar:focus-within { background-color: white; box-shadow: 0 0 0 2px var(--primary-light), 0 0 0 1px var(--primary-color); } .search-bar input { border: none; background: transparent; width: 100%; font-size: 14px; outline: none; margin-left: 8px; } .search-icon { color: var(--secondary-color); font-size: 14px; } .tree-view { list-style-type: none; } .tree-item { margin: 2px 0; position: relative; } .tree-content { display: flex; align-items: center; padding: 8px 10px; border-radius: var(--border-radius); cursor: pointer; transition: background-color var(--transition-speed) ease; user-select: none; gap: 10px; } .tree-content:hover { background-color: rgba(74, 108, 255, 0.08); } .tree-content.active { background-color: var(--primary-light); color: var(--primary-color); } .tree-icon { display: flex; justify-content: center; align-items: center; width: 24px; height: 24px; border-radius: 4px; transition: transform var(--transition-speed) ease; } .expand-icon { transition: transform var(--transition-speed) ease; color: var(--secondary-color); font-size: 10px; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; } .tree-item.open > .tree-content .expand-icon { transform: rotate(90deg); } .tree-icon svg { width: 16px; height: 16px; } .tree-label { flex: 1; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .tree-children { list-style-type: none; margin-left: 25px; height: 0; overflow: hidden; opacity: 0; transition: height var(--transition-speed) ease, opacity var(--transition-speed) ease; } .tree-item.open > .tree-children { height: auto; opacity: 1; } .folder-icon { color: var(--folder-color); } .document-icon { color: var(--document-color); } .image-icon { color: var(--image-color); } .audio-icon { color: var(--audio-color); } .video-icon { color: var(--video-color); } .breadcrumb { display: flex; gap: 8px; align-items: center; margin-bottom: 16px; font-size: 14px; color: var(--secondary-color); } .breadcrumb-item { cursor: pointer; white-space: nowrap; } .breadcrumb-item:hover { color: var(--primary-color); } .breadcrumb-separator { color: #ccc; } .file-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 16px; } .file-item { display: flex; flex-direction: column; align-items: center; padding: 12px; border-radius: var(--border-radius); cursor: pointer; transition: all var(--transition-speed) ease; position: relative; } .file-item:hover { background-color: var(--primary-light); } .file-icon { display: flex; justify-content: center; align-items: center; width: 48px; height: 48px; margin-bottom: 8px; border-radius: 6px; } .file-name { text-align: center; font-size: 13px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; } .status-bar { display: flex; justify-content: space-between; padding: 8px 16px; background-color: #f5f7fa; font-size: 12px; color: var(--secondary-color); border-top: 1px solid #eaedf1; margin-top: 16px; } .drag-indicator { position: absolute; height: 2px; background-color: var(--primary-color); pointer-events: none; opacity: 0; transition: opacity 0.2s ease; } .drag-ghost { position: fixed; pointer-events: none; z-index: 1000; opacity: 0.7; transform: translate(-50%, -50%); } .drop-zone { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(74, 108, 255, 0.1); border: 2px dashed var(--primary-color); border-radius: var(--border-radius); display: flex; justify-content: center; align-items: center; color: var(--primary-color); font-weight: 500; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; z-index: 10; } .drop-zone.active { opacity: 1; } .file-item.dragging { opacity: 0.5; } .file-context-menu { position: absolute; background: white; border-radius: 8px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); padding: 6px 0; min-width: 180px; z-index: 100; opacity: 0; transform: scale(0.95); transform-origin: top left; pointer-events: none; transition: opacity 0.15s ease, transform 0.15s ease; } .file-context-menu.show { opacity: 1; transform: scale(1); pointer-events: auto; } .context-menu-item { padding: 8px 14px; display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: 13px; transition: background-color 0.15s ease; } .context-menu-item:hover { background-color: var(--primary-light); color: var(--primary-color); } .context-menu-separator { height: 1px; background-color: #eaedf1; margin: 6px 0; } .tooltip { position: absolute; background: rgba(0, 0, 0, 0.8); color: white; padding: 4px 8px; border-radius: 4px; font-size: 12px; z-index: 100; opacity: 0; pointer-events: none; transition: opacity 0.2s ease; white-space: nowrap; } .tooltip.show { opacity: 1; } @media (max-width: 600px) { .file-explorer { grid-template-columns: 1fr; overflow-y: auto; } .sidebar { display: none; } .main-content { overflow-y: visible; } .file-grid { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); } } /* Custom Scrollbar */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.1); border-radius: 10px; } ::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.2); } /* Animation for new items */ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .file-item { animation: fadeIn 0.3s ease forwards; } /* Drag and drop visual feedback */ .drag-over { background-color: var(--primary-light); outline: 2px solid var(--primary-color); } /* Folder open/close animation */ .folder-icon.open { color: var(--folder-color); animation: folderOpen 0.3s forwards; } @keyframes folderOpen { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } </style> </head> <body> <div class="file-explorer"> <aside class="sidebar"> <div class="explorer-header"> <h1 class="explorer-title">File Explorer</h1> </div> <div class="search-bar"> <span class="search-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/> </svg> </span> <input type="text" placeholder="Search files..." id="file-search"> </div> <ul class="tree-view" id="tree-view"> <li class="tree-item open" data-path="Projects"> <div class="tree-content active"> <span class="expand-icon">▶</span> <span class="tree-icon folder-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M.54 3.87.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31zM2.19 4a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91h10.348a1 1 0 0 0 .995-.91l.637-7A1 1 0 0 0 13.81 4H2.19zm4.69-1.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707z"/> </svg> </span> <span class="tree-label">Projects</span> </div> <ul class="tree-children"> <li class="tree-item" data-path="Projects/Web Development"> <div class="tree-content"> <span class="expand-icon">▶</span> <span class="tree-icon folder-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M.54 3.87.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31zM2.19 4a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91h10.348a1 1 0 0 0 .995-.91l.637-7A1 1 0 0 0 13.81 4H2.19zm4.69-1.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707z"/> </svg> </span> <span class="tree-label">Web Development</span> </div> <ul class="tree-children"> <li class="tree-item" data-path="Projects/Web Development/portfolio-site"> <div class="tree-content"> <span class="expand-icon" style="visibility: hidden;">▶</span> <span class="tree-icon document-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71V3.5z"/> <path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm7-8A7 7 0 1 1 1 8a7 7 0 0 1 14 0z"/> </svg> </span> <span class="tree-label">portfolio-site.html</span> </div> </li> <li class="tree-item" data-path="Projects/Web Development/styles"> <div class="tree-content"> <span class="expand-icon" style="visibility: hidden;">▶</span> <span class="tree-icon document-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/> </svg> </span> <span class="tree-label">styles.css</span> </div> </li> </ul> </li> <li class="tree-item" data-path="Projects/Design Assets"> <div class="tree-content"> <span class="expand-icon">▶</span> <span class="tree-icon folder-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M.54 3.87.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31zM2.19 4a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91h10.348a1 1 0 0 0 .995-.91l.637-7A1 1 0 0 0 13.81 4H2.19zm4.69-1.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707z"/> </svg> </span> <span class="tree-label">Design Assets</span> </div> <ul class="tree-children"> <li class="tree-item" data-path="Projects/Design Assets/logo"> <div class="tree-content"> <span class="expand-icon" style="visibility: hidden;">▶</span> <span class="tree-icon image-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M6.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/> <path d="M2.002 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2h-12zm12 1a1 1 0 0 1 1 1v6.5l-3.777-1.947a.5.5 0 0 0-.577.093l-3.71 3.71-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12V3a1 1 0 0 1 1-1h12z"/> </svg> </span> <span class="tree-label">logo.png</span> </div> </li> <li class="tree-item" data-path="Projects/Design Assets/header-bg"> <div class="tree-content"> <span class="expand-icon" style="visibility: hidden;">▶</span> <span class="tree-icon image-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M6.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/> <path d="M2.002 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2h-12zm12 1a1 1 0 0 1 1 1v6.5l-3.777-1.947a.5.5 0 0 0-.577.093l-3.71 3.71-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12V3a1 1 0 0 1 1-1h12z"/> </svg> </span> <span class="tree-label">header-bg.jpg</span> </div> </li> </ul> </li> <li class="tree-item" data-path="Projects/Documents"> <div class="tree-content"> <span class="expand-icon">▶</span> <span class="tree-icon folder-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M.54 3.87.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31zM2.19 4a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91h10.348a1 1 0 0 0 .995-.91l.637-7A1 1 0 0 0 13.81 4H2.19zm4.69-1.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707z"/> </svg> </span> <span class="tree-label">Documents</span> </div> <ul class="tree-children"> <li class="tree-item" data-path="Projects/Documents/project-brief"> <div class="tree-content"> <span class="expand-icon" style="visibility: hidden;">▶</span> <span class="tree-icon document-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/> </svg> </span> <span class="tree-label">project-brief.pdf</span> </div> </li> <li class="tree-item" data-path="Projects/Documents/timeline"> <div class="tree-content"> <span class="expand-icon" style="visibility: hidden;">▶</span> <span class="tree-icon document-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/> </svg> </span> <span class="tree-label">timeline.xlsx</span> </div> </li> </ul> </li> <li class="tree-item" data-path="Projects/Media"> <div class="tree-content"> <span class="expand-icon">▶</span> <span class="tree-icon folder-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M.54 3.87.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31zM2.19 4a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91h10.348a1 1 0 0 0 .995-.91l.637-7A1 1 0 0 0 13.81 4H2.19zm4.69-1.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707z"/> </svg> </span> <span class="tree-label">Media</span> </div> <ul class="tree-children"> <li class="tree-item" data-path="Projects/Media/intro-video"> <div class="tree-content"> <span class="expand-icon" style="visibility: hidden;">▶</span> <span class="tree-icon video-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M0 1a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1zm4 0v6h8V1H4zm8 8H4v6h8V9zM1 1v2h2V1H1zm2 3H1v2h2V4zM1 7v2h2V7H1zm2 3H1v2h2v-2zm-2 3v2h2v-2H1zM15 1h-2v2h2V1zm-2 3v2h2V4h-2zm2 3h-2v2h2V7zm-2 3v2h2v-2h-2zm2 3h-2v2h2v-2z"/> </svg> </span> <span class="tree-label">intro-video.mp4</span> </div> </li> <li class="tree-item" data-path="Projects/Media/interview"> <div class="tree-content"> <span class="expand-icon" style="visibility: hidden;">▶</span> <span class="tree-icon audio-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M8 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 1a4 4 0 1 1 0-8 4 4 0 0 1 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"/> </svg> </span> <span class="tree-label">interview.mp3</span> </div> </li> </ul> </li> </ul> </li> <li class="tree-item" data-path="Downloads"> <div class="tree-content"> <span class="expand-icon">▶</span> <span class="tree-icon folder-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M.54 3.87.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31zM2.19 4a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91h10.348a1 1 0 0 0 .995-.91l.637-7A1 1 0 0 0 13.81 4H2.19zm4.69-1.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707z"/> </svg>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Admin Dashboard Sidebar</title> <style> :root { --primary: #334155; --primary-light: #475569; --secondary: #0ea5e9; --accent: #7c3aed; --text-primary: #f8fafc; --text-secondary: #cbd5e1; --background: #1e293b; --background-light: #243247; --border: #475569; --success: #10b981; --warning: #f59e0b; --danger: #ef4444; --transition-speed: 280ms; } * { 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); display: flex; height: 100vh; overflow: hidden; } .dashboard-container { display: flex; width: 100%; max-width: 700px; height: 700px; margin: auto; border-radius: 12px; overflow: hidden; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.25); position: relative; } .sidebar { width: 280px; background-color: var(--primary); display: flex; flex-direction: column; overflow-y: auto; transition: width var(--transition-speed) ease; scrollbar-width: thin; scrollbar-color: var(--primary-light) var(--primary); } .sidebar::-webkit-scrollbar { width: 6px; } .sidebar::-webkit-scrollbar-track { background: var(--primary); } .sidebar::-webkit-scrollbar-thumb { background-color: var(--primary-light); border-radius: 3px; } .sidebar-header { padding: 20px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--border); position: sticky; top: 0; background-color: var(--primary); z-index: 10; } .logo { display: flex; align-items: center; gap: 12px; } .logo-icon { width: 32px; height: 32px; background-color: var(--accent); border-radius: 8px; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 16px; } .logo-text { font-weight: 600; font-size: 18px; } .toggle-sidebar { background: none; border: none; color: var(--text-secondary); cursor: pointer; width: 32px; height: 32px; border-radius: 6px; display: flex; align-items: center; justify-content: center; transition: background-color 0.2s ease; } .toggle-sidebar:hover { background-color: var(--primary-light); color: var(--text-primary); } .sidebar-search { padding: 16px; position: relative; } .search-icon { position: absolute; left: 28px; top: 50%; transform: translateY(-50%); color: var(--text-secondary); pointer-events: none; } .search-input { width: 100%; padding: 10px 10px 10px 36px; background-color: var(--background-light); border: 1px solid var(--border); border-radius: 6px; color: var(--text-primary); font-size: 14px; outline: none; transition: border-color 0.2s ease, box-shadow 0.2s ease; } .search-input:focus { border-color: var(--secondary); box-shadow: 0 0 0 2px rgba(14, 165, 233, 0.2); } .search-input::placeholder { color: var(--text-secondary); } .tree-view { padding: 0 0 20px 0; } .tree-item { list-style-type: none; } .tree-content { display: flex; align-items: center; padding: 10px 16px; cursor: pointer; border-left: 3px solid transparent; transition: background-color var(--transition-speed) ease, border-left-color var(--transition-speed) ease; position: relative; } .tree-content:hover { background-color: var(--background-light); } .tree-content.active { background-color: var(--background-light); border-left-color: var(--secondary); } .tree-icon { width: 20px; margin-right: 12px; color: var(--text-secondary); transition: color var(--transition-speed) ease; } .tree-content:hover .tree-icon, .tree-content.active .tree-icon { color: var(--text-primary); } .tree-label { flex: 1; font-size: 14px; font-weight: 500; color: var(--text-secondary); transition: color var(--transition-speed) ease; } .tree-content:hover .tree-label, .tree-content.active .tree-label { color: var(--text-primary); } .tree-chevron { color: var(--text-secondary); transition: transform var(--transition-speed) ease; } .tree-item.expanded > .tree-content .tree-chevron { transform: rotate(90deg); } .tree-children { max-height: 0; overflow: hidden; margin-left: 20px; transition: max-height var(--transition-speed) ease; } .tree-item.expanded > .tree-children { max-height: 1000px; } .badge { padding: 2px 8px; font-size: 11px; font-weight: 600; border-radius: 12px; margin-right: 8px; } .badge.new { background-color: var(--accent); color: white; } .badge.updated { background-color: var(--secondary); color: white; } .badge.beta { background-color: var(--warning); color: var(--primary); } .tree-notification { width: 20px; height: 20px; background-color: var(--danger); color: white; border-radius: 50%; font-size: 11px; display: flex; align-items: center; justify-content: center; margin-left: 8px; } .main-content { flex: 1; background-color: var(--background-light); padding: 20px; display: flex; flex-direction: column; overflow-y: auto; } .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; } .page-title { font-size: 24px; font-weight: 600; } .breadcrumb { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-secondary); margin-bottom: 8px; } .breadcrumb-item { display: flex; align-items: center; } .breadcrumb-separator { margin: 0 4px; } .breadcrumb-current { color: var(--text-primary); font-weight: 500; } .empty-state { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 20px; color: var(--text-secondary); } .empty-state-icon { font-size: 60px; margin-bottom: 20px; color: var(--border); } .empty-state-title { font-size: 20px; font-weight: 600; margin-bottom: 12px; color: var(--text-primary); } .empty-state-description { max-width: 300px; margin-bottom: 20px; line-height: 1.5; } .button { padding: 10px 16px; background-color: var(--secondary); color: white; border: none; border-radius: 6px; font-weight: 500; cursor: pointer; transition: background-color 0.2s ease, transform 0.1s ease; display: inline-flex; align-items: center; gap: 8px; } .button:hover { background-color: #0284c7; } .button:active { transform: scale(0.98); } @media (max-width: 600px) { .dashboard-container { border-radius: 0; height: 100vh; } .sidebar { width: 0; position: absolute; height: 100%; z-index: 100; } .sidebar.expanded { width: 280px; } .main-content { width: 100%; } .mobile-toggle { display: block; position: absolute; top: 16px; left: 16px; z-index: 101; background-color: var(--primary); border-radius: 50%; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); } } .pulse { position: relative; } .pulse::before { content: ''; position: absolute; top: 50%; right: 16px; transform: translateY(-50%); width: 8px; height: 8px; background-color: var(--success); border-radius: 50%; } .pulse::after { content: ''; position: absolute; top: 50%; right: 16px; transform: translateY(-50%); width: 8px; height: 8px; background-color: var(--success); border-radius: 50%; animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: translateY(-50%) scale(1); opacity: 1; } 70% { transform: translateY(-50%) scale(2); opacity: 0; } 100% { transform: translateY(-50%) scale(1); opacity: 0; } } .accordion-icon { display: inline-block; width: 16px; height: 16px; margin-right: 10px; position: relative; } .accordion-icon::before, .accordion-icon::after { content: ''; position: absolute; background-color: var(--text-secondary); transition: all var(--transition-speed) ease; } .accordion-icon::before { top: 7px; left: 0; width: 16px; height: 2px; } .accordion-icon::after { top: 0; left: 7px; width: 2px; height: 16px; } .tree-item.expanded > .tree-content .accordion-icon::after { transform: rotate(90deg); opacity: 0; } .shake { animation: shake 0.5s ease-in-out; } @keyframes shake { 0%, 100% { transform: translateX(0); } 20%, 60% { transform: translateX(-4px); } 40%, 80% { transform: translateX(4px); } } .tooltip { position: relative; } .tooltip::after { content: attr(data-tooltip); position: absolute; left: 100%; top: 50%; transform: translateY(-50%); background-color: var(--primary); color: var(--text-primary); padding: 6px 10px; border-radius: 4px; font-size: 12px; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 0.2s ease, transform 0.2s ease; transform: translateY(-50%) translateX(10px); z-index: 100; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); } .tooltip:hover::after { opacity: 1; transform: translateY(-50%) translateX(8px); } </style> </head> <body> <div class="dashboard-container"> <aside class="sidebar"> <div class="sidebar-header"> <div class="logo"> <div class="logo-icon">N</div> <div class="logo-text">NexusAdmin</div> </div> <button class="toggle-sidebar" id="toggle-sidebar"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/> </svg> </button> </div> <div class="sidebar-search"> <div class="search-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" viewBox="0 0 16 16"> <path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/> </svg> </div> <input type="text" class="search-input" placeholder="Search settings..." id="search-input"> </div> <ul class="tree-view" id="tree-view"> <li class="tree-item"> <div class="tree-content active"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M8 4a.5.5 0 0 1 .5.5V6a.5.5 0 0 1-1 0V4.5A.5.5 0 0 1 8 4zM3.732 5.732a.5.5 0 0 1 .707 0l.915.914a.5.5 0 1 1-.708.708l-.914-.915a.5.5 0 0 1 0-.707zM2 10a.5.5 0 0 1 .5-.5h1.586a.5.5 0 0 1 0 1H2.5A.5.5 0 0 1 2 10zm9.5 0a.5.5 0 0 1 .5-.5h1.5a.5.5 0 0 1 0 1H12a.5.5 0 0 1-.5-.5zm.754-4.246a.389.389 0 0 0-.527-.02L7.547 9.31a.91.91 0 1 0 1.302 1.258l3.434-4.297a.389.389 0 0 0-.029-.518z"/> <path fill-rule="evenodd" d="M0 10a8 8 0 1 1 15.547 2.661c-.442 1.253-1.845 1.602-2.932 1.25C11.309 13.488 9.475 13 8 13c-1.474 0-3.31.488-4.615.911-1.087.352-2.49.003-2.932-1.25A7.988 7.988 0 0 1 0 10zm8-7a7 7 0 0 0-6.603 9.329c.203.575.923.876 1.68.63C4.397 12.533 6.358 12 8 12s3.604.532 4.923.96c.757.245 1.477-.056 1.68-.631A7 7 0 0 0 8 3z"/> </svg> </div> <span class="tree-label">Dashboard</span> </div> </li> <li class="tree-item"> <div class="tree-content"> <div class="accordion-icon"></div> <span class="tree-label">User Management</span> <svg class="tree-chevron" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> </svg> </div> <ul class="tree-children"> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0zm4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4zm-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10z"/> </svg> </div> <span class="tree-label">User Directory</span> <div class="tree-notification">8</div> </div> </li> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M7 14s-1 0-1-1 1-4 5-4 5 3 5 4-1 1-1 1H7zm4-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/> <path fill-rule="evenodd" d="M5.216 14A2.238 2.238 0 0 1 5 13c0-1.355.68-2.75 1.936-3.72A6.325 6.325 0 0 0 5 9c-4 0-5 3-5 4s1 1 1 1h4.216z"/> <path d="M4.5 8a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z"/> </svg> </div> <span class="tree-label">Roles & Permissions</span> </div> </li> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/> </svg> </div> <span class="tree-label">User Activity Log</span> </div> </li> </ul> </li> <li class="tree-item"> <div class="tree-content"> <div class="accordion-icon"></div> <span class="tree-label">Content Management</span> <svg class="tree-chevron" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> </svg> </div> <ul class="tree-children"> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2zm15 2h-4v3h4V4zm0 4h-4v3h4V8zm0 4h-4v3h3a1 1 0 0 0 1-1v-2zm-5 3v-3H6v3h4zm-5 0v-3H1v2a1 1 0 0 0 1 1h3zm-4-4h4V8H1v3zm0-4h4V4H1v3zm5-3v3h4V4H6zm4 4H6v3h4V8z"/> </svg> </div> <span class="tree-label">Page Builder</span> <span class="badge new">New</span> </div> </li> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M14.5 3a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h13zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z"/> <path d="M3 5.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zM3 8a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9A.5.5 0 0 1 3 8zm0 2.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5z"/> </svg> </div> <span class="tree-label">Blog Posts</span> </div> </li> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M.002 3a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-12a2 2 0 0 1-2-2V3zm1 9v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V9.5l-3.777-1.947a.5.5 0 0 0-.577.093l-3.71 3.71-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12zm5-6.5a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0z"/> </svg> </div> <span class="tree-label">Media Library</span> </div> </li> <li class="tree-item"> <div class="tree-content"> <div class="accordion-icon"></div> <span class="tree-label">Global Elements</span> <svg class="tree-chevron" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> </svg> </div> <ul class="tree-children"> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M0 1a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1zm4 0v6h8V1H4zm8 8H4v6h8V9zM1 1v2h2V1H1zm2 3H1v2h2V4zM1 7v2h2V7H1zm2 3H1v2h2v-2zm-2 3v2h2v-2H1zM15 1h-2v2h2V1zm-2 3v2h2V4h-2zm2 3h-2v2h2V7zm-2 3v2h2v-2h-2zm2 3h-2v2h2v-2z"/> </svg> </div> <span class="tree-label">Headers & Footers</span> </div> </li> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"/> <path d="M6.854 4.646a.5.5 0 0 1 0 .708L4.207 8l2.647 2.646a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 0 1 .708 0zm2.292 0a.5.5 0 0 0 0 .708L11.793 8l-2.647 2.646a.5.5 0 0 0 .708.708l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.708 0z"/> </svg> </div> <span class="tree-label">Code Snippets</span> </div> </li> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M3.362 10.11c0 .926-.756 1.681-1.681 1.681S0 11.036 0 10.111C0 9.186.756 8.43 1.68 8.43h1.682v1.68zm.846 0c0-.924.756-1.68 1.681-1.68s1.681.756 1.681 1.68v4.21c0 .924-.756 1.68-1.68 1.68a1.685 1.685 0 0 1-1.682-1.68v-4.21zM5.89 3.362c-.926 0-1.682-.756-1.682-1.681S4.964 0 5.89 0s1.68.756 1.68 1.68v1.682H5.89zm0 .846c.924 0 1.68.756 1.68 1.681S6.814 7.57 5.89 7.57H1.68C.757 7.57 0 6.814 0 5.89c0-.926.756-1.682 1.68-1.682h4.21zm6.749 1.682c0-.926.755-1.682 1.68-1.682.925 0 1.681.756 1.681 1.681s-.756 1.681-1.68 1.681h-1.681V5.89zm-.848 0c0 .924-.755 1.68-1.68 1.68A1.685 1.685 0 0 1 8.43 5.89V1.68C8.43.757 9.186 0 10.11 0c.926 0 1.681.756 1.681 1.68v4.21zm-1.681 6.748c.926 0 1.682.756 1.682 1.681S11.036 16 10.11 16s-1.681-.756-1.681-1.68v-1.682h1.68zm0-.847c-.924 0-1.68-.755-1.68-1.68 0-.925.756-1.681 1.68-1.681h4.21c.924 0 1.68.756 1.68 1.68 0 .926-.756 1.681-1.68 1.681h-4.21z"/> </svg> </div> <span class="tree-label">Navigation Menus</span> </div> </li> </ul> </li> </ul> </li> <li class="tree-item"> <div class="tree-content"> <div class="accordion-icon"></div> <span class="tree-label">E-commerce</span> <svg class="tree-chevron" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> </svg> </div> <ul class="tree-children"> <li class="tree-item"> <div class="tree-content"> <div class="tree-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2zm9.5 0a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.5-.5h-1zM3 11.5a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-
<html> <head> <title>E-commerce Category Navigator</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', sans-serif; } :root { --primary: #ff6b6b; --secondary: #4ecdc4; --accent: #ffbe0b; --dark: #1a1a2e; --light: #f7f7f7; --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } body { background-color: var(--light); color: var(--dark); display: flex; justify-content: center; align-items: center; min-height: 100vh; overflow-x: hidden; padding: 20px; } .container { width: 100%; max-width: 700px; height: 700px; background: white; border-radius: 16px; box-shadow: 0 14px 28px rgba(0,0,0,0.05), 0 10px 10px rgba(0,0,0,0.05); overflow: hidden; display: flex; flex-direction: column; } .header { padding: 24px; background: linear-gradient(135deg, var(--primary), var(--secondary)); color: white; text-align: center; position: relative; overflow: hidden; } .header h1 { font-size: 28px; font-weight: 800; margin-bottom: 8px; position: relative; z-index: 2; } .header p { font-size: 16px; opacity: 0.9; margin-bottom: 10px; position: relative; z-index: 2; } .search-container { display: flex; margin: 10px 0; position: relative; z-index: 2; } .search-input { flex: 1; padding: 12px 16px; border: none; border-radius: 50px; font-size: 16px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); outline: none; transition: var(--transition); } .search-input:focus { box-shadow: 0 6px 10px rgba(0,0,0,0.15); } .search-btn { background: var(--accent); border: none; width: 48px; border-radius: 50%; margin-left: 10px; cursor: pointer; box-shadow: 0 4px 6px rgba(0,0,0,0.1); transition: var(--transition); display: flex; justify-content: center; align-items: center; } .search-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 10px rgba(0,0,0,0.15); } .search-btn i { color: var(--dark); font-size: 18px; } .pattern { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: radial-gradient(circle, rgba(255,255,255,0.1) 2px, transparent 2px); background-size: 20px 20px; opacity: 0.5; z-index: 1; } .navigation { flex: 1; padding: 20px; overflow-y: auto; position: relative; } .popular-tags { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 24px; } .tag { padding: 8px 16px; background: #f0f0f0; border-radius: 30px; font-size: 14px; cursor: pointer; transition: var(--transition); display: flex; align-items: center; gap: 6px; } .tag:hover { background: var(--secondary); color: white; transform: translateY(-2px); } .tag-icon { font-size: 14px; } .categories { list-style: none; } .category { margin-bottom: 5px; border-radius: 10px; transition: var(--transition); } .category-header { display: flex; align-items: center; padding: 14px 18px; cursor: pointer; border-radius: 10px; transition: var(--transition); position: relative; overflow: hidden; } .category-header:hover { background: rgba(78, 205, 196, 0.1); } .category-header.active { background: var(--secondary); color: white; } .category-icon { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; font-size: 18px; margin-right: 14px; background: rgba(255, 107, 107, 0.1); border-radius: 8px; color: var(--primary); transition: var(--transition); } .category-header.active .category-icon { background: rgba(255, 255, 255, 0.2); color: white; } .category-title { flex: 1; font-weight: 600; font-size: 16px; } .category-items { font-size: 14px; opacity: 0.7; } .category-arrow { transform: rotate(0deg); transition: var(--transition); font-size: 18px; } .category.open .category-arrow { transform: rotate(90deg); } .category-header .ripple { position: absolute; border-radius: 50%; background-color: rgba(255, 255, 255, 0.7); transform: scale(0); animation: ripple 0.6s linear; pointer-events: none; } @keyframes ripple { to { transform: scale(4); opacity: 0; } } .subcategories { max-height: 0; overflow: hidden; transition: max-height 0.5s ease; list-style: none; padding-left: 46px; } .category.open .subcategories { max-height: 500px; } .subcategory { padding: 12px 18px; margin: 6px 0; border-radius: 8px; display: flex; align-items: center; cursor: pointer; transition: var(--transition); position: relative; overflow: hidden; } .subcategory:hover { background: rgba(255, 107, 107, 0.1); } .subcategory-icon { margin-right: 12px; font-size: 16px; color: var(--primary); opacity: 0.9; } .subcategory-title { font-weight: 500; flex: 1; } .subcategory-count { background: var(--accent); color: var(--dark); font-size: 12px; font-weight: 600; padding: 2px 8px; border-radius: 30px; min-width: 28px; text-align: center; } .bottom-nav { display: flex; justify-content: space-between; padding: 16px 24px; background: white; box-shadow: 0 -2px 10px rgba(0,0,0,0.05); } .nav-item { display: flex; flex-direction: column; align-items: center; cursor: pointer; transition: var(--transition); } .nav-item:hover { color: var(--primary); transform: translateY(-2px); } .nav-icon { font-size: 22px; margin-bottom: 5px; } .nav-label { font-size: 12px; font-weight: 500; } .subcategory-preview { position: absolute; background: white; padding: 15px; border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,0.15); width: 200px; display: none; z-index: 10; top: 50%; left: 100%; transform: translateY(-50%); animation: slideIn 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); pointer-events: none; } @keyframes slideIn { from { opacity: 0; transform: translate(10px, -50%); } to { opacity: 1; transform: translate(0, -50%); } } .preview-title { font-weight: 600; margin-bottom: 8px; color: var(--primary); } .preview-items { font-size: 13px; line-height: 1.5; } /* Custom scrollbar */ .navigation::-webkit-scrollbar { width: 6px; } .navigation::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; } .navigation::-webkit-scrollbar-thumb { background: var(--secondary); border-radius: 10px; } .navigation::-webkit-scrollbar-thumb:hover { background: var(--primary); } /* For Firefox */ .navigation { scrollbar-width: thin; scrollbar-color: var(--secondary) #f1f1f1; } @media (max-width: 500px) { .header h1 { font-size: 24px; } .header p { font-size: 14px; } .category-header { padding: 12px 15px; } .subcategory { padding: 10px 15px; } .category-icon { width: 28px; height: 28px; font-size: 16px; margin-right: 12px; } .nav-icon { font-size: 20px; } .nav-label { font-size: 11px; } } </style> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&display=swap" rel="stylesheet"> </head> <body> <div class="container"> <div class="header"> <div class="pattern"></div> <h1>Shop by Category</h1> <p>Discover thousands of products in our curated collections</p> <div class="search-container"> <input type="text" class="search-input" placeholder="Search for categories, items, brands..."> <button class="search-btn"> <i class="fas fa-search"></i> </button> </div> </div> <div class="navigation"> <div class="popular-tags"> <div class="tag"><i class="fas fa-bolt tag-icon"></i>Flash Deals</div> <div class="tag"><i class="fas fa-percentage tag-icon"></i>Clearance</div> <div class="tag"><i class="fas fa-star tag-icon"></i>New Arrivals</div> <div class="tag"><i class="fas fa-fire tag-icon"></i>Trending</div> </div> <ul class="categories"> <li class="category"> <div class="category-header"> <div class="category-icon"><i class="fas fa-tshirt"></i></div> <span class="category-title">Fashion</span> <span class="category-items">2,345 items</span> <i class="fas fa-chevron-right category-arrow"></i> </div> <ul class="subcategories"> <li class="subcategory"> <i class="fas fa-female subcategory-icon"></i> <span class="subcategory-title">Women's Clothing</span> <span class="subcategory-count">845</span> <div class="subcategory-preview"> <div class="preview-title">Women's Clothing</div> <div class="preview-items"> Dresses, Tops, Pants, Skirts, Activewear, Swimwear, Outerwear </div> </div> </li> <li class="subcategory"> <i class="fas fa-male subcategory-icon"></i> <span class="subcategory-title">Men's Clothing</span> <span class="subcategory-count">765</span> <div class="subcategory-preview"> <div class="preview-title">Men's Clothing</div> <div class="preview-items"> Shirts, Pants, Suits, Activewear, Swimwear, Outerwear </div> </div> </li> <li class="subcategory"> <i class="fas fa-child subcategory-icon"></i> <span class="subcategory-title">Kids' Clothing</span> <span class="subcategory-count">412</span> </li> <li class="subcategory"> <i class="fas fa-shoe-prints subcategory-icon"></i> <span class="subcategory-title">Footwear</span> <span class="subcategory-count">323</span> </li> </ul> </li> <li class="category"> <div class="category-header"> <div class="category-icon"><i class="fas fa-laptop"></i></div> <span class="category-title">Electronics</span> <span class="category-items">1,876 items</span> <i class="fas fa-chevron-right category-arrow"></i> </div> <ul class="subcategories"> <li class="subcategory"> <i class="fas fa-mobile-alt subcategory-icon"></i> <span class="subcategory-title">Smartphones</span> <span class="subcategory-count">423</span> </li> <li class="subcategory"> <i class="fas fa-laptop subcategory-icon"></i> <span class="subcategory-title">Laptops & Computers</span> <span class="subcategory-count">289</span> </li> <li class="subcategory"> <i class="fas fa-headphones subcategory-icon"></i> <span class="subcategory-title">Audio & Headphones</span> <span class="subcategory-count">312</span> </li> <li class="subcategory"> <i class="fas fa-camera subcategory-icon"></i> <span class="subcategory-title">Cameras</span> <span class="subcategory-count">156</span> </li> </ul> </li> <li class="category"> <div class="category-header"> <div class="category-icon"><i class="fas fa-home"></i></div> <span class="category-title">Home & Living</span> <span class="category-items">3,012 items</span> <i class="fas fa-chevron-right category-arrow"></i> </div> <ul class="subcategories"> <li class="subcategory"> <i class="fas fa-couch subcategory-icon"></i> <span class="subcategory-title">Furniture</span> <span class="subcategory-count">518</span> </li> <li class="subcategory"> <i class="fas fa-bed subcategory-icon"></i> <span class="subcategory-title">Bedding & Bath</span> <span class="subcategory-count">467</span> </li> <li class="subcategory"> <i class="fas fa-utensils subcategory-icon"></i> <span class="subcategory-title">Kitchen</span> <span class="subcategory-count">743</span> </li> <li class="subcategory"> <i class="fas fa-lightbulb subcategory-icon"></i> <span class="subcategory-title">Lighting</span> <span class="subcategory-count">236</span> </li> </ul> </li> <li class="category"> <div class="category-header"> <div class="category-icon"><i class="fas fa-heartbeat"></i></div> <span class="category-title">Health & Beauty</span> <span class="category-items">1,533 items</span> <i class="fas fa-chevron-right category-arrow"></i> </div> <ul class="subcategories"> <li class="subcategory"> <i class="fas fa-spa subcategory-icon"></i> <span class="subcategory-title">Skincare</span> <span class="subcategory-count">345</span> </li> <li class="subcategory"> <i class="fas fa-palette subcategory-icon"></i> <span class="subcategory-title">Makeup</span> <span class="subcategory-count">421</span> </li> <li class="subcategory"> <i class="fas fa-pump-medical subcategory-icon"></i> <span class="subcategory-title">Personal Care</span> <span class="subcategory-count">286</span> </li> <li class="subcategory"> <i class="fas fa-dumbbell subcategory-icon"></i> <span class="subcategory-title">Fitness</span> <span class="subcategory-count">198</span> </li> </ul> </li> <li class="category"> <div class="category-header"> <div class="category-icon"><i class="fas fa-gamepad"></i></div> <span class="category-title">Toys & Games</span> <span class="category-items">987 items</span> <i class="fas fa-chevron-right category-arrow"></i> </div> <ul class="subcategories"> <li class="subcategory"> <i class="fas fa-puzzle-piece subcategory-icon"></i> <span class="subcategory-title">Board Games</span> <span class="subcategory-count">126</span> </li> <li class="subcategory"> <i class="fas fa-robot subcategory-icon"></i> <span class="subcategory-title">Action Figures</span> <span class="subcategory-count">211</span> </li> <li class="subcategory"> <i class="fas fa-dice subcategory-icon"></i> <span class="subcategory-title">Collectibles</span> <span class="subcategory-count">187</span> </li> <li class="subcategory"> <i class="fas fa-baby subcategory-icon"></i> <span class="subcategory-title">Baby Toys</span> <span class="subcategory-count">143</span> </li> </ul> </li> </ul> </div> <div class="bottom-nav"> <div class="nav-item"> <i class="fas fa-home nav-icon"></i> <span class="nav-label">Home</span> </div> <div class="nav-item"> <i class="fas fa-th-large nav-icon"></i> <span class="nav-label">Categories</span> </div> <div class="nav-item"> <i class="fas fa-heart nav-icon"></i> <span class="nav-label">Wishlist</span> </div> <div class="nav-item"> <i class="fas fa-shopping-cart nav-icon"></i> <span class="nav-label">Cart</span> </div> <div class="nav-item"> <i class="fas fa-user nav-icon"></i> <span class="nav-label">Account</span> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initialize category toggles const categoryHeaders = document.querySelectorAll('.category-header'); categoryHeaders.forEach(header => { header.addEventListener('click', function(e) { // Create ripple effect const circle = document.createElement('span'); const diameter = Math.max(this.clientWidth, this.clientHeight); const radius = diameter / 2; circle.style.width = circle.style.height = `${diameter}px`; circle.style.left = `${e.clientX - this.getBoundingClientRect().left - radius}px`; circle.style.top = `${e.clientY - this.getBoundingClientRect().top - radius}px`; circle.classList.add('ripple'); const ripple = this.getElementsByClassName('ripple')[0]; if (ripple) { ripple.remove(); } this.appendChild(circle); // Toggle active class for styling categoryHeaders.forEach(h => h.classList.remove('active')); this.classList.add('active'); // Toggle category open state const category = this.parentNode; if (category.classList.contains('open')) { category.classList.remove('open'); } else { document.querySelectorAll('.category').forEach(cat => { cat.classList.remove('open'); }); category.classList.add('open'); } }); }); // Initialize subcategory previews const subcategories = document.querySelectorAll('.subcategory'); subcategories.forEach(subcategory => { const preview = subcategory.querySelector('.subcategory-preview'); if (preview) { subcategory.addEventListener('mouseenter', function() { preview.style.display = 'block'; }); subcategory.addEventListener('mouseleave', function() { preview.style.display = 'none'; }); } }); // Add click listeners to tags const tags = document.querySelectorAll('.tag'); tags.forEach(tag => { tag.addEventListener('click', function() { tags.forEach(t => t.style.background = '#f0f0f0'); tags.forEach(t => t.style.color = 'var(--dark)'); this.style.background = 'var(--primary)'; this.style.color = 'white'; }); }); // Add click listeners to nav items const navItems = document.querySelectorAll('.nav-item'); navItems.forEach(item => { item.addEventListener('click', function() { navItems.forEach(ni => ni.style.color = ''); this.style.color = 'var(--primary)'; }); }); // Initialize with the first category open document.querySelector('.category').classList.add('open'); document.querySelector('.category-header').classList.add('active'); // Add click listener to search button const searchBtn = document.querySelector('.search-btn'); const searchInput = document.querySelector('.search-input'); searchBtn.addEventListener('click', function() { if (searchInput.value.trim() !== '') { // In a real app, you would handle the search here searchInput.value = ''; // Visual feedback searchBtn.classList.add('clicked'); setTimeout(() => { searchBtn.classList.remove('clicked'); }, 300); } }); // Allow Enter key to trigger search searchInput.addEventListener('keypress', function(e) { if (e.key === 'Enter' && this.value.trim() !== '') { // In a real app, you would handle the search here this.value = ''; // Visual feedback searchBtn.classList.add('clicked'); setTimeout(() => { searchBtn.classList.remove('clicked'); }, 300); } }); }); </script> </body> </html>
<html> <head> <style> :root { --bg-primary: #1e1e2e; --bg-secondary: #282a36; --bg-hover: #313244; --text-primary: #f8f8f2; --text-secondary: #bac2de; --text-muted: #6c7086; --accent-blue: #89b4fa; --accent-green: #a6e3a1; --accent-red: #f38ba8; --accent-yellow: #f9e2af; --accent-purple: #cba6f7; --accent-orange: #fab387; --accent-cyan: #89dceb; --shadow: rgba(0, 0, 0, 0.2); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; } body { background-color: var(--bg-primary); color: var(--text-primary); height: 100vh; display: flex; flex-direction: column; overflow: hidden; } header { background-color: var(--bg-secondary); padding: 15px 20px; border-bottom: 1px solid #3b3b4d; display: flex; justify-content: space-between; align-items: center; } .repo-info { display: flex; align-items: center; gap: 12px; } .repo-icon { color: var(--accent-purple); font-size: 22px; } .repo-name { font-weight: 600; color: var(--text-primary); font-size: 16px; } .repo-details { display: flex; gap: 15px; } .repo-stat { display: flex; align-items: center; gap: 5px; color: var(--text-secondary); font-size: 13px; } .container { display: flex; height: calc(100vh - 58px); position: relative; } .sidebar { width: 200px; background-color: var(--bg-secondary); border-right: 1px solid #3b3b4d; overflow-y: auto; transition: width 0.3s ease; padding: 15px 0; } .main-content { flex: 1; overflow-y: auto; padding: 20px; position: relative; } .search-bar { margin: 0 15px 15px; position: relative; } .search-input { width: 100%; background-color: var(--bg-primary); border: 1px solid #3b3b4d; border-radius: 5px; padding: 8px 10px 8px 30px; color: var(--text-primary); font-size: 13px; outline: none; transition: border-color 0.2s ease; } .search-input:focus { border-color: var(--accent-blue); } .search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-muted); font-size: 14px; } .branch-selector { margin: 0 15px 15px; display: flex; align-items: center; gap: 5px; padding: 6px 10px; background-color: var(--bg-primary); border-radius: 5px; cursor: pointer; font-size: 13px; border: 1px solid #3b3b4d; color: var(--text-secondary); transition: background-color 0.2s ease; } .branch-selector:hover { background-color: var(--bg-hover); } .branch-icon { color: var(--accent-purple); } .sidebar-title { padding: 10px 15px 5px; font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; } .file-tree { list-style-type: none; padding-left: 15px; } .tree-item { margin: 2px 0; position: relative; } .tree-toggle { display: inline-flex; align-items: center; cursor: pointer; padding: 4px 8px; border-radius: 4px; transition: background-color 0.2s ease; width: 100%; } .tree-toggle:hover { background-color: var(--bg-hover); } .tree-toggle.active { background-color: rgba(137, 180, 250, 0.1); } .toggle-icon { display: inline-block; width: 14px; height: 14px; margin-right: 5px; color: var(--text-secondary); transition: transform 0.2s ease; } .tree-toggle.expanded .toggle-icon { transform: rotate(90deg); } .item-name { display: flex; align-items: center; gap: 6px; font-size: 13px; } .item-icon { color: var(--text-muted); font-size: 14px; } .item-icon.folder { color: var(--accent-yellow); } .item-icon.file-js { color: var(--accent-yellow); } .item-icon.file-html { color: var(--accent-orange); } .item-icon.file-css { color: var(--accent-blue); } .item-icon.file-json { color: var(--accent-cyan); } .item-icon.file-md { color: var(--accent-purple); } .item-icon.file-ts { color: var(--accent-blue); } .item-icon.file-img { color: var(--accent-green); } .item-icon.file-txt { color: var(--text-secondary); } .nested { display: none; padding-left: 20px; margin-top: 2px; list-style-type: none; overflow: hidden; max-height: 0; transition: max-height 0.3s ease-in-out; } .tree-toggle.expanded + .nested { display: block; max-height: 1000px; } .file-path { padding: 10px 15px; background-color: var(--bg-secondary); border-radius: 5px; margin-bottom: 15px; font-size: 13px; overflow-x: auto; white-space: nowrap; color: var(--text-secondary); } .path-separator { color: var(--text-muted); margin: 0 5px; } .file-details { display: flex; gap: 20px; margin-bottom: 20px; } .file-stats { display: flex; gap: 15px; font-size: 13px; color: var(--text-secondary); } .file-stat { display: flex; align-items: center; gap: 5px; } .file-actions { display: flex; gap: 10px; } .file-action { background-color: var(--bg-secondary); color: var(--text-secondary); border: none; padding: 6px 12px; border-radius: 5px; cursor: pointer; font-size: 13px; display: flex; align-items: center; gap: 5px; transition: background-color 0.2s ease; } .file-action:hover { background-color: var(--bg-hover); } .file-content { background-color: var(--bg-secondary); border-radius: 5px; padding: 20px; font-size: 14px; line-height: 1.5; overflow-x: auto; border: 1px solid #3b3b4d; } .line-numbers { color: var(--text-muted); text-align: right; padding-right: 10px; user-select: none; padding-top: 12px; padding-bottom: 12px; } .code-content { padding: 12px 0; } .code-line { display: flex; } .code-text { flex: 1; color: var(--text-primary); } .active-file { background-color: rgba(137, 180, 250, 0.1); } .bottom-bar { position: fixed; bottom: 0; left: 0; right: 0; background-color: var(--bg-secondary); display: flex; padding: 8px 20px; font-size: 12px; color: var(--text-secondary); border-top: 1px solid #3b3b4d; } .bottom-stat { display: flex; align-items: center; gap: 5px; margin-right: 15px; } .loading-indicator { position: absolute; top: 0; left: 0; width: 0; height: 3px; background: linear-gradient(90deg, var(--accent-blue), var(--accent-purple)); animation: loading 1s ease-in-out; z-index: 999; } @keyframes loading { 0% { width: 0; } 50% { width: 70%; } 100% { width: 100%; } } /* Theme markers */ .keyword { color: var(--accent-purple); } .string { color: var(--accent-green); } .comment { color: var(--text-muted); font-style: italic; } .function { color: var(--accent-blue); } .number { color: var(--accent-orange); } .property { color: var(--accent-cyan); } .operator { color: var(--accent-red); } .html-tag { color: var(--accent-red); } .html-attr { color: var(--accent-cyan); } /* CSS for tooltip */ .tooltip { position: relative; display: inline-block; } .tooltip .tooltip-text { visibility: hidden; background-color: #2a2a3a; color: var(--text-primary); text-align: center; border-radius: 4px; padding: 5px 10px; position: absolute; z-index: 1; bottom: 125%; left: 50%; transform: translateX(-50%); opacity: 0; transition: opacity 0.2s; white-space: nowrap; font-size: 12px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); pointer-events: none; } .tooltip:hover .tooltip-text { visibility: visible; opacity: 1; } /* Responsive adjustments */ @media (max-width: 700px) { .sidebar { width: 50px; overflow-x: hidden; } .sidebar:hover { width: 200px; z-index: 10; } .sidebar-title, .branch-selector span, .search-bar { display: none; } .sidebar:hover .sidebar-title, .sidebar:hover .branch-selector span, .sidebar:hover .search-bar { display: block; } .file-details { flex-direction: column; gap: 10px; } .file-actions { justify-content: space-between; } } /* Pulsing animation for active file */ @keyframes pulse { 0% { background-color: rgba(137, 180, 250, 0.1); } 50% { background-color: rgba(137, 180, 250, 0.2); } 100% { background-color: rgba(137, 180, 250, 0.1); } } .tree-toggle.active { animation: pulse 2s infinite; } /* Fancy badge */ .badge { display: inline-block; padding: 2px 6px; border-radius: 10px; font-size: 10px; text-transform: uppercase; font-weight: bold; margin-left: 5px; } .badge-new { background-color: var(--accent-green); color: var(--bg-primary); } .badge-modified { background-color: var(--accent-orange); color: var(--bg-primary); } /* File drag indicator */ .drag-indicator { height: 2px; background-color: var(--accent-blue); margin: 2px 0; opacity: 0; transition: opacity 0.2s; } .drag-indicator.active { opacity: 1; } /* Custom scrollbar */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: var(--bg-primary); } ::-webkit-scrollbar-thumb { background: #3b3b4d; border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { background: #4d4d63; } </style> </head> <body> <div class="loading-indicator"></div> <header> <div class="repo-info"> <i class="repo-icon fas fa-code-branch"></i> <span class="repo-name">quantum-ui</span> </div> <div class="repo-details"> <div class="repo-stat tooltip"> <i class="fas fa-star"></i> <span>254</span> <span class="tooltip-text">Stars</span> </div> <div class="repo-stat tooltip"> <i class="fas fa-code-branch"></i> <span>54</span> <span class="tooltip-text">Forks</span> </div> <div class="repo-stat tooltip"> <i class="fas fa-eye"></i> <span>1.2k</span> <span class="tooltip-text">Watchers</span> </div> </div> </header> <div class="container"> <div class="sidebar"> <div class="search-bar"> <i class="search-icon fas fa-search"></i> <input type="text" class="search-input" placeholder="Search files..."> </div> <div class="branch-selector"> <i class="branch-icon fas fa-code-branch"></i> <span>main</span> </div> <div class="sidebar-title">Explorer</div> <ul class="file-tree"> <li class="tree-item"> <div class="tree-toggle expanded"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>src</span> </div> </div> <ul class="nested"> <li class="tree-item"> <div class="tree-toggle expanded"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>components</span> </div> </div> <ul class="nested"> <li class="tree-item"> <div class="tree-toggle expanded"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>Button</span> </div> </div> <ul class="nested"> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-js fab fa-js"></i> <span>Button.jsx</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-css fab fa-css3"></i> <span>Button.module.css</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-js fab fa-js"></i> <span>index.js</span> </div> </div> </li> </ul> </li> <li class="tree-item"> <div class="tree-toggle expanded"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>TreeView</span> <span class="badge badge-new">New</span> </div> </div> <ul class="nested"> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-ts fab fa-js"></i> <span>TreeView.tsx</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle active"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-ts fab fa-js"></i> <span>TreeNode.tsx</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-css fab fa-css3"></i> <span>TreeView.module.css</span> <span class="badge badge-modified">Modified</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-js fab fa-js"></i> <span>index.ts</span> </div> </div> </li> </ul> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>Modal</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>Dropdown</span> </div> </div> </li> </ul> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>hooks</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>utils</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-js fab fa-js"></i> <span>index.ts</span> </div> </div> </li> </ul> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>public</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon">▶</span> <div class="item-name"> <i class="item-icon folder fas fa-folder"></i> <span>tests</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-json fas fa-file-code"></i> <span>package.json</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-json fas fa-file-code"></i> <span>tsconfig.json</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-md fas fa-file-alt"></i> <span>README.md</span> </div> </div> </li> <li class="tree-item"> <div class="tree-toggle"> <span class="toggle-icon invisible"></span> <div class="item-name"> <i class="item-icon file-md fas fa-file-alt"></i> <span>CHANGELOG.md</span> </div> </div> </li> <li class="tree-item"> <div class="drag-indicator"></div> </li> </ul> </div> <div class="main-content"> <div class="file-path"> <span style="color: var(--accent-yellow);">quantum-ui</span> <span class="path-separator">/</span> <span>src</span> <span class="path-separator">/</span> <span>components</span> <span class="path-separator">/</span> <span>TreeView</span> <span class="path-separator">/</span> <span style="color: var(--accent-blue);">TreeNode.tsx</span> </div> <div class="file-details"> <div class="file-stats"> <div class="file-stat tooltip"> <i class="fas fa-code"></i> <span>124 lines</span> <span class="tooltip-text">Lines of code</span> </div> <div class="file-stat tooltip"> <i class="fas fa-history"></i> <span>Last edited 2 hours ago</span> <span class="tooltip-text">By quantum-dev</span> </div> </div> <div class="file-actions"> <button class="file-action tooltip"> <i class="fas fa-edit"></i> <span>Edit</span> <span class="tooltip-text">Edit file</span> </button> <button class="file-action tooltip"> <i class="fas fa-history"></i> <span>History</span> <span class="tooltip-text">View file history</span> </button> <button class="file-action tooltip"> <i class="fas fa-download"></i> <span>Raw</span> <span class="tooltip-text">View raw file</span> </button> </div> </div> <div class="file-content"> <table> <tbody> <tr class="code-line"> <td class="line-numbers">1</td> <td class="code-text"><span class="keyword">import</span> React, { <span class="property">useState</span>, <span class="property">useEffect</span>, <span class="property">useRef</span> } <span class="keyword">from</span> <span class="string">'react'</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">2</td> <td class="code-text"><span class="keyword">import</span> styles <span class="keyword">from</span> <span class="string">'./TreeView.module.css'</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">3</td> <td class="code-text"></td> </tr> <tr class="code-line"> <td class="line-numbers">4</td> <td class="code-text"><span class="keyword">export</span> <span class="keyword">interface</span> <span class="function">TreeNodeProps</span> {</td> </tr> <tr class="code-line"> <td class="line-numbers">5</td> <td class="code-text"> <span class="property">id</span>: <span class="property">string</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">6</td> <td class="code-text"> <span class="property">label</span>: <span class="property">string</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">7</td> <td class="code-text"> <span class="property">icon</span>?: <span class="property">string</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">8</td> <td class="code-text"> <span class="property">type</span>: <span class="string">'file'</span> | <span class="string">'folder'</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">9</td> <td class="code-text"> <span class="property">children</span>?: <span class="property">TreeNodeProps</span>[];</td> </tr> <tr class="code-line"> <td class="line-numbers">10</td> <td class="code-text"> <span class="property">isExpanded</span>?: <span class="property">boolean</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">11</td> <td class="code-text"> <span class="property">level</span>?: <span class="property">number</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">12</td> <td class="code-text"> <span class="property">onToggle</span>?: (<span class="property">id</span>: <span class="property">string</span>) <span class="operator">=></span> <span class="property">void</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">13</td> <td class="code-text"> <span class="property">onSelect</span>?: (<span class="property">id</span>: <span class="property">string</span>) <span class="operator">=></span> <span class="property">void</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">14</td> <td class="code-text"> <span class="property">isSelected</span>?: <span class="property">boolean</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">15</td> <td class="code-text"> <span class="property">isDraggable</span>?: <span class="property">boolean</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">16</td> <td class="code-text"> <span class="property">badge</span>?: {</td> </tr> <tr class="code-line"> <td class="line-numbers">17</td> <td class="code-text"> <span class="property">text</span>: <span class="property">string</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">18</td> <td class="code-text"> <span class="property">variant</span>: <span class="string">'new'</span> | <span class="string">'modified'</span> | <span class="string">'error'</span>;</td> </tr> <tr class="code-line"> <td class="line-numbers">19</td> <td class="code-text"> }</td> </tr> <tr class="code-line"> <td class="line-numbers">20</td> <td class="code-text">}</td> </tr> <tr class="code-line"> <td class="line-numbers">21</td> <td class="code-text"></td> </tr> <tr class="code-line"> <td class="line-numbers">22</td> <td class="code-text"><span class="comment">/**</span></td> </tr> <tr class="code-line"> <td class="line-numbers">23</td> <td class="code-text"><span class="comment"> * TreeNode component represents a node in the tree structure</span></td> </tr> <tr class="code-line"> <td class="line-numbers">24</td> <td class="code-text"><span class="comment"> * It can be a file or a folder with nested items</span></td> </tr> <tr class="code-line"> <td class="line-numbers">25</td> <td class="code-text"><span class="comment"> */</span></td> </tr> <tr class="code-line"> <td class="line-numbers">26</td> <td class="code-text"><span class="keyword">const</span> <span class="function">TreeNode</span>: <span class="property">React.FC</span><span class="operator"><</span><span class="property">TreeNodeProps</span><span class="operator">></span> <span class="operator">=</span> ({</td> </tr> <tr class="code-line"> <td class="line-numbers">27</td> <td class="code-text"> <span class="property">id</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">28</td> <td class="code-text"> <span class="property">label</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">29</td> <td class="code-text"> <span class="property">icon</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">30</td> <td class="code-text"> <span class="property">type</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">31</td> <td class="code-text"> <span class="property">children</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">32</td> <td class="code-text"> <span class="property">isExpanded</span> <span class="operator">=</span> <span class="keyword">false</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">33</td> <td class="code-text"> <span class="property">level</span> <span class="operator">=</span> <span class="number">0</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">34</td> <td class="code-text"> <span class="property">onToggle</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">35</td> <td class="code-text"> <span class="property">onSelect</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">36</td> <td class="code-text"> <span class="property">isSelected</span> <span class="operator">=</span> <span class="keyword">false</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">37</td> <td class="code-text"> <span class="property">isDraggable</span> <span class="operator">=</span> <span class="keyword">true</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">38</td> <td class="code-text"> <span class="property">badge</span>,</td> </tr> <tr class="code-line"> <td class="line-numbers">39</td> <td class="code-text">}) <span class="operator">=></span> {</td> </tr> <tr class="code-line"> <td class="line-numbers">40</td> <td class="code-text"> <span class="keyword">const</span> [<span class="property">expanded</span>, <span class="property">setExpanded</span>] <span class="operator">=</span> <span class="function">useState</span><span class="operator">
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Organizational Chart Explorer</title> <style> * { 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; } :root { --primary: #2c5282; --primary-light: #4299e1; --secondary: #38b2ac; --text-dark: #2d3748; --text-light: #718096; --background: #f7fafc; --white: #ffffff; --border: #e2e8f0; --hover: #ebf8ff; --shadow: 0 4px 6px rgba(0, 0, 0, 0.1); --transition: all 0.3s ease; } body { background: var(--background); color: var(--text-dark); height: 700px; width: 700px; overflow: hidden; display: flex; flex-direction: column; } .container { width: 100%; height: 100%; max-width: 700px; max-height: 700px; padding: 1rem; display: flex; flex-direction: column; overflow: hidden; } .header { display: flex; justify-content: space-between; align-items: center; padding-bottom: 1rem; border-bottom: 1px solid var(--border); margin-bottom: 1rem; } .title { font-size: 1.5rem; font-weight: 700; color: var(--primary); display: flex; align-items: center; gap: 0.5rem; } .search-container { position: relative; width: 220px; height: 38px; } .search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-light); } .search-input { width: 100%; height: 100%; padding: 0.5rem 0.5rem 0.5rem 2rem; border-radius: 6px; border: 1px solid var(--border); background: var(--white); color: var(--text-dark); font-size: 0.875rem; transition: var(--transition); } .search-input:focus { outline: none; border-color: var(--primary-light); box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.2); } .org-chart { flex: 1; overflow: auto; padding: 1rem 0; margin-top: 0.5rem; position: relative; } .zoom-controls { position: absolute; right: 1rem; top: 1rem; display: flex; flex-direction: column; background: var(--white); border-radius: 6px; box-shadow: var(--shadow); z-index: 100; } .zoom-btn { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; background: var(--white); border: none; cursor: pointer; color: var(--primary); font-size: 1.125rem; transition: var(--transition); } .zoom-btn:first-child { border-bottom: 1px solid var(--border); border-radius: 6px 6px 0 0; } .zoom-btn:last-child { border-radius: 0 0 6px 6px; } .zoom-btn:hover { background: var(--hover); } .node { display: inline-block; position: relative; padding: 0.5rem 0; vertical-align: top; text-align: center; list-style-type: none; transition: var(--transition); } .node::before, .node::after { content: ""; position: absolute; top: 0; left: 50%; border-left: 1px solid var(--border); width: 0; height: 20px; } .node::after { top: auto; bottom: 0; height: 20px; } .node:only-child::after, .node:only-child::before { display: none; } .node:first-child::before, .node:last-child::after { border: 0 none; } .node:last-child::before { border-left: 1px solid var(--border); border-bottom-left-radius: 5px; } .node:first-child::after { border-right: 1px solid var(--border); border-top-right-radius: 5px; } .level { white-space: nowrap; margin: 0; padding: 0; } .level-1 { text-align: center; } .level-2, .level-3, .level-4 { position: relative; } .level-2::before, .level-3::before, .level-4::before { content: ""; position: absolute; top: 50px; left: 0; width: 100%; height: 1px; background-color: var(--border); } .employee-card { display: inline-block; background: linear-gradient(145deg, var(--white), #f0f5ff); border: 1px solid var(--border); border-radius: 8px; box-shadow: var(--shadow); padding: 0.75rem 1rem; margin: 0 0.5rem 1rem; width: 180px; text-align: left; cursor: pointer; position: relative; transition: var(--transition); z-index: 10; } .employee-card:hover { transform: translateY(-3px); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); border-color: var(--primary-light); } .employee-card.active { border-color: var(--primary); background: linear-gradient(145deg, #f0f5ff, #e6f0ff); } .employee-header { display: flex; align-items: center; margin-bottom: 0.5rem; } .employee-avatar { width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); margin-right: 0.75rem; display: flex; align-items: center; justify-content: center; color: var(--white); font-weight: 600; font-size: 0.875rem; } .employee-info { flex: 1; } .employee-name { font-weight: 600; font-size: 0.9375rem; color: var(--text-dark); line-height: 1.3; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .employee-role { font-size: 0.75rem; color: var(--text-light); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .employee-meta { display: flex; justify-content: space-between; align-items: center; font-size: 0.75rem; color: var(--text-light); margin-top: 0.5rem; } .employee-team { display: flex; align-items: center; gap: 0.25rem; } .team-icon { font-size: 0.875rem; } .employee-reports { display: flex; align-items: center; gap: 0.25rem; } .toggle-btn { position: absolute; bottom: -12px; left: 50%; transform: translateX(-50%); width: 24px; height: 24px; background: var(--white); border: 1px solid var(--border); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 20; transition: var(--transition); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .toggle-btn:hover { background: var(--primary-light); color: var(--white); border-color: var(--primary-light); } .toggle-btn.active { background: var(--primary); color: var(--white); border-color: var(--primary); } .collapsed > ul { display: none; } .children { padding-top: 30px; position: relative; } .tooltip { position: absolute; background: var(--white); box-shadow: var(--shadow); border-radius: 6px; padding: 0.75rem; width: 200px; z-index: 100; visibility: hidden; opacity: 0; transition: opacity 0.2s, visibility 0.2s; } .tooltip-header { display: flex; align-items: center; margin-bottom: 0.5rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--border); } .tooltip-avatar { width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); margin-right: 0.75rem; display: flex; align-items: center; justify-content: center; color: var(--white); font-weight: 600; font-size: 1rem; } .tooltip-info h3 { font-size: 1rem; font-weight: 600; margin: 0 0 0.25rem; } .tooltip-info p { font-size: 0.75rem; color: var(--text-light); margin: 0; } .tooltip-body { font-size: 0.8125rem; } .tooltip-contact { display: flex; gap: 0.75rem; margin-top: 0.5rem; } .tooltip-contact-item { display: flex; align-items: center; gap: 0.25rem; font-size: 0.75rem; color: var(--primary); } .tooltip-contact-icon { font-size: 0.875rem; } .detail-panel { position: absolute; right: 0; top: 0; width: 0; height: 100%; background: var(--white); box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1); transition: width 0.3s ease-in-out; overflow: hidden; z-index: 200; } .detail-panel.open { width: 270px; } .detail-header { padding: 1.25rem; background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); color: var(--white); display: flex; flex-direction: column; align-items: center; position: relative; } .close-panel { position: absolute; top: 0.75rem; right: 0.75rem; background: none; border: none; color: var(--white); cursor: pointer; font-size: 1.25rem; opacity: 0.8; transition: var(--transition); } .close-panel:hover { opacity: 1; } .detail-avatar { width: 80px; height: 80px; border-radius: 50%; background: var(--white); display: flex; align-items: center; justify-content: center; font-size: 2rem; font-weight: 600; color: var(--primary); margin-bottom: 1rem; border: 3px solid rgba(255, 255, 255, 0.3); } .detail-name { font-size: 1.25rem; font-weight: 600; margin: 0 0 0.25rem; text-align: center; } .detail-role { font-size: 0.875rem; opacity: 0.9; text-align: center; margin: 0; } .detail-body { padding: 1.25rem; } .detail-section { margin-bottom: 1.25rem; } .detail-section-title { font-size: 0.875rem; text-transform: uppercase; color: var(--text-light); margin: 0 0 0.75rem; letter-spacing: 0.5px; } .detail-info-item { display: flex; margin-bottom: 0.5rem; font-size: 0.875rem; } .detail-info-label { flex: 0 0 90px; color: var(--text-light); } .detail-info-value { flex: 1; color: var(--text-dark); font-weight: 500; } .detail-contact { display: flex; flex-wrap: wrap; gap: 0.5rem; } .detail-contact-btn { flex: 1; min-width: 100px; padding: 0.5rem; background: var(--background); border: 1px solid var(--border); border-radius: 6px; font-size: 0.8125rem; display: flex; align-items: center; justify-content: center; gap: 0.375rem; color: var(--text-dark); cursor: pointer; transition: var(--transition); } .detail-contact-btn:hover { background: var(--hover); border-color: var(--primary-light); color: var(--primary); } .detail-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.75rem; } .detail-stat-item { padding: 0.75rem; background: var(--background); border-radius: 6px; text-align: center; } .detail-stat-value { font-size: 1.125rem; font-weight: 600; color: var(--primary); margin: 0 0 0.25rem; } .detail-stat-label { font-size: 0.75rem; color: var(--text-light); margin: 0; } /* Animation keyframes */ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes slideDown { from { transform: translateY(-20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } /* Loading animation */ .loading { display: flex; justify-content: center; align-items: center; height: 100%; width: 100%; } .loading-spinner { width: 40px; height: 40px; border: 3px solid rgba(44, 82, 130, 0.2); border-radius: 50%; border-top-color: var(--primary); animation: spin 1s ease-in-out infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Responsiveness */ @media (max-width: 500px) { .header { flex-direction: column; align-items: flex-start; gap: 0.75rem; } .search-container { width: 100%; } .employee-card { width: 150px; } .detail-panel.open { width: 100%; } } /* New additions for enhanced visual effect */ .gradient-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle at top right, rgba(56, 178, 172, 0.05) 0%, rgba(44, 82, 130, 0.05) 100%); pointer-events: none; z-index: -1; } .connection-line { stroke: #cbd5e0; stroke-width: 1; fill: none; transition: all 0.3s ease; } .connection-line.highlight { stroke: var(--primary-light); stroke-width: 2; filter: drop-shadow(0 0 3px rgba(66, 153, 225, 0.4)); } .legend { position: absolute; bottom: 1rem; left: 1rem; display: flex; gap: 1rem; padding: 0.5rem 0.75rem; background: var(--white); border-radius: 6px; box-shadow: var(--shadow); font-size: 0.75rem; opacity: 0.9; } .legend-item { display: flex; align-items: center; gap: 0.375rem; } .legend-color { width: 10px; height: 10px; border-radius: 50%; } .legend-color.executive { background: #4c51bf; } .legend-color.management { background: #38a169; } .legend-color.staff { background: #e53e3e; } </style> </head> <body> <div class="container"> <div class="header"> <h1 class="title"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path> <circle cx="9" cy="7" r="4"></circle> <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path> <path d="M16 3.13a4 4 0 0 1 0 7.75"></path> </svg> Silverstone Tech Organization </h1> <div class="search-container"> <span class="search-icon"> <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"> <circle cx="11" cy="11" r="8"></circle> <line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </span> <input type="text" class="search-input" placeholder="Search employee by name..." id="search-input"> </div> </div> <div class="org-chart" id="org-chart"> <div class="zoom-controls"> <button class="zoom-btn" id="zoom-in">+</button> <button class="zoom-btn" id="zoom-out">-</button> </div> <div class="loading" id="loading"> <div class="loading-spinner"></div> </div> <div class="legend"> <div class="legend-item"> <span class="legend-color executive"></span> <span>Executive</span> </div> <div class="legend-item"> <span class="legend-color management"></span> <span>Management</span> </div> <div class="legend-item"> <span class="legend-color staff"></span> <span>Staff</span> </div> </div> <svg id="connections-svg" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 5;"></svg> </div> <div class="detail-panel" id="detail-panel"> <!-- Detail panel content will be dynamically inserted --> </div> <div class="gradient-bg"></div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Organization data structure const orgData = { id: 'emp1', name: 'Elena Rodriguez', role: 'Chief Executive Officer', department: 'Executive', location: 'San Francisco, CA', email: '[email protected]', phone: '+1 (415) 555-8901', hireDate: '2015-06-12', level: 'Executive', directReports: 5, teamSize: 127, children: [ { id: 'emp2', name: 'Marcus Chen', role: 'Chief Technology Officer', department: 'Technology', location: 'San Francisco, CA', email: '[email protected]', phone: '+1 (415) 555-2341', hireDate: '2016-03-18', level: 'Executive', directReports: 3, teamSize: 48, children: [ { id: 'emp6', name: 'Priya Sharma', role: 'VP of Engineering', department: 'Engineering', location: 'San Francisco, CA', email: '[email protected]', phone: '+1 (415) 555-6789', hireDate: '2017-05-02', level: 'Management', directReports: 4, teamSize: 32, children: [ { id: 'emp11', name: 'David Kim', role: 'Engineering Manager', department: 'Engineering', location: 'San Francisco, CA', email: '[email protected]', phone: '+1 (415) 555-3456', hireDate: '2018-11-15', level: 'Management', directReports: 8, teamSize: 8, children: [] }, { id: 'emp12', name: 'Sarah Johnson', role: 'DevOps Lead', department: 'Engineering', location: 'San Francisco, CA', email: '[email protected]', phone: '+1 (415) 555-7890', hireDate: '2019-02-28', level: 'Management', directReports: 5, teamSize: 5, children: [] } ] }, { id: 'emp7', name: 'James Wilson', role: 'VP of Product', department: 'Product', location: 'Austin, TX', email: '[email protected]', phone: '+1 (512) 555-4567', hireDate: '2018-01-22', level: 'Management', directReports: 3, teamSize: 12, children: [ { id: 'emp13', name: 'Ana Diaz', role: 'Product Manager', department: 'Product', location: 'Austin, TX', email: '[email protected]', phone: '+1 (512) 555-8901', hireDate: '2019-08-15', level: 'Staff', directReports: 0, teamSize: 0, children: [] } ] } ] }, { id: 'emp3', name: 'Olivia Bennett', role: 'Chief Financial Officer', department: 'Finance', location: 'New York, NY', email: '[email protected]', phone: '+1 (212) 555-4567', hireDate: '2017-09-25', level: 'Executive', directReports: 2, teamSize: 15, children: [ { id: 'emp8', name: 'Thomas Wright', role: 'Financial Controller', department: 'Finance', location: 'New York, NY', email: '[email protected]', phone: '+1 (212) 555-7890', hireDate: '2018-05-14', level: 'Management', directReports: 6, teamSize: 6, children: [] } ] }, { id: 'emp4', name: 'Jackson Lee', role: 'Chief Marketing Officer', department: 'Marketing', location: 'Seattle, WA', email: '[email protected]', phone: '+1 (206) 555-8901', hireDate: '2018-03-12', level: 'Executive', directReports: 3, teamSize: 22, children: [ { id: 'emp9', name: 'Emma Martinez', role: 'Marketing Director', department: 'Marketing', location: 'Seattle, WA', email: '[email protected]', phone: '+1 (206) 555-2345', hireDate: '2019-06-03', level: 'Management', directReports: 7, teamSize: 7, children: [] } ] }, { id: 'emp5', name: 'Sophia Williams', role: 'Chief People Officer', department: 'Human Resources', location: 'Boston, MA', email: '[email protected]', phone: '+1 (617) 555-6789', hireDate: '2017-11-08', level: 'Executive', directReports: 2, teamSize: 10, children: [ { id: 'emp10', name: 'Michael Taylor', role: 'HR Director', department: 'Human Resources', location: 'Boston, MA', email: '[email protected]', phone: '+1 (617) 555-0123', hireDate: '2019-01-15', level: 'Management', directReports: 4, teamSize: 4, children: [] } ] } ] }; const orgChart = document.getElementById('org-chart'); const detailPanel = document.getElementById('detail-panel'); const loading = document.getElementById('loading'); const searchInput = document.getElementById('search-input'); const connectionsSvg = document.getElementById('connections-svg'); const zoomInBtn = document.getElementById('zoom-in'); const zoomOutBtn = document.getElementById('zoom-out'); // Scale factor for zoom (default 1) let currentScale = 1; let orgChartContent = null; // Function to get initials from name function getInitials(name) { return name.split(' ').map(n => n[0]).join(''); } // Color mapping based on level function getLevelColor(level) { const colors = { 'Executive': '#4c51bf', 'Management': '#38a169', 'Staff': '#e53e3e' }; return colors[level] || '#4299e1'; } // Build the organization chart tree function buildOrgChart(data, level = 1) { const node = document.createElement('li'); node.className = 'node'; node.dataset.id = data.id; // Create employee card const card = document.createElement('div'); card.className = 'employee-card'; card.dataset.id = data.id; const avatarColor = getLevelColor(data.level); // Create card content card.innerHTML = ` <div class="employee-header"> <div class="employee-avatar" style="background:linear-gradient(135deg, ${avatarColor} 0%, ${lightenColor(avatarColor, 30)} 100%)"> ${getInitials(data.name)} </div> <div class="employee-info"> <h3 class="employee-name">${data.name}</h3> <div class="employee-role">${data.role}</div> </div> </div> <div class="employee-meta"> <div class="employee-team"> <span class="team-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M20 7h-4V4c0-1.1-.9-2-2-2h-4c-1.1 0-2 .9-2 2v3H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2z"/> </svg> </span> ${data.department} </div> <div class="employee-reports"> <span>${data.directReports}</span> <span> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path> <circle cx="9" cy="7" r="4"></circle> <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path> <path d="M16 3.13a4 4 0 0 1 0 7.75"></path> </svg> </span> </div> </div> `; // Add toggle button if has children if (data.children && data.children.length > 0) { const toggleBtn = document.createElement('button'); toggleBtn.className = 'toggle-btn'; toggleBtn.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="6 9 12 15 18 9"></polyline> </svg> `; card.appendChild(toggleBtn); toggleBtn.addEventListener('click', function(e) { e.stopPropagation(); const parentNode = this.closest('.node'); parentNode.classList.toggle('collapsed'); this.classList.toggle('active'); // Update connections after toggling setTimeout(updateConnections, 300); }); } node.appendChild(card); // Show details when card is clicked card.addEventListener('click', function() { showEmployeeDetails(data); // Remove active class from all cards and add to current document.querySelectorAll('.employee-card').forEach(c => c.classList.remove('active')); card.classList.add('active'); }); // Create tooltip for hover const tooltip = document.createElement('div'); tooltip.className = 'tooltip'; tooltip.innerHTML = ` <div class="tooltip-header"> <div class="tooltip-avatar" style="background:linear-gradient(135deg, ${avatarColor} 0%, ${lightenColor(avatarColor, 30)} 100%)"> ${getInitials(data.name)} </div> <div class="tooltip-info"> <h3>${data.name}</h3> <p>${data.role}</p> </div> </div> <div class="tooltip-body"> <p>${data.department} · ${data.location}</p> <div class="tooltip-contact"> <div class="tooltip-contact-item"> <span class="tooltip-contact-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path> <polyline points="22,6 12,13 2,6"></polyline> </svg> </span> Email </div> <div class="tooltip-contact-item"> <span class="tooltip-contact-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path> </svg> </span> Call </div> </div> </div> `; card.addEventListener('mouseenter', function(e) { const rect = card.getBoundingClientRect(); const orgChartRect = orgChart.getBoundingClientRect(); tooltip.style.left = `${rect.right + 10 - orgCh
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root { --primary: #5B8AF7; --primary-hover: #4A79E6; --secondary: #6FC9C6; --tertiary: #FFC857; --quaternary: #FF7F50; --quinary: #9D84B7; --light: #F5F7FA; --text: #2D3748; --text-light: #718096; --border: #E2E8F0; --shadow: 0 4px 6px rgba(0, 0, 0, 0.1); --radius: 12px; --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background-color: var(--light); color: var(--text); font-size: 16px; line-height: 1.6; height: 100vh; width: 100%; display: flex; flex-direction: column; overflow: hidden; } .lms-navigator { display: flex; flex-direction: column; max-width: 700px; width: 100%; height: 700px; margin: 0 auto; background: white; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); position: relative; } .navigator-header { padding: 20px; background: linear-gradient(to right, var(--primary), var(--secondary)); color: white; border-top-left-radius: var(--radius); border-top-right-radius: var(--radius); } .navigator-header h1 { font-size: 1.6rem; margin-bottom: 5px; display: flex; align-items: center; } .navigator-header h1 svg { margin-right: 10px; } .navigator-header p { font-size: 0.95rem; opacity: 0.9; } .search-container { padding: 15px 20px; background: white; border-bottom: 1px solid var(--border); display: flex; } .search-input { flex: 1; padding: 10px 15px; border: 1px solid var(--border); border-radius: 6px; font-size: 0.9rem; outline: none; transition: var(--transition); } .search-input:focus { border-color: var(--primary); box-shadow: 0 0 0 2px rgba(91, 138, 247, 0.2); } .search-input::placeholder { color: var(--text-light); } .tree-container { flex: 1; overflow-y: auto; padding: 0; } .course-tree { list-style: none; padding: 0; } .course-item { margin: 0; border-bottom: 1px solid var(--border); } .course-header { padding: 15px 20px; display: flex; align-items: center; cursor: pointer; transition: var(--transition); position: relative; } .course-header:hover { background-color: rgba(91, 138, 247, 0.05); } .course-header.active { background-color: rgba(91, 138, 247, 0.1); } .course-icon { width: 28px; height: 28px; border-radius: 6px; display: flex; align-items: center; justify-content: center; margin-right: 12px; color: white; flex-shrink: 0; } .course-title { flex: 1; font-weight: 500; } .course-info { font-size: 0.8rem; color: var(--text-light); margin-top: 3px; } .toggle-arrow { margin-left: 10px; transition: transform 0.3s ease; } .course-header.active .toggle-arrow { transform: rotate(90deg); } .module-list { max-height: 0; overflow: hidden; list-style: none; transition: max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1); background-color: #F9FAFC; } .module-list.expanded { max-height: 1000px; } .module-item { margin: 0; border-top: 1px solid var(--border); } .module-header { padding: 12px 20px 12px 40px; display: flex; align-items: center; cursor: pointer; transition: var(--transition); } .module-header:hover { background-color: rgba(111, 201, 198, 0.05); } .module-header.active { background-color: rgba(111, 201, 198, 0.1); } .module-icon { width: 22px; height: 22px; border-radius: 4px; display: flex; align-items: center; justify-content: center; margin-right: 12px; color: white; flex-shrink: 0; } .module-title { flex: 1; font-weight: 500; font-size: 0.95rem; } .lesson-list { max-height: 0; overflow: hidden; list-style: none; transition: max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1); background-color: #F5F7FA; } .lesson-list.expanded { max-height: 800px; } .lesson-item { padding: 10px 20px 10px 74px; position: relative; cursor: pointer; transition: var(--transition); display: flex; align-items: center; border-top: 1px solid var(--border); } .lesson-item:hover { background-color: rgba(255, 200, 87, 0.1); } .lesson-item.active, .lesson-item:active { background-color: rgba(255, 200, 87, 0.2); } .lesson-icon { width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; margin-right: 10px; color: var(--text-light); flex-shrink: 0; } .lesson-title { font-size: 0.9rem; flex: 1; } .lesson-duration { font-size: 0.75rem; color: var(--text-light); margin-left: 10px; } .completion-badge { display: inline-flex; padding: 2px 8px; border-radius: 12px; font-size: 0.7rem; margin-left: 10px; align-items: center; justify-content: center; font-weight: 600; } .completion-badge.completed { background-color: rgba(111, 201, 198, 0.15); color: var(--secondary); } .completion-badge.in-progress { background-color: rgba(255, 200, 87, 0.15); color: var(--tertiary); } .completion-badge.not-started { background-color: rgba(113, 128, 150, 0.15); color: var(--text-light); } .completion-badge svg { margin-right: 4px; font-size: 10px; } .progress-ring { width: 18px; height: 18px; margin-left: 10px; position: relative; } .progress-ring circle { transition: stroke-dashoffset 0.35s; transform: rotate(-90deg); transform-origin: 50% 50%; } .navigator-footer { padding: 15px 20px; background: #F5F7FA; border-top: 1px solid var(--border); font-size: 0.85rem; color: var(--text-light); display: flex; justify-content: space-between; align-items: center; } .view-toggle { display: flex; align-items: center; } .view-toggle-btn { background: none; border: none; color: var(--text-light); margin-left: 10px; cursor: pointer; display: flex; align-items: center; transition: var(--transition); padding: 5px 10px; border-radius: 4px; } .view-toggle-btn:hover { background-color: rgba(91, 138, 247, 0.1); color: var(--primary); } .view-toggle-btn.active { background-color: var(--primary); color: white; } .view-toggle-btn svg { margin-right: 4px; } /* Custom scrollbar */ .tree-container::-webkit-scrollbar { width: 8px; } .tree-container::-webkit-scrollbar-track { background: #f1f1f1; } .tree-container::-webkit-scrollbar-thumb { background: #c1c1c1; border-radius: 4px; } .tree-container::-webkit-scrollbar-thumb:hover { background: #a8a8a8; } /* Progress indicator */ .progress-indicator { height: 4px; background-color: #E2E8F0; position: absolute; bottom: 0; left: 0; width: 100%; overflow: hidden; } .progress-bar { height: 100%; background: linear-gradient(to right, var(--tertiary), var(--quaternary)); width: 0; transition: width 0.8s ease; } /* Pulse effect for current lesson */ @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(255, 127, 80, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(255, 127, 80, 0); } 100% { box-shadow: 0 0 0 0 rgba(255, 127, 80, 0); } } .current-lesson { animation: pulse 2s infinite; } /* Tooltip */ .tooltip { position: relative; } .tooltip:hover::after { content: attr(data-tooltip); position: absolute; bottom: 125%; left: 50%; transform: translateX(-50%); background-color: #333; color: white; padding: 5px 10px; border-radius: 4px; white-space: nowrap; font-size: 0.75rem; z-index: 10; opacity: 0; animation: fadeIn 0.3s forwards; } @keyframes fadeIn { to { opacity: 1; } } /* Responsive tweaks */ @media (max-width: 500px) { .navigator-header h1 { font-size: 1.3rem; } .course-header, .module-header { padding: 12px 10px; } .lesson-item { padding: 10px 10px 10px 54px; } .completion-badge { display: none; } } </style> </head> <body> <div class="lms-navigator"> <div class="navigator-header"> <h1> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="22 12 16 12 14 15 10 15 8 12 2 12"></polyline> <path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"></path> </svg> Learning Path Navigator </h1> <p>Explore your personalized learning journey and track your progress</p> </div> <div class="search-container"> <input type="text" class="search-input" placeholder="Search for courses, modules, or lessons..." id="searchInput"> </div> <div class="tree-container"> <ul class="course-tree" id="courseTree"> <!-- Course 1 --> <li class="course-item"> <div class="course-header" data-course="1"> <div class="course-icon" style="background-color: var(--primary);"> <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="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path> <path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path> </svg> </div> <div> <div class="course-title">Web Development Fundamentals</div> <div class="course-info">12 modules • 87% complete</div> </div> <div class="completion-badge completed"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> In Progress </div> <svg class="toggle-arrow" 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"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </div> <ul class="module-list"> <!-- Module 1 --> <li class="module-item"> <div class="module-header" data-module="1"> <div class="module-icon" style="background-color: var(--secondary);"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="16 18 22 12 16 6"></polyline> <polyline points="8 6 2 12 8 18"></polyline> </svg> </div> <div class="module-title">HTML & CSS Basics</div> <div class="completion-badge completed"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" 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> Completed </div> <svg class="toggle-arrow" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </div> <ul class="lesson-list"> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> </svg> </div> <div class="lesson-title">Introduction to HTML5 Structure</div> <div class="lesson-duration">12 min</div> </li> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> </svg> </div> <div class="lesson-title">CSS Selectors & Properties</div> <div class="lesson-duration">18 min</div> </li> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path> <polyline points="14 2 14 8 20 8"></polyline> </svg> </div> <div class="lesson-title">Box Model & Layout Fundamentals</div> <div class="lesson-duration">15 min</div> </li> </ul> </li> <!-- Module 2 --> <li class="module-item"> <div class="module-header" data-module="2"> <div class="module-icon" style="background-color: var(--tertiary);"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon> </svg> </div> <div class="module-title">Responsive Design Principles</div> <div class="completion-badge in-progress"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <polyline points="12 6 12 12 16 14"></polyline> </svg> In Progress </div> <svg class="toggle-arrow" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </div> <ul class="lesson-list"> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> </svg> </div> <div class="lesson-title">Media Queries & Breakpoints</div> <div class="lesson-duration">22 min</div> </li> <li class="lesson-item current-lesson"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <polygon points="10 8 16 12 10 16 10 8"></polygon> </svg> </div> <div class="lesson-title">Flexbox & Grid Systems</div> <div class="lesson-duration">25 min</div> </li> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="16" x2="12" y2="12"></line> <line x1="12" y1="8" x2="12.01" y2="8"></line> </svg> </div> <div class="lesson-title">Mobile-First Design Approach</div> <div class="lesson-duration">18 min</div> </li> </ul> </li> </ul> </li> <!-- Course 2 --> <li class="course-item"> <div class="course-header" data-course="2"> <div class="course-icon" style="background-color: var(--quaternary);"> <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"> <circle cx="12" cy="12" r="10"></circle> <line x1="14.31" y1="8" x2="20.05" y2="17.94"></line> <line x1="9.69" y1="8" x2="21.17" y2="8"></line> <line x1="7.38" y1="12" x2="13.12" y2="2.06"></line> <line x1="9.69" y1="16" x2="3.95" y2="6.06"></line> <line x1="14.31" y1="16" x2="2.83" y2="16"></line> <line x1="16.62" y1="12" x2="10.88" y2="21.94"></line> </svg> </div> <div> <div class="course-title">JavaScript & Modern Frameworks</div> <div class="course-info">8 modules • 32% complete</div> </div> <div class="completion-badge in-progress"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <polyline points="12 6 12 12 16 14"></polyline> </svg> In Progress </div> <svg class="toggle-arrow" 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"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </div> <ul class="module-list"> <!-- Module 1 --> <li class="module-item"> <div class="module-header" data-module="3"> <div class="module-icon" style="background-color: var(--quinary);"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="4 17 10 11 4 5"></polyline> <line x1="12" y1="19" x2="20" y2="19"></line> </svg> </div> <div class="module-title">JavaScript Essentials</div> <div class="completion-badge completed"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" 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> Completed </div> <svg class="toggle-arrow" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </div> <ul class="lesson-list"> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> </svg> </div> <div class="lesson-title">Variables, Data Types & Operators</div> <div class="lesson-duration">20 min</div> </li> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> </svg> </div> <div class="lesson-title">Functions & Scopes</div> <div class="lesson-duration">24 min</div> </li> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path> <polyline points="14 2 14 8 20 8"></polyline> </svg> </div> <div class="lesson-title">DOM Manipulation</div> <div class="lesson-duration">28 min</div> </li> </ul> </li> <!-- Module 2 --> <li class="module-item"> <div class="module-header" data-module="4"> <div class="module-icon" style="background-color: var(--primary);"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 10h-4v4h4v-4z"></path> <path d="M10 10H6v4h4v-4z"></path> <path d="M18 3H6l-6 9 6 9h12l6-9-6-9z"></path> </svg> </div> <div class="module-title">React Fundamentals</div> <div class="completion-badge not-started"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="8" x2="12" y2="16"></line> <line x1="8" y1="12" x2="16" y2="12"></line> </svg> Not Started </div> <svg class="toggle-arrow" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </div> <ul class="lesson-list"> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> </svg> </div> <div class="lesson-title">Components & Props</div> <div class="lesson-duration">26 min</div> </li> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> </svg> </div> <div class="lesson-title">State & Lifecycle</div> <div class="lesson-duration">30 min</div> </li> <li class="lesson-item"> <div class="lesson-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path> <polyline points="14 2 14 8 20 8"></polyline> </svg> </div> <div class="lesson-title">Hooks & Context API</div> <div class="lesson-duration">34 min</div> </li> </ul> </li> </ul> </li> <!-- Course 3 --> <li class="course-item"> <div class="course-header" data-course="3"> <div class="course-icon" style="background-color: var(--secondary);"> <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="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path> </svg> </div> <div> <div class="course-title">Web Security & Best Practices</div> <div class="course-info">6 modules • 0% complete</div> </div> <div class="completion-badge not-started"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="8" x2="12" y2="16"></line> <line x1="8" y1="12" x2="16" y2="12"></line> </svg> Not Started </div> <svg class="toggle-arrow" xmlns="http://www.w3.org/2000/svg" width="16"
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Knowledge Base Hierarchy</title> <style> :root { --color-bg: #f8f9fc; --color-primary: #4f6ef7; --color-secondary: #e2e8ff; --color-text: #2c3e50; --color-light-text: #6c7a89; --color-border: #d8e2f4; --color-hover: #edf2ff; --color-active: #dfe6ff; --shadow-sm: 0 2px 10px rgba(79, 110, 247, 0.08); --shadow-md: 0 4px 20px rgba(79, 110, 247, 0.15); --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, 'Segoe UI', Roboto, sans-serif; } body { background-color: var(--color-bg); color: var(--color-text); display: flex; flex-direction: column; height: 100vh; padding: 20px; max-width: 700px; margin: 0 auto; overflow: hidden; } header { margin-bottom: 20px; } h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 8px; color: var(--color-text); } p.subtitle { color: var(--color-light-text); font-size: 0.9rem; margin-bottom: 20px; } .search-container { position: relative; margin-bottom: 20px; } .search-container input { width: 100%; padding: 12px 16px 12px 40px; border: 1px solid var(--color-border); border-radius: 8px; background: white; font-size: 0.9rem; color: var(--color-text); transition: var(--transition); box-shadow: var(--shadow-sm); } .search-container input:focus { outline: none; border-color: var(--color-primary); box-shadow: var(--shadow-md); } .search-container svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--color-light-text); } .knowledge-container { display: flex; gap: 20px; height: calc(100vh - 160px); max-height: 600px; overflow: hidden; } .tree-view { flex: 1; overflow-y: auto; background: white; border-radius: 12px; padding: 16px; box-shadow: var(--shadow-sm); max-width: 300px; } .content-view { flex: 2; overflow-y: auto; background: white; border-radius: 12px; padding: 24px; box-shadow: var(--shadow-sm); } .tree-node { position: relative; padding-left: 8px; } .tree-node-content { display: flex; align-items: center; padding: 10px; border-radius: 6px; cursor: pointer; transition: var(--transition); margin-bottom: 2px; } .tree-node-content:hover { background-color: var(--color-hover); } .tree-node-content.active { background-color: var(--color-active); font-weight: 500; color: var(--color-primary); } .tree-node-content .icon { margin-right: 8px; transform: rotate(0deg); transition: transform 0.3s ease; } .tree-node-content .icon.expanded { transform: rotate(90deg); } .tree-node-content .node-text { flex: 1; font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .tree-node-content .badge { background-color: var(--color-secondary); color: var(--color-primary); font-size: 0.7rem; padding: 2px 6px; border-radius: 10px; margin-left: 4px; } .tree-node-children { padding-left: 20px; max-height: 0; overflow: hidden; transition: max-height 0.3s ease-out; } .tree-node-children.expanded { max-height: 1000px; } .content-title { font-size: 1.3rem; font-weight: 600; margin-bottom: 12px; color: var(--color-text); position: relative; display: inline-block; } .content-title::after { content: ''; position: absolute; bottom: -6px; left: 0; width: 40px; height: 3px; background-color: var(--color-primary); border-radius: 2px; } .breadcrumb { display: flex; font-size: 0.8rem; color: var(--color-light-text); margin-bottom: 20px; flex-wrap: wrap; } .breadcrumb span { margin: 0 6px; } .breadcrumb a { color: var(--color-primary); text-decoration: none; transition: var(--transition); } .breadcrumb a:hover { text-decoration: underline; } .content-meta { display: flex; align-items: center; margin-bottom: 24px; font-size: 0.8rem; color: var(--color-light-text); } .content-meta div { display: flex; align-items: center; margin-right: 16px; } .content-meta svg { margin-right: 4px; } .content-text p { line-height: 1.6; margin-bottom: 16px; color: var(--color-text); font-size: 0.95rem; } .content-text h2 { font-size: 1.1rem; margin: 24px 0 12px; color: var(--color-text); } .content-text ul, .content-text ol { margin-bottom: 16px; padding-left: 24px; } .content-text li { margin-bottom: 8px; line-height: 1.5; } .content-text pre { background-color: var(--color-hover); padding: 16px; border-radius: 8px; overflow-x: auto; margin-bottom: 16px; font-family: monospace; font-size: 0.9rem; } .related-topics { margin-top: 30px; padding-top: 20px; border-top: 1px solid var(--color-border); } .related-topics h3 { font-size: 0.9rem; margin-bottom: 12px; color: var(--color-light-text); } .topic-pills { display: flex; flex-wrap: wrap; gap: 8px; } .topic-pill { background-color: var(--color-secondary); color: var(--color-primary); font-size: 0.8rem; padding: 6px 12px; border-radius: 16px; cursor: pointer; transition: var(--transition); } .topic-pill:hover { background-color: var(--color-primary); color: white; transform: translateY(-2px); } .node-highlight { animation: highlight 1s ease; } @keyframes highlight { 0% { background-color: rgba(79, 110, 247, 0.3); } 100% { background-color: transparent; } } @media (max-width: 700px) { .knowledge-container { flex-direction: column; height: auto; } .tree-view { max-width: 100%; max-height: 250px; } .content-view { max-height: 400px; } } </style> </head> <body> <header> <h1>Knowledge Explorer</h1> <p class="subtitle">Navigate through interconnected concepts with ease</p> <div class="search-container"> <svg xmlns="http://www.w3.org/2000/svg" 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> <input type="text" placeholder="Search topics..." id="search-input"> </div> </header> <div class="knowledge-container"> <div class="tree-view" id="tree-view"> <!-- Tree nodes will be generated by JavaScript --> </div> <div class="content-view" id="content-view"> <!-- Content will be populated by JavaScript --> </div> </div> <script> // Knowledge base data structure const knowledgeBase = [ { id: 'prog', name: 'Programming', children: [ { id: 'lang', name: 'Languages', children: [ { id: 'js', name: 'JavaScript', content: { title: 'JavaScript Fundamentals', lastUpdated: '2023-11-10', views: 1243, text: ` <p>JavaScript is a versatile programming language primarily used for web development. It allows you to implement complex features on web pages to make them interactive.</p> <h2>Core Concepts</h2> <p>Understanding these fundamental concepts is essential for mastering JavaScript:</p> <ul> <li><strong>Variables</strong> - Store and manipulate data using let, const, and var</li> <li><strong>Functions</strong> - Reusable blocks of code that perform specific tasks</li> <li><strong>Objects</strong> - Collections of related data and functionality</li> <li><strong>Arrays</strong> - Ordered lists of values with built-in methods</li> </ul> <h2>Example Code</h2> <pre>// Function to calculate factorial function factorial(n) { if (n <= 1) return 1; return n * factorial(n - 1); } console.log(factorial(5)); // Output: 120</pre> `, relatedTopics: ['DOM Manipulation', 'ES6 Features', 'Async JavaScript'] } }, { id: 'py', name: 'Python', content: { title: 'Python Programming', lastUpdated: '2023-10-22', views: 985, text: ` <p>Python is known for its simplicity and readability, making it an excellent language for beginners and experienced developers alike.</p> <h2>Key Features</h2> <ul> <li>Simple, easy-to-learn syntax</li> <li>Dynamic typing and memory management</li> <li>Extensive standard library</li> <li>Support for multiple programming paradigms</li> </ul> <h2>Example Code</h2> <pre># A simple Python function def fibonacci(n): a, b = 0, 1 for _ in range(n): a, b = b, a + b return a # Print the 10th Fibonacci number print(fibonacci(10))</pre> `, relatedTopics: ['Data Science with Python', 'Web Frameworks', 'Machine Learning'] } }, { id: 'rust', name: 'Rust', content: { title: 'Rust Programming Language', lastUpdated: '2023-11-05', views: 512, text: ` <p>Rust is a systems programming language focused on safety, speed, and concurrency without a garbage collector.</p> <h2>Unique Features</h2> <ul> <li>Memory safety without garbage collection</li> <li>Zero-cost abstractions</li> <li>Pattern matching and type inference</li> <li>Trait-based generics</li> </ul> <h2>Example Code</h2> <pre>fn main() { // Using Option to handle potential absence of a value let some_number = Some(5); let absent_number: Option<i32> = None; // Pattern matching with match expression match some_number { Some(n) => println!("Got a number: {}", n), None => println!("No number found"), } }</pre> `, relatedTopics: ['Memory Management', 'Systems Programming', 'WebAssembly'] } } ] }, { id: 'webdev', name: 'Web Development', children: [ { id: 'frontend', name: 'Frontend', content: { title: 'Frontend Web Development', lastUpdated: '2023-11-08', views: 876, text: ` <p>Frontend development focuses on creating the user interface and user experience of a website or web application.</p> <h2>Core Technologies</h2> <ul> <li><strong>HTML</strong> - Structure and content</li> <li><strong>CSS</strong> - Styling and layout</li> <li><strong>JavaScript</strong> - Interactivity and behavior</li> </ul> <h2>Modern Frontend Development</h2> <p>Today's frontend development often involves frameworks like React, Vue, or Angular, build tools like Webpack or Vite, and CSS preprocessors like Sass or Less.</p> <h2>Responsive Design Principles</h2> <ul> <li>Fluid grids</li> <li>Flexible images</li> <li>Media queries</li> <li>Mobile-first approach</li> </ul> `, relatedTopics: ['CSS Frameworks', 'JavaScript Frameworks', 'Web Performance'] } }, { id: 'backend', name: 'Backend', content: { title: 'Backend Development', lastUpdated: '2023-10-19', views: 723, text: ` <p>Backend development involves building the server-side logic, databases, and APIs that power web applications.</p> <h2>Key Components</h2> <ul> <li><strong>Server</strong> - Handles HTTP requests and responses</li> <li><strong>Database</strong> - Stores and retrieves application data</li> <li><strong>API</strong> - Enables communication between frontend and backend</li> <li><strong>Authentication</strong> - Verifies user identity and permissions</li> </ul> <h2>Common Technologies</h2> <p>Backend developers work with server-side languages like Node.js, Python, Ruby, Java, or PHP, and databases like PostgreSQL, MySQL, MongoDB, or Redis.</p> <h2>API Design Principles</h2> <ul> <li>RESTful architecture</li> <li>Clear endpoint naming</li> <li>Proper HTTP method usage</li> <li>Consistent error handling</li> </ul> `, relatedTopics: ['Database Design', 'API Architecture', 'Server Management'] } } ] } ] }, { id: 'design', name: 'Design', children: [ { id: 'ui', name: 'UI Design', content: { title: 'User Interface Design', lastUpdated: '2023-11-01', views: 654, text: ` <p>User Interface (UI) design focuses on anticipating user needs and creating interfaces that are easy to use and visually appealing.</p> <h2>Key Principles</h2> <ul> <li><strong>Clarity</strong> - Eliminate ambiguity</li> <li><strong>Flexibility</strong> - Accommodate a range of users</li> <li><strong>Familiarity</strong> - Use recognizable patterns</li> <li><strong>Efficiency</strong> - Minimize steps and cognitive load</li> </ul> <h2>Design Elements</h2> <p>UI design involves working with typography, color theory, layout principles, iconography, and visual hierarchy to create cohesive interfaces.</p> <h2>Design Systems</h2> <p>A design system is a collection of reusable components guided by clear standards. It helps maintain consistency across products and streamlines the design process.</p> `, relatedTopics: ['Color Theory', 'Typography', 'Design Systems'] } }, { id: 'ux', name: 'UX Design', content: { title: 'User Experience Design', lastUpdated: '2023-10-29', views: 732, text: ` <p>User Experience (UX) design is about enhancing user satisfaction by improving the usability, accessibility, and pleasure provided in the interaction with a product.</p> <h2>UX Design Process</h2> <ol> <li><strong>Research</strong> - Understanding users and their needs</li> <li><strong>Analysis</strong> - Defining problems and opportunities</li> <li><strong>Design</strong> - Creating solutions and prototypes</li> <li><strong>Testing</strong> - Validating designs with real users</li> <li><strong>Implementation</strong> - Working with developers to build the solution</li> </ol> <h2>Research Methods</h2> <ul> <li>User interviews</li> <li>Usability testing</li> <li>Surveys and questionnaires</li> <li>Card sorting</li> <li>Analytics analysis</li> </ul> <h2>Deliverables</h2> <p>UX designers create user personas, journey maps, wireframes, prototypes, and site maps to communicate their design decisions.</p> `, relatedTopics: ['User Research', 'Prototyping', 'Usability Testing'] } }, { id: 'graphic', name: 'Graphic Design', children: [ { id: 'typography', name: 'Typography', content: { title: 'Typography in Design', lastUpdated: '2023-09-15', views: 543, text: ` <p>Typography is the art and technique of arranging type to make written language legible, readable, and appealing when displayed.</p> <h2>Type Classification</h2> <ul> <li><strong>Serif</strong> - Have small lines at the ends of characters (e.g., Times New Roman)</li> <li><strong>Sans-serif</strong> - Clean, modern typefaces without serifs (e.g., Helvetica)</li> <li><strong>Display</strong> - Decorative, attention-grabbing fonts for headlines</li> <li><strong>Script</strong> - Mimic handwriting or calligraphy</li> <li><strong>Monospace</strong> - Characters occupy the same width (e.g., Courier)</li> </ul> <h2>Key Typography Terms</h2> <ul> <li><strong>Leading</strong> - The vertical space between lines of text</li> <li><strong>Kerning</strong> - The spacing between individual characters</li> <li><strong>Tracking</strong> - Overall letter spacing in a word or phrase</li> <li><strong>Hierarchy</strong> - Visual organization of text by importance</li> </ul> <h2>Typography for Web</h2> <p>Web typography considerations include readability on screens, font loading performance, responsive sizing with rem/em units, and font fallbacks for cross-platform compatibility.</p> `, relatedTopics: ['Font Pairing', 'Readability', 'Type Hierarchy'] } }, { id: 'color', name: 'Color Theory', content: { title: 'Color Theory Fundamentals', lastUpdated: '2023-10-05', views: 621, text: ` <p>Color theory is the practical guidance for color mixing and the visual effects of color combinations.</p> <h2>Color Properties</h2> <ul> <li><strong>Hue</strong> - The pure color itself (red, blue, etc.)</li> <li><strong>Saturation</strong> - The intensity or purity of a color</li> <li><strong>Value</strong> - The lightness or darkness of a color</li> </ul> <h2>Color Harmonies</h2> <ul> <li><strong>Complementary</strong> - Colors opposite on the color wheel</li> <li><strong>Analogous</strong> - Colors adjacent on the color wheel</li> <li><strong>Triadic</strong> - Three colors equally spaced on the color wheel</li> <li><strong>Monochromatic</strong> - Different shades of a single color</li> </ul> <h2>Color Psychology</h2> <p>Colors evoke emotional responses and cultural associations. For example, blue often conveys trust and stability, while red can suggest excitement or urgency.</p> <h2>Accessible Color Use</h2> <p>Ensure sufficient contrast between text and background colors to maintain readability for all users, including those with visual impairments.</p> `, relatedTopics: ['Color Systems', 'Accessible Design', 'Brand Colors'] } } ] } ] }, { id: 'ai', name: 'Artificial Intelligence', children: [ { id: 'ml', name: 'Machine Learning', content: { title: 'Machine Learning Fundamentals', lastUpdated: '2023-11-12', views: 947, text: ` <p>Machine Learning (ML) is a subset of artificial intelligence that enables systems to learn and improve from experience without being explicitly programmed.</p> <h2>Types of Machine Learning</h2> <ul> <li><strong>Supervised Learning</strong> - Models learn from labeled training data</li> <li><strong>Unsupervised Learning</strong> - Models identify patterns in unlabeled data</li> <li><strong>Reinforcement Learning</strong> - Models learn through trial and error with rewards/penalties</li> </ul> <h2>Common Algorithms</h2> <ul> <li>Linear and Logistic Regression</li> <li>Decision Trees and Random Forests</li> <li>Support Vector Machines</li> <li>K-means Clustering</li> <li>Neural Networks</li> </ul> <h2>The ML Workflow</h2> <ol> <li>Data collection and preparation</li> <li>Feature engineering and selection</li> <li>Model selection and training</li> <li>Model evaluation and tuning</li> <li>Deployment and monitoring</li> </ol> `, relatedTopics: ['Deep Learning', 'Natural Language Processing', 'Computer Vision'] }, children: [ { id: 'dl', name: 'Deep Learning', content: { title: 'Deep Learning Concepts', lastUpdated: '2023-11-09', views: 782, text: ` <p>Deep Learning is a subfield of machine learning that uses neural networks with multiple layers (deep neural networks) to analyze various forms of data.</p> <h2>Neural Network Architecture</h2> <ul> <li><strong>Input Layer</strong> - Receives raw data</li> <li><strong>Hidden Layers</strong> - Extract and learn features</li> <li><strong>Output Layer</strong> - Produces the prediction or classification</li> </ul> <h2>Common Neural Network Types</h2> <ul> <li><strong>Convolutional Neural Networks (CNNs)</strong> - Excel at image processing</li> <li><strong>Recurrent Neural Networks (RNNs)</strong> - Handle sequential data like text or time series</li> <li><strong>Transformers</strong> - Power modern NLP models like BERT and GPT</li> <li><strong>Generative Adversarial Networks (GANs)</strong> - Generate new content</li> </ul> <h2>Training Deep Neural Networks</h2> <p>Training involves forward propagation (making predictions), calculating loss (measuring errors), and backpropagation (adjusting weights). Optimization algorithms like SGD, Adam, or RMSprop are used to update model parameters.</p> <h2>Challenges</h2> <ul> <li>Requires large amounts of data</li> <li>Computationally expensive</li> <li>Risk of overfitting</li> <li>Model interpretability issues</li> </ul> `, relatedTopics: ['Neural Networks', 'Computer Vision', 'Transfer Learning'] } }, { id: 'nlp', name: 'Natural Language Processing', content: { title: 'Natural Language Processing', lastUpdated: '2023-10-28', views: 614, text: ` <p>Natural Language Processing (NLP) is a field at the intersection of computer science, artificial intelligence, and linguistics that focuses on the interaction between computers and human language.</p> <h2>NLP Tasks</h2> <ul> <li><strong>Text Classification</strong> - Categorizing text (sentiment analysis, topic tagging)</li> <li><strong>Named Entity Recognition</strong> - Identifying entities like people, places, organizations</li> <li><strong>Machine Translation</strong> - Converting text between languages</li> <li><strong>Text Generation</strong> - Creating human-like text</li> <li><strong>Question Answering</strong> - Finding answers in text</li> </ul> <h2>Text Processing Steps</h2> <ol> <li><strong>Tokenization</strong> - Breaking text into words or subwords</li> <li><strong>Normalization</strong> - Converting to lowercase, removing punctuation</li> <li><strong>Stopword removal</strong> - Filtering common words (a, the, is)</li> <li><strong>Stemming/Lemmatization</strong> - Reducing words to base forms</li> </ol> <h2>Modern NLP Models</h2> <p>Transformer-based models like BERT, GPT, and T5 have revolutionized NLP by capturing contextual relationships in text and enabling transfer learning.</p> `, relatedTopics: ['Text Mining', 'Sentiment Analysis', 'Language Models'] } } ] }, { id: 'cv', name: 'Computer Vision', content: { title: 'Computer Vision', lastUpdated: '2023-10-15', views: 573, text: ` <p>Computer Vision is a field of artificial intelligence that trains computers to interpret and understand the visual world. It focuses on extracting meaningful information from digital images and videos.</p> <h2>Core Tasks</h2> <ul> <li><strong>Image Classification</strong> - Categorizing images into classes</li> <li><strong>Object Detection</strong> - Locating and identifying objects in images</li> <li><strong>Semantic Segmentation</strong> - Classifying each pixel in an image</li> <li><strong>Instance Segmentation</strong> - Identifying separate instances of objects</li> <li><strong>Image Generation</strong> - Creating new images</li> </ul> <h2>Key Techniques</h2> <ul> <li><strong>Feature Extraction</strong> - Identifying edges, corners, and textures</li> <li><strong>Convolutional Neural Networks</strong> - Deep learning architecture for visual data</li> <li><strong>Transfer Learning</strong> - Using pre-trained models as starting points</li> </ul> <h2>Applications</h2> <p>Computer vision powers facial recognition, autonomous vehicles, medical image analysis, augmented reality, and industrial quality control systems.</p> `, relatedTopics: ['Image Processing', 'Object Detection', 'Facial Recognition'] } } ] } ]; // Initialize the tree view const treeView = document.getElementById('tree-view'); const contentView = document.getElementById('content-view'); const searchInput = document.getElementById('search-input'); // Build tree nodes recursively function buildTreeNode(node, level = 0) { const nodeElement = document.createElement('div'); nodeElement.className = 'tree-node'; nodeElement.dataset.id = node.id; const nodeContent = document.createElement('div'); nodeContent.className = 'tree-node-content'; nodeContent.setAttribute('role', 'button'); nodeContent.setAttribute('tabindex', '0'); const hasChildren = node.children && node.children.length > 0; // Create chevron icon for expandable nodes const icon = document.createElement('span'); icon.className = 'icon'; icon.innerHTML = hasChildren ? '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 6L15 12L9 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>' : '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 5V19M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="opacity: 0.3"/></svg>'; const nodeText = document.createElement('span'); nodeText.className = 'node-text'; nodeText.textContent = node.name; nodeContent.appendChild(icon); nodeContent.appendChild(nodeText); // Add child count badge if node has children if (hasChildren) { const badge = document.createElement('span'); badge.className = 'badge'; badge.textContent = node.children.length; nodeContent.appendChild(badge); } nodeElement.appendChild(nodeContent); // Create container for children and recursively add child nodes if (hasChildren) { const childrenContainer = document.createElement('div'); childrenContainer.className = 'tree-node-children'; node.children.forEach(childNode => { childrenContainer.appendChild(buildTreeNode(childNode, level + 1)); }); nodeElement.appendChild(childrenContainer); // Add click event to toggle children visibility nodeContent.addEventListener('click', (e) => { e.stopPropagation(); const childrenEl = nodeElement.querySelector('.tree-node-children'); const iconEl = nodeContent.querySelector('.icon'); childrenEl.classList.toggle('expanded'); iconEl.classList.toggle('expanded'); }); // Also trigger on keyboard interaction nodeContent.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); nodeContent.click(); } }); } // Add click event to display content nodeContent.addEventListener('click', (e) => { // Remove active class from all nodes document.querySelectorAll('.tree-node-content').forEach(el => { el.classList.remove('active'); }); // Add active class to clicked node nodeContent.classList.add('active'); // Display content if available if (node.content) { displayContent(node, getNodePath(node.id)); } }); return nodeElement; } // Find a node by ID in the knowledge base function findNodeById(id, nodes = knowledgeBase) { for (const node of nodes) { if (node.id === id) { return node; } if (node.children) { const found = findNodeById(id, node.children); if (found) { return found; } } } return null; } // Get the full path to a node (for breadcrumbs) function getNodePath(id) { const path = []; function findPath(nodeId, nodes = knowledgeBase, currentPath = []) { for (const node of nodes) { const newPath = [...currentPath, { id: node.id, name: node.name }]; if (node.id === nodeId) { path.push(...newPath); return true; } if (node.children && findPath(nodeId, node.children, newPath)) { return true; } } return false;
<html> <head> <style> * { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Segoe UI', 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif; } :root { --primary: #0B132B; --secondary: #1C2541; --accent-blue: #3A506B; --accent-teal: #5BC0BE; --accent-cyan: #6FFFE9; --text-light: #E9ECEF; --text-dark: #212529; --shadow: 0 4px 6px rgba(0, 0, 0, 0.1); --glow: 0 0 15px rgba(91, 192, 190, 0.5); } body { background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); color: var(--text-light); display: flex; flex-direction: column; height: 100vh; padding: 20px; overflow: hidden; } .container { width: 100%; max-width: 700px; height: 700px; margin: 0 auto; display: flex; flex-direction: column; background-color: rgba(28, 37, 65, 0.7); backdrop-filter: blur(10px); border-radius: 16px; box-shadow: var(--shadow); border: 1px solid rgba(111, 255, 233, 0.2); overflow: hidden; } .header { padding: 20px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid rgba(111, 255, 233, 0.2); } .header h1 { font-size: 24px; font-weight: 500; letter-spacing: 0.5px; color: var(--accent-cyan); } .search-container { position: relative; width: 50%; } .search { width: 100%; padding: 10px 15px 10px 40px; background: rgba(58, 80, 107, 0.3); border: 1px solid rgba(111, 255, 233, 0.3); border-radius: 24px; color: var(--text-light); outline: none; transition: all 0.3s ease; } .search:focus { border-color: var(--accent-teal); box-shadow: var(--glow); } .search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--accent-teal); } .stats { display: flex; justify-content: space-between; padding: 15px 20px; background: rgba(58, 80, 107, 0.3); } .stat { text-align: center; } .stat-value { font-size: 24px; font-weight: bold; color: var(--accent-cyan); } .stat-label { font-size: 12px; color: var(--text-light); opacity: 0.8; } .main { display: flex; flex: 1; overflow: hidden; } .tree-container { flex: 1; overflow-y: auto; padding: 15px; } .device-details { width: 250px; padding: 20px; background: rgba(11, 19, 43, 0.8); border-left: 1px solid rgba(111, 255, 233, 0.2); overflow-y: auto; transform: translateX(100%); transition: transform 0.3s ease-in-out; } .device-details.active { transform: translateX(0); } .tree-node { margin-bottom: 10px; } .tree-header { display: flex; align-items: center; padding: 10px; cursor: pointer; border-radius: 8px; transition: all 0.2s ease; background: rgba(58, 80, 107, 0.2); } .tree-header:hover { background: rgba(58, 80, 107, 0.4); } .tree-header.expanded { background: rgba(91, 192, 190, 0.2); margin-bottom: 5px; } .toggle-icon { margin-right: 10px; font-size: 18px; color: var(--accent-teal); transition: transform 0.3s ease; } .expanded .toggle-icon { transform: rotate(90deg); } .node-icon { margin-right: 10px; font-size: 18px; color: var(--accent-cyan); } .node-name { flex: 1; font-weight: 500; } .node-count { background: rgba(91, 192, 190, 0.2); color: var(--accent-cyan); padding: 2px 8px; border-radius: 12px; font-size: 12px; } .tree-content { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; padding-left: 30px; } .expanded + .tree-content { max-height: 500px; } .device-item { display: flex; align-items: center; padding: 8px 10px; margin: 5px 0; border-radius: 8px; cursor: pointer; background: rgba(58, 80, 107, 0.1); transition: all 0.2s ease; } .device-item:hover { background: rgba(58, 80, 107, 0.3); } .device-item.active { background: rgba(91, 192, 190, 0.3); border-left: 3px solid var(--accent-cyan); } .device-icon { color: var(--accent-teal); margin-right: 10px; font-size: 16px; } .device-name { flex: 1; font-size: 14px; } .device-status { width: 10px; height: 10px; border-radius: 50%; margin-left: 10px; } .status-online { background-color: #4CAF50; box-shadow: 0 0 5px #4CAF50; } .status-offline { background-color: #F44336; } .status-warning { background-color: #FFC107; box-shadow: 0 0 5px #FFC107; } .device-detail-header { margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid rgba(111, 255, 233, 0.2); } .device-detail-name { font-size: 18px; font-weight: 500; color: var(--accent-cyan); margin-bottom: 5px; } .device-detail-location { font-size: 14px; opacity: 0.8; } .device-detail-status { display: flex; align-items: center; margin-bottom: 5px; } .status-indicator { width: 12px; height: 12px; border-radius: 50%; margin-right: 10px; } .device-metrics { margin-top: 20px; } .metric { margin-bottom: 15px; } .metric-header { display: flex; justify-content: space-between; margin-bottom: 5px; font-size: 14px; } .metric-name { color: var(--text-light); } .metric-value { color: var(--accent-cyan); font-weight: 500; } .metric-bar { height: 6px; background: rgba(58, 80, 107, 0.5); border-radius: 3px; overflow: hidden; } .metric-fill { height: 100%; background: linear-gradient(90deg, var(--accent-teal) 0%, var(--accent-cyan) 100%); border-radius: 3px; transition: width 0.3s ease; } .device-actions { display: flex; justify-content: space-between; margin-top: 30px; } .action-btn { background: rgba(58, 80, 107, 0.5); border: 1px solid rgba(111, 255, 233, 0.3); border-radius: 8px; padding: 8px 15px; color: var(--text-light); font-size: 14px; cursor: pointer; transition: all 0.2s ease; } .action-btn:hover { background: rgba(91, 192, 190, 0.3); border-color: var(--accent-cyan); } .action-btn.primary { background: rgba(91, 192, 190, 0.3); border-color: var(--accent-teal); } .action-btn.primary:hover { background: rgba(91, 192, 190, 0.5); } /* Custom scrollbar */ ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-track { background: rgba(58, 80, 107, 0.1); } ::-webkit-scrollbar-thumb { background: rgba(91, 192, 190, 0.5); border-radius: 3px; } ::-webkit-scrollbar-thumb:hover { background: rgba(111, 255, 233, 0.5); } /* Responsive design */ @media (max-width: 700px) { .container { border-radius: 0; height: 100%; } .header { flex-direction: column; align-items: flex-start; } .search-container { width: 100%; margin-top: 10px; } .stats { overflow-x: auto; } .device-details { position: absolute; top: 0; right: 0; height: 100%; width: 100%; max-width: 100%; z-index: 10; } .device-details.active { transform: translateX(0); } } /* Pulse animation for active devices */ @keyframes pulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.05); opacity: 0.8; } 100% { transform: scale(1); opacity: 1; } } .pulse { animation: pulse 2s infinite; } /* Floating notification */ .notification { position: absolute; bottom: 20px; right: 20px; background: rgba(91, 192, 190, 0.8); color: var(--text-dark); padding: 12px 20px; border-radius: 8px; box-shadow: var(--shadow); transform: translateY(100px); opacity: 0; transition: all 0.3s ease; } .notification.show { transform: translateY(0); opacity: 1; } .close-details { position: absolute; top: 15px; right: 15px; background: none; border: none; color: var(--accent-teal); cursor: pointer; font-size: 18px; display: none; } @media (max-width: 700px) { .close-details { display: block; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>NexusHub IoT Control Center</h1> <div class="search-container"> <span class="search-icon">🔍</span> <input type="text" class="search" placeholder="Search devices..." id="search-input"> </div> </div> <div class="stats"> <div class="stat"> <div class="stat-value">42</div> <div class="stat-label">TOTAL DEVICES</div> </div> <div class="stat"> <div class="stat-value">38</div> <div class="stat-label">ONLINE</div> </div> <div class="stat"> <div class="stat-value">3</div> <div class="stat-label">WARNINGS</div> </div> <div class="stat"> <div class="stat-value">1</div> <div class="stat-label">OFFLINE</div> </div> </div> <div class="main"> <div class="tree-container" id="tree-container"> <!-- Tree content will be populated by JavaScript --> </div> <div class="device-details" id="device-details"> <button class="close-details" id="close-details">✖</button> <div class="device-detail-header"> <div class="device-detail-name">Select a Device</div> <div class="device-detail-location">No device selected</div> <div class="device-detail-status"> <div class="status-indicator"></div> <span>Status: Unknown</span> </div> </div> <div class="device-metrics"> <div class="metric"> <div class="metric-header"> <span class="metric-name">CPU Usage</span> <span class="metric-value">0%</span> </div> <div class="metric-bar"> <div class="metric-fill" style="width: 0%"></div> </div> </div> <div class="metric"> <div class="metric-header"> <span class="metric-name">Memory</span> <span class="metric-value">0 MB</span> </div> <div class="metric-bar"> <div class="metric-fill" style="width: 0%"></div> </div> </div> <div class="metric"> <div class="metric-header"> <span class="metric-name">Temperature</span> <span class="metric-value">0°C</span> </div> <div class="metric-bar"> <div class="metric-fill" style="width: 0%"></div> </div> </div> <div class="metric"> <div class="metric-header"> <span class="metric-name">Battery</span> <span class="metric-value">0%</span> </div> <div class="metric-bar"> <div class="metric-fill" style="width: 0%"></div> </div> </div> </div> <div class="device-actions"> <button class="action-btn">Restart</button> <button class="action-btn primary">Configure</button> </div> </div> </div> </div> <div class="notification" id="notification">Device status updated</div> <script> // IoT device data with realistic types and locations const iotDevices = { "Living Areas": { "Living Room": [ { id: 1, name: "Smart TV", type: "entertainment", status: "online", metrics: { cpu: 32, memory: 512, temp: 38, battery: 'N/A' } }, { id: 2, name: "Ambient Lighting", type: "lighting", status: "online", metrics: { cpu: 12, memory: 64, temp: 29, battery: 'N/A' } }, { id: 3, name: "Air Purifier", type: "climate", status: "warning", metrics: { cpu: 45, memory: 128, temp: 42, battery: 'N/A' } }, { id: 4, name: "Motion Sensor", type: "security", status: "online", metrics: { cpu: 5, memory: 32, temp: 25, battery: 82 } } ], "Kitchen": [ { id: 5, name: "Smart Refrigerator", type: "appliance", status: "online", metrics: { cpu: 28, memory: 256, temp: 32, battery: 'N/A' } }, { id: 6, name: "Coffee Maker", type: "appliance", status: "online", metrics: { cpu: 15, memory: 128, temp: 55, battery: 'N/A' } }, { id: 7, name: "Smoke Detector", type: "safety", status: "online", metrics: { cpu: 8, memory: 64, temp: 29, battery: 95 } } ], "Dining Room": [ { id: 8, name: "Chandelier Control", type: "lighting", status: "online", metrics: { cpu: 10, memory: 64, temp: 30, battery: 'N/A' } }, { id: 9, name: "Ambient Speaker", type: "entertainment", status: "online", metrics: { cpu: 25, memory: 128, temp: 35, battery: 'N/A' } } ] }, "Bedrooms": { "Master Bedroom": [ { id: 10, name: "Smart Blinds", type: "automation", status: "online", metrics: { cpu: 12, memory: 64, temp: 28, battery: 78 } }, { id: 11, name: "Sleep Tracker", type: "health", status: "online", metrics: { cpu: 22, memory: 128, temp: 31, battery: 65 } }, { id: 12, name: "Ambient Noise Machine", type: "comfort", status: "online", metrics: { cpu: 18, memory: 96, temp: 33, battery: 'N/A' } } ], "Guest Bedroom": [ { id: 13, name: "Smart Lamp", type: "lighting", status: "online", metrics: { cpu: 8, memory: 32, temp: 27, battery: 'N/A' } }, { id: 14, name: "Temperature Sensor", type: "climate", status: "warning", metrics: { cpu: 6, memory: 32, temp: 48, battery: 45 } } ], "Kid's Room": [ { id: 15, name: "Night Light", type: "lighting", status: "online", metrics: { cpu: 5, memory: 16, temp: 25, battery: 'N/A' } }, { id: 16, name: "Baby Monitor", type: "security", status: "online", metrics: { cpu: 35, memory: 256, temp: 38, battery: 87 } } ] }, "Utility Areas": { "Garage": [ { id: 17, name: "Door Opener", type: "automation", status: "online", metrics: { cpu: 15, memory: 64, temp: 32, battery: 'N/A' } }, { id: 18, name: "EV Charger", type: "energy", status: "online", metrics: { cpu: 30, memory: 128, temp: 40, battery: 'N/A' } }, { id: 19, name: "Security Camera", type: "security", status: "offline", metrics: { cpu: 0, memory: 0, temp: 0, battery: 0 } } ], "Basement": [ { id: 20, name: "Water Leak Sensor", type: "safety", status: "online", metrics: { cpu: 4, memory: 16, temp: 22, battery: 92 } }, { id: 21, name: "Dehumidifier", type: "climate", status: "online", metrics: { cpu: 25, memory: 128, temp: 35, battery: 'N/A' } } ], "Laundry Room": [ { id: 22, name: "Smart Washer", type: "appliance", status: "online", metrics: { cpu: 28, memory: 256, temp: 38, battery: 'N/A' } }, { id: 23, name: "Smart Dryer", type: "appliance", status: "warning", metrics: { cpu: 65, memory: 256, temp: 62, battery: 'N/A' } } ] }, "Outdoor": { "Front Yard": [ { id: 24, name: "Doorbell Camera", type: "security", status: "online", metrics: { cpu: 38, memory: 256, temp: 32, battery: 78 } }, { id: 25, name: "Landscape Lighting", type: "lighting", status: "online", metrics: { cpu: 10, memory: 64, temp: 28, battery: 'N/A' } } ], "Backyard": [ { id: 26, name: "Weather Station", type: "environmental", status: "online", metrics: { cpu: 22, memory: 128, temp: 30, battery: 85 } }, { id: 27, name: "Irrigation Controller", type: "automation", status: "online", metrics: { cpu: 18, memory: 96, temp: 31, battery: 'N/A' } }, { id: 28, name: "Pool Monitor", type: "environmental", status: "online", metrics: { cpu: 25, memory: 128, temp: 33, battery: 90 } } ] } }; // Icons for different types of devices const typeIcons = { 'entertainment': '🎮', 'lighting': '💡', 'climate': '🌡️', 'security': '🔒', 'appliance': '🔌', 'safety': '⚠️', 'automation': '⚙️', 'health': '❤️', 'comfort': '🛋️', 'energy': '⚡', 'environmental': '🌱' }; // Location icons const locationIcons = { 'Living Areas': '🏠', 'Bedrooms': '🛌', 'Utility Areas': '🔧', 'Outdoor': '🌳' }; // DOM elements const treeContainer = document.getElementById('tree-container'); const deviceDetails = document.getElementById('device-details'); const searchInput = document.getElementById('search-input'); const notification = document.getElementById('notification'); const closeDetailsBtn = document.getElementById('close-details'); // Build the tree structure function buildTree() { treeContainer.innerHTML = ''; for (const [category, locations] of Object.entries(iotDevices)) { const categoryNode = document.createElement('div'); categoryNode.className = 'tree-node'; const categoryHeader = document.createElement('div'); categoryHeader.className = 'tree-header'; categoryHeader.innerHTML = ` <span class="toggle-icon">▶</span> <span class="node-icon">${locationIcons[category]}</span> <span class="node-name">${category}</span> <span class="node-count">${countDevicesInCategory(locations)}</span> `; const categoryContent = document.createElement('div'); categoryContent.className = 'tree-content'; for (const [location, devices] of Object.entries(locations)) { const locationNode = document.createElement('div'); locationNode.className = 'tree-node'; const locationHeader = document.createElement('div'); locationHeader.className = 'tree-header'; locationHeader.innerHTML = ` <span class="toggle-icon">▶</span> <span class="node-icon">📍</span> <span class="node-name">${location}</span> <span class="node-count">${devices.length}</span> `; const locationContent = document.createElement('div'); locationContent.className = 'tree-content'; for (const device of devices) { const deviceItem = document.createElement('div'); deviceItem.className = `device-item ${device.status === 'warning' ? 'pulse' : ''}`; deviceItem.dataset.id = device.id; deviceItem.innerHTML = ` <span class="device-icon">${typeIcons[device.type] || '📱'}</span> <span class="device-name">${device.name}</span> <span class="device-status status-${device.status}"></span> `; deviceItem.addEventListener('click', () => showDeviceDetails(device, category, location)); locationContent.appendChild(deviceItem); } locationNode.appendChild(locationHeader); locationNode.appendChild(locationContent); categoryContent.appendChild(locationNode); // Event listener for location header locationHeader.addEventListener('click', function() { this.classList.toggle('expanded'); }); } categoryNode.appendChild(categoryHeader); categoryNode.appendChild(categoryContent); treeContainer.appendChild(categoryNode); // Event listener for category header categoryHeader.addEventListener('click', function() { this.classList.toggle('expanded'); }); } } // Count devices in a category function countDevicesInCategory(locations) { let count = 0; for (const devices of Object.values(locations)) { count += devices.length; } return count; } // Show device details function showDeviceDetails(device, category, location) { // Deactivate any previously active device const activeDevice = document.querySelector('.device-item.active'); if (activeDevice) { activeDevice.classList.remove('active'); } // Activate the selected device const deviceItem = document.querySelector(`.device-item[data-id="${device.id}"]`); if (deviceItem) { deviceItem.classList.add('active'); } // Update details panel let statusClass = ''; let statusText = ''; switch(device.status) { case 'online': statusClass = 'status-online'; statusText = 'Online'; break; case 'offline': statusClass = 'status-offline'; statusText = 'Offline'; break; case 'warning': statusClass = 'status-warning'; statusText = 'Warning'; break; } deviceDetails.querySelector('.device-detail-name').textContent = device.name; deviceDetails.querySelector('.device-detail-location').textContent = `${category} > ${location}`; const statusIndicator = deviceDetails.querySelector('.status-indicator'); statusIndicator.className = 'status-indicator ' + statusClass; deviceDetails.querySelector('.device-detail-status span').textContent = `Status: ${statusText}`; // Update metrics updateMetric('CPU Usage', device.metrics.cpu + '%', device.metrics.cpu); updateMetric('Memory', device.metrics.memory + ' MB', device.metrics.memory / 10); updateMetric('Temperature', device.metrics.temp + '°C', (device.metrics.temp / 100) * 100); if (device.metrics.battery === 'N/A') { updateMetric('Battery', 'N/A', 0); } else { updateMetric('Battery', device.metrics.battery + '%', device.metrics.battery); } // Show details panel deviceDetails.classList.add('active'); } // Update a metric in the details panel function updateMetric(name, value, percentage) { const metrics = deviceDetails.querySelectorAll('.metric'); for (const metric of metrics) { const metricName = metric.querySelector('.metric-name').textContent; if (metricName === name) { metric.querySelector('.metric-value').textContent = value; metric.querySelector('.metric-fill').style.width = `${percentage}%`; } } } // Search functionality searchInput.addEventListener('input', function(e) { const searchTerm = e.target.value.toLowerCase(); filterDevices(searchTerm); }); function filterDevices(searchTerm) { const deviceItems = document.querySelectorAll('.device-item'); let hasResults = false; deviceItems.forEach(item => { const deviceName = item.querySelector('.device-name').textContent.toLowerCase(); const shouldShow = deviceName.includes(searchTerm); item.style.display = shouldShow ? 'flex' : 'none'; if (shouldShow) { hasResults = true; // Make sure parent containers are expanded let parent = item.parentElement; while (parent && !parent.classList.contains('tree-container')) { if (parent.classList.contains('tree-content')) { const header = parent.previousElementSibling; if (header && header.classList.contains('tree-header')) { header.classList.add('expanded'); } } parent = parent.parentElement; } } }); if (!hasResults && searchTerm) { showNotification('No devices found matching your search'); } } // Close details panel (mobile) closeDetailsBtn.addEventListener('click', function() { deviceDetails.classList.remove('active'); const activeDevice = document.querySelector('.device-item.active'); if (activeDevice) { activeDevice.classList.remove('active'); } }); // Show notification function showNotification(message) { notification.textContent = message; notification.classList.add('show'); setTimeout(() => { notification.classList.remove('show'); }, 3000); } // Initialize the tree buildTree(); // Simulate device status changes setInterval(() => { const devices = Object.values(iotDevices).flatMap(locations => Object.values(locations).flatMap(devices => devices) ); const randomDevice = devices[Math.floor(Math.random() * devices.length)]; const statuses = ['online', 'warning', 'offline']; const prevStatus = randomDevice.status; const newStatus = statuses[Math.floor(Math.random() * 3)]; if (prevStatus !== newStatus && Math.random() > 0.7) { randomDevice.status = newStatus; // Update in the tree const deviceItem = document.querySelector(`.device-item[data-id="${randomDevice.id}"]`); if (deviceItem) { const statusIndicator = deviceItem.querySelector('.device-status'); statusIndicator.className = `device-status status-${newStatus}`; if (newStatus === 'warning') { deviceItem.classList.add('pulse'); } else { deviceItem.classList.remove('pulse'); } // Update in details panel if this device is selected if (deviceItem.classList.contains('active')) { const statusIndicator = deviceDetails.querySelector('.status-indicator'); statusIndicator.className = `status-indicator status-${newStatus}`; let statusText = ''; switch(newStatus) { case 'online': statusText = 'Online'; break; case 'offline': statusText = 'Offline'; break; case 'warning': statusText = 'Warning'; break; } deviceDetails.querySelector('.device-detail-status span').textContent = `Status: ${statusText}`; } showNotification(`${randomDevice.name} status changed to ${newStatus}`); } } // Randomize metrics for online devices if (randomDevice.status !== 'offline') { const variation = Math.floor(Math.random() * 11) - 5; // -5 to +5 randomDevice.metrics.cpu = Math.max(5, Math.min(95, randomDevice.metrics.cpu + variation)); randomDevice.metrics.temp = Math.max(20, Math.min(70, randomDevice.metrics.temp + (variation / 2))); if (randomDevice.metrics.battery !== 'N/A') { randomDevice.metrics.battery = Math.max(0, Math.min(100, randomDevice.metrics.battery - Math.random())); } // Update metrics if device is selected const deviceItem = document.querySelector(`.device-item[data-id="${randomDevice.id}"]`); if (deviceItem && deviceItem.classList.contains('active')) { updateMetric('CPU Usage', randomDevice.metrics.cpu + '%', randomDevice.metrics.cpu); updateMetric('Temperature', randomDevice.metrics.temp + '°C', (randomDevice.metrics.temp / 100) * 100); if (randomDevice.metrics.battery !== 'N/A') { updateMetric('Battery', Math.floor(randomDevice.metrics.battery) + '%', randomDevice.metrics.battery); } } } }, 5000); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Project Management Breakdown Structure</title> <style> :root { --primary-color: #2a7de1; --primary-light: #eaf1fd; --primary-dark: #1c5db0; --success-color: #26c485; --warning-color: #f3b73e; --danger-color: #e74d3d; --neutral-color: #64748b; --neutral-light: #f8fafc; --neutral-dark: #334155; --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05); --shadow-md: 0 4px 8px rgba(0, 0, 0, 0.1); --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1); --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --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: var(--neutral-light); color: var(--neutral-dark); width: 100%; height: 100vh; display: flex; flex-direction: column; overflow: hidden; } .container { max-width: 700px; width: 100%; height: 700px; margin: 0 auto; padding: 16px; display: flex; flex-direction: column; overflow: hidden; background-color: white; border-radius: var(--radius-lg); box-shadow: var(--shadow-md); } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid #e2e8f0; } .header h1 { font-size: 1.5rem; font-weight: 700; color: var(--neutral-dark); } .toolbar { display: flex; gap: 8px; } .btn { padding: 8px 12px; border-radius: var(--radius-sm); font-weight: 500; font-size: 0.875rem; cursor: pointer; transition: var(--transition); border: none; display: flex; align-items: center; gap: 6px; } .btn-primary { background-color: var(--primary-color); color: white; } .btn-primary:hover { background-color: var(--primary-dark); } .btn-outline { background-color: transparent; border: 1px solid var(--neutral-color); color: var(--neutral-color); } .btn-outline:hover { background-color: var(--neutral-light); } .search-bar { display: flex; align-items: center; margin-bottom: 16px; position: relative; } .search-bar input { width: 100%; padding: 10px 12px 10px 36px; border-radius: var(--radius-md); border: 1px solid #e2e8f0; font-size: 0.875rem; transition: var(--transition); } .search-bar input:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 3px rgba(42, 125, 225, 0.1); } .search-icon { position: absolute; left: 12px; color: var(--neutral-color); } .project-tree { flex-grow: 1; overflow-y: auto; padding-right: 8px; } .project-tree::-webkit-scrollbar { width: 6px; } .project-tree::-webkit-scrollbar-track { background: #f1f5f9; border-radius: 10px; } .project-tree::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 10px; } .project-tree::-webkit-scrollbar-thumb:hover { background: #94a3b8; } .tree-node { margin-bottom: 8px; } .node-content { display: flex; align-items: center; padding: 10px 12px; border-radius: var(--radius-md); background-color: white; border: 1px solid #e2e8f0; transition: var(--transition); cursor: grab; position: relative; overflow: hidden; } .node-content.milestone { border-left: 4px solid var(--success-color); } .node-content.at-risk { border-left: 4px solid var(--danger-color); } .node-content.warning { border-left: 4px solid var(--warning-color); } .node-content:hover { box-shadow: var(--shadow-sm); background-color: #fcfcfd; } .node-content.dragging { box-shadow: var(--shadow-md); opacity: 0.7; cursor: grabbing; } .node-content.drop-target { border: 2px dashed var(--primary-color); background-color: var(--primary-light); } .expand-icon { margin-right: 8px; cursor: pointer; transition: transform 0.2s ease; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; border-radius: 50%; } .expand-icon:hover { background-color: var(--neutral-light); } .task-type { width: 24px; height: 24px; border-radius: 4px; margin-right: 10px; display: flex; align-items: center; justify-content: center; font-size: 14px; color: white; } .task-type.feature { background-color: var(--primary-color); } .task-type.bug { background-color: var(--danger-color); } .task-type.task { background-color: var(--neutral-color); } .task-type.milestone { background-color: var(--success-color); } .node-details { flex-grow: 1; } .node-title { font-weight: 500; margin-bottom: 2px; font-size: 0.9rem; } .node-meta { display: flex; align-items: center; gap: 8px; font-size: 0.75rem; color: var(--neutral-color); } .node-meta span { display: flex; align-items: center; gap: 4px; } .progress-bar { height: 4px; width: 100%; background-color: #e2e8f0; border-radius: 2px; margin-top: 6px; overflow: hidden; } .progress-fill { height: 100%; background-color: var(--primary-color); transition: width 0.5s ease; } .node-actions { display: flex; align-items: center; gap: 6px; opacity: 0; transition: opacity 0.2s ease; } .node-content:hover .node-actions { opacity: 1; } .action-btn { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--neutral-color); transition: var(--transition); background: transparent; border: none; } .action-btn:hover { background-color: var(--neutral-light); color: var(--neutral-dark); } .children { margin-left: 24px; max-height: 0; overflow: hidden; transition: max-height 0.3s ease; } .children.expanded { max-height: 1000px; } .task-pill { padding: 2px 6px; border-radius: 10px; font-size: 0.7rem; font-weight: 500; } .task-pill.high { background-color: #fecaca; color: #b91c1c; } .task-pill.medium { background-color: #fed7aa; color: #c2410c; } .task-pill.low { background-color: #bfdbfe; color: #1e40af; } .add-task-form { margin-top: 16px; padding: 16px; background-color: var(--primary-light); border-radius: var(--radius-md); display: none; } .add-task-form.active { display: block; animation: slideDown 0.3s ease; } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } .form-group { margin-bottom: 12px; } .form-group label { display: block; margin-bottom: 4px; font-size: 0.875rem; font-weight: 500; } .form-control { width: 100%; padding: 8px 12px; border-radius: var(--radius-sm); border: 1px solid #e2e8f0; font-size: 0.875rem; } .form-control:focus { outline: none; border-color: var(--primary-color); } .form-row { display: flex; gap: 12px; } .form-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; } .node-level-1 .node-content { background-color: #f8fafc; } .node-level-2 .node-content { background-color: #f1f5f9; } .node-level-3 .node-content { background-color: #e2e8f0; } .completion-line { position: absolute; bottom: 0; left: 0; height: 3px; background-color: var(--success-color); transition: width 0.5s ease; } .pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .filter-tags { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; } .filter-tag { padding: 4px 10px; border-radius: 16px; font-size: 0.75rem; font-weight: 500; cursor: pointer; transition: var(--transition); background-color: var(--neutral-light); color: var(--neutral-dark); border: 1px solid transparent; } .filter-tag.active { background-color: var(--primary-light); color: var(--primary-dark); border-color: var(--primary-color); } .filter-tag:hover { background-color: var(--primary-light); } .milestone-indicator { position: absolute; top: 0; right: 0; width: 0; height: 0; border-style: solid; border-width: 0 20px 20px 0; border-color: transparent var(--success-color) transparent transparent; } @media (max-width: 480px) { .header h1 { font-size: 1.2rem; } .toolbar { gap: 4px; } .btn { padding: 6px 8px; font-size: 0.75rem; } .node-content { padding: 8px; } .form-row { flex-direction: column; gap: 8px; } .node-meta { flex-wrap: wrap; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>Product Launch Q4 2023</h1> <div class="toolbar"> <button class="btn btn-outline" id="collapseAll"> <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"><polyline points="4 14 10 14 10 20"></polyline><polyline points="20 10 14 10 14 4"></polyline><line x1="14" y1="10" x2="21" y2="3"></line><line x1="3" y1="21" x2="10" y2="14"></line></svg> Collapse All </button> <button class="btn btn-primary" id="addTask"> <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"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg> Add Task </button> </div> </div> <div class="search-bar"> <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" class="search-icon"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg> <input type="text" placeholder="Search tasks..." id="searchTasks"> </div> <div class="filter-tags"> <div class="filter-tag active" data-filter="all">All Tasks</div> <div class="filter-tag" data-filter="milestone">Milestones</div> <div class="filter-tag" data-filter="at-risk">At Risk</div> <div class="filter-tag" data-filter="high">High Priority</div> </div> <div class="project-tree" id="projectTree"> <!-- Tree nodes will be populated by JavaScript --> </div> <div class="add-task-form" id="addTaskForm"> <div class="form-group"> <label for="taskTitle">Task Title</label> <input type="text" id="taskTitle" class="form-control" placeholder="Enter task title"> </div> <div class="form-row"> <div class="form-group" style="flex: 1;"> <label for="taskType">Task Type</label> <select id="taskType" class="form-control"> <option value="task">Task</option> <option value="feature">Feature</option> <option value="bug">Bug</option> <option value="milestone">Milestone</option> </select> </div> <div class="form-group" style="flex: 1;"> <label for="taskPriority">Priority</label> <select id="taskPriority" class="form-control"> <option value="low">Low</option> <option value="medium">Medium</option> <option value="high">High</option> </select> </div> </div> <div class="form-group"> <label for="taskProgress">Progress (%)</label> <input type="range" id="taskProgress" class="form-control" min="0" max="100" value="0"> </div> <div class="form-actions"> <button class="btn btn-outline" id="cancelAddTask">Cancel</button> <button class="btn btn-primary" id="saveNewTask">Save Task</button> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initial project data const projectData = [ { id: 1, title: "Product Development", type: "task", priority: "high", assignee: "Sarah", dueDate: "Nov 15", progress: 65, expanded: true, children: [ { id: 2, title: "Feature Implementation", type: "feature", priority: "high", assignee: "Mike", dueDate: "Oct 28", progress: 70, expanded: true, children: [ { id: 3, title: "User Authentication Module", type: "task", priority: "medium", assignee: "Alex", dueDate: "Oct 20", progress: 100, children: [] }, { id: 4, title: "Dashboard Analytics", type: "feature", priority: "high", assignee: "Lisa", dueDate: "Oct 25", progress: 85, atRisk: true, children: [] }, { id: 5, title: "Export Functionality", type: "feature", priority: "medium", assignee: "John", dueDate: "Oct 27", progress: 35, children: [] } ] }, { id: 6, title: "Bug Fixes", type: "bug", priority: "medium", assignee: "Emma", dueDate: "Oct 30", progress: 45, expanded: true, children: [ { id: 7, title: "Mobile Responsive Issues", type: "bug", priority: "high", assignee: "Ryan", dueDate: "Oct 22", progress: 80, children: [] }, { id: 8, title: "Performance Optimization", type: "bug", priority: "low", assignee: "Emma", dueDate: "Oct 29", progress: 10, children: [] } ] }, { id: 9, title: "Alpha Release", type: "milestone", priority: "high", assignee: "Team", dueDate: "Nov 1", progress: 50, children: [] } ] }, { id: 10, title: "Marketing Campaign", type: "task", priority: "medium", assignee: "Jessica", dueDate: "Nov 20", progress: 30, expanded: true, children: [ { id: 11, title: "Content Creation", type: "task", priority: "medium", assignee: "Tom", dueDate: "Nov 5", progress: 60, atRisk: true, children: [] }, { id: 12, title: "Social Media Strategy", type: "task", priority: "low", assignee: "Mia", dueDate: "Nov 10", progress: 25, children: [] }, { id: 13, title: "Campaign Launch", type: "milestone", priority: "high", assignee: "Team", dueDate: "Nov 15", progress: 0, warning: true, children: [] } ] }, { id: 14, title: "Product Launch", type: "milestone", priority: "high", assignee: "Leadership", dueDate: "Dec 1", progress: 10, children: [] } ]; // HTML Templates for tree nodes function generateNodeHTML(node, level = 1) { const hasChildren = node.children && node.children.length > 0; const expandIconClass = node.expanded ? 'transform: rotate(90deg)' : ''; const expandedClass = node.expanded ? 'expanded' : ''; // Node class based on properties let nodeClass = ''; if (node.type === 'milestone') nodeClass += ' milestone'; if (node.atRisk) nodeClass += ' at-risk'; if (node.warning) nodeClass += ' warning'; let html = ` <div class="tree-node node-level-${level}" data-id="${node.id}" data-type="${node.type}" data-priority="${node.priority}"> <div class="node-content${nodeClass}" draggable="true"> ${hasChildren ? `<div class="expand-icon" style="${expandIconClass}"> <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"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </div>` : '<div style="width: 18px; margin-right: 8px;"></div>'} <div class="task-type ${node.type}"> ${getIconForType(node.type)} </div> <div class="node-details"> <div class="node-title">${node.title}</div> <div class="node-meta"> <span class="task-pill ${node.priority}">${capitalizeFirstLetter(node.priority)}</span> <span> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path> <circle cx="12" cy="7" r="4"></circle> </svg> ${node.assignee} </span> <span> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect> <line x1="16" y1="2" x2="16" y2="6"></line> <line x1="8" y1="2" x2="8" y2="6"></line> <line x1="3" y1="10" x2="21" y2="10"></line> </svg> ${node.dueDate} </span> </div> <div class="progress-bar"> <div class="progress-fill" style="width: ${node.progress}%"></div> </div> <div class="completion-line" style="width: ${node.progress}%"></div> ${node.type === 'milestone' ? '<div class="milestone-indicator"></div>' : ''} </div> <div class="node-actions"> <button class="action-btn edit-btn"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 20h9"></path> <path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path> </svg> </button> <button class="action-btn delete-btn"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="3 6 5 6 21 6"></polyline> <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path> </svg> </button> </div> </div> `; if (hasChildren) { html += `<div class="children ${expandedClass}">`; node.children.forEach(child => { html += generateNodeHTML(child, level + 1); }); html += `</div>`; } html += `</div>`; return html; } function getIconForType(type) { switch(type) { case 'feature': return '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon></svg>'; case 'bug': return '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1L8 5H4L2 9l2 4-2 4 2 4h4l4 4 4-4h4l2-4-2-4 2-4-2-4h-4L12 1z"></path></svg>'; case 'milestone': return '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8h1a4 4 0 0 1 0 8h-1"></path><path d="M2 8h16v9a4 4 0 0 1-4 4H6a4 4 0 0 1-4-4V8z"></path><line x1="6" y1="1" x2="6" y2="4"></line><line x1="10" y1="1" x2="10" y2="4"></line><line x1="14" y1="1" x2="14" y2="4"></line></svg>'; default: return '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 11 12 14 22 4"></polyline><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path></svg>'; } } function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } // Render project tree function renderProjectTree() { const treeContainer = document.getElementById('projectTree'); let treeHTML = ''; projectData.forEach(node => { treeHTML += generateNodeHTML(node); }); treeContainer.innerHTML = treeHTML; attachEventListeners(); } // Attach event listeners to tree nodes function attachEventListeners() { // Expand/collapse functionality document.querySelectorAll('.expand-icon').forEach(icon => { icon.addEventListener('click', function(e) { e.stopPropagation(); const node = this.closest('.tree-node'); const children = node.querySelector('.children'); if (children) { children.classList.toggle('expanded'); this.style.transform = children.classList.contains('expanded') ? 'rotate(90deg)' : ''; } }); }); // Drag and drop functionality let draggedNode = null; document.querySelectorAll('.node-content').forEach(node => { node.addEventListener('dragstart', function(e) { draggedNode = this.closest('.tree-node'); this.classList.add('dragging'); setTimeout(() => { draggedNode.style.display = 'none'; }, 0); }); node.addEventListener('dragend', function() { this.classList.remove('dragging'); draggedNode.style.display = ''; draggedNode = null; document.querySelectorAll('.drop-target').forEach(el => { el.classList.remove('drop-target'); }); }); node.addEventListener('dragover', function(e) { e.preventDefault(); if (draggedNode && draggedNode !== this.closest('.tree-node')) { this.classList.add('drop-target'); } }); node.addEventListener('dragleave', function() { this.classList.remove('drop-target'); }); node.addEventListener('drop', function(e) { e.preventDefault(); if (draggedNode) { const targetNode = this.closest('.tree-node'); const targetId = parseInt(targetNode.dataset.id); const draggedId = parseInt(draggedNode.dataset.id); // Here you would update your data structure // This is a simplified example showing visual feedback this.classList.remove('drop-target'); // Add animation before actual move targetNode.classList.add('pulse'); setTimeout(() => { targetNode.classList.remove('pulse'); }, 1000); } }); }); // Delete and edit buttons document.querySelectorAll('.delete-btn').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); const node = this.closest('.tree-node'); node.style.animation = 'fadeOut 0.3s ease'; setTimeout(() => { node.style.display = 'none'; }, 300); }); }); document.querySelectorAll('.edit-btn').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); const node = this.closest('.tree-node'); node.classList.add('pulse'); setTimeout(() => { node.classList.remove('pulse'); }, 1000); }); }); } // Add task form functionality const addTaskBtn = document.getElementById('addTask'); const addTaskForm = document.getElementById('addTaskForm'); const cancelAddTaskBtn = document.getElementById('cancelAddTask'); const saveNewTaskBtn = document.getElementById('saveNewTask'); addTaskBtn.addEventListener('click', function() { addTaskForm.classList.add('active'); }); cancelAddTaskBtn.addEventListener('click', function() { addTaskForm.classList.remove('active'); }); saveNewTaskBtn.addEventListener('click', function() { const title = document.getElementById('taskTitle').value; const type = document.getElementById('taskType').value; const priority = document.getElementById('taskPriority').value; const progress = document.getElementById('taskProgress').value; if (title) { const newTask = { id: Date.now(), title: title, type: type, priority: priority, assignee: "You", dueDate: "TBD", progress: parseInt(progress), children: [] }; projectData.push(newTask); renderProjectTree(); addTaskForm.classList.remove('active'); // Reset form document.getElementById('taskTitle').value = ''; document.getElementById('taskProgress').value = 0; } }); // Collapse all button document.getElementById('collapseAll').addEventListener('click', function() { document.querySelectorAll('.children').forEach(child => { child.classList.remove('expanded'); }); document.querySelectorAll('.expand-icon').forEach(icon => { icon.style.transform = ''; }); }); // Search functionality document.getElementById('searchTasks').addEventListener('input', function(e) { const searchTerm = e.target.value.toLowerCase(); document.querySelectorAll('.tree-node').forEach(node => { const title = node.querySelector('.node-title').textContent.toLowerCase(); const isVisible = title.includes(searchTerm); node.style.display = isVisible ? '' : 'none'; // If we're showing this node, also show its parents if (isVisible) { let parent = node.parentElement; while (parent && parent.classList.contains('children')) { parent.classList.add('expanded'); parent = parent.parentElement; } } }); }); // Filter tags document.querySelectorAll('.filter-tag').forEach(tag => { tag.addEventListener('click', function() { document.querySelectorAll('.filter-tag').forEach(t => t.classList.remove('active')); this.classList.add('active'); const filter = this
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root { --primary-color: #2c6bed; --secondary-color: #8546eb; --background-color: #f7f9fd; --card-bg: #ffffff; --text-primary: #252b42; --text-secondary: #6c7a9c; --success-color: #2ecc71; --warning-color: #f39c12; --danger-color: #e74c3c; --border-radius: 12px; --shadow: 0 10px 30px rgba(44, 107, 237, 0.05); --animation-speed: 0.3s; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: var(--background-color); color: var(--text-primary); width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; overflow: hidden; } .container { width: 700px; height: 700px; background-color: var(--card-bg); border-radius: var(--border-radius); box-shadow: var(--shadow); padding: 24px; display: flex; flex-direction: column; position: relative; overflow: hidden; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .title { font-size: 24px; font-weight: 700; background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; } .search-filter { display: flex; gap: 12px; margin-bottom: 24px; } .search-box { flex: 1; position: relative; } .search-box input { width: 100%; padding: 12px 16px 12px 40px; border-radius: var(--border-radius); border: 1px solid #e1e5ee; background-color: var(--background-color); font-size: 14px; outline: none; transition: all var(--animation-speed) ease; } .search-box input:focus { border-color: var(--primary-color); box-shadow: 0 0 0 3px rgba(44, 107, 237, 0.15); } .search-icon { position: absolute; top: 50%; left: 14px; transform: translateY(-50%); color: var(--text-secondary); } .filter-button { display: flex; align-items: center; gap: 8px; padding: 12px 16px; background-color: var(--background-color); border: 1px solid #e1e5ee; border-radius: var(--border-radius); cursor: pointer; transition: all var(--animation-speed) ease; } .filter-button:hover { background-color: #ebf1fd; } .tree-container { flex: 1; overflow: auto; padding-right: 8px; } .tree-container::-webkit-scrollbar { width: 6px; } .tree-container::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; } .tree-container::-webkit-scrollbar-thumb { background: #d1d9e6; border-radius: 10px; } .tree-container::-webkit-scrollbar-thumb:hover { background: #a8b5d1; } .tree-node { margin-bottom: 6px; border-radius: var(--border-radius); transition: all var(--animation-speed) ease; } .node-content { display: flex; align-items: center; padding: 12px 16px; border-radius: var(--border-radius); background-color: var(--background-color); cursor: pointer; transition: all var(--animation-speed) ease; position: relative; overflow: hidden; } .node-content::before { content: ''; position: absolute; left: 0; top: 0; height: 100%; width: 4px; background: linear-gradient(to bottom, var(--primary-color), var(--secondary-color)); border-radius: 2px; opacity: 0; transition: opacity var(--animation-speed) ease; } .node-content:hover { background-color: #ebf1fd; } .node-content:hover::before { opacity: 1; } .node-toggle { margin-right: 12px; width: 20px; height: 20px; display: flex; justify-content: center; align-items: center; border-radius: 50%; background-color: #e1e5ee; color: var(--text-secondary); font-size: 14px; cursor: pointer; transition: all var(--animation-speed) ease; transform: rotate(0deg); } .node-open > .node-content .node-toggle { transform: rotate(90deg); background-color: var(--primary-color); color: white; } .node-icon { margin-right: 12px; width: 20px; height: 20px; display: flex; justify-content: center; align-items: center; } .node-text { flex: 1; font-size: 14px; font-weight: 500; color: var(--text-primary); } .node-metrics { display: flex; align-items: center; gap: 12px; } .metric { font-size: 12px; font-weight: 600; padding: 4px 8px; border-radius: 6px; display: flex; align-items: center; gap: 4px; } .metric-value { display: flex; align-items: center; } .metric-positive { color: var(--success-color); background-color: rgba(46, 204, 113, 0.1); } .metric-neutral { color: var(--warning-color); background-color: rgba(243, 156, 18, 0.1); } .metric-negative { color: var(--danger-color); background-color: rgba(231, 76, 60, 0.1); } .node-children { margin-left: 24px; border-left: 1px dashed #e1e5ee; padding-left: 16px; display: none; animation: fadeIn var(--animation-speed) ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } .node-open > .node-children { display: block; } .breadcrumb { display: flex; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 4px; } .breadcrumb-item { font-size: 12px; color: var(--text-secondary); display: flex; align-items: center; } .breadcrumb-item:not(:last-child)::after { content: '/'; margin: 0 6px; color: #d1d9e6; } .breadcrumb-item:last-child { color: var(--primary-color); font-weight: 600; } .tooltip { position: absolute; background: rgba(52, 73, 94, 0.95); color: white; padding: 10px 14px; border-radius: 6px; font-size: 12px; pointer-events: none; z-index: 100; opacity: 0; transition: opacity 0.2s ease; max-width: 220px; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); } .filters-panel { position: absolute; top: 120px; right: 24px; background-color: var(--card-bg); box-shadow: var(--shadow); border-radius: var(--border-radius); padding: 16px; z-index: 10; width: 260px; transform: translateX(300px); opacity: 0; transition: all var(--animation-speed) ease; } .filters-panel.active { transform: translateX(0); opacity: 1; } .filters-heading { font-size: 16px; font-weight: 600; margin-bottom: 16px; display: flex; justify-content: space-between; align-items: center; } .close-filters { cursor: pointer; color: var(--text-secondary); } .filter-group { margin-bottom: 16px; } .filter-label { font-size: 12px; font-weight: 500; color: var(--text-secondary); margin-bottom: 8px; } .filter-options { display: flex; flex-direction: column; gap: 8px; } .filter-option { display: flex; align-items: center; gap: 8px; } .filter-checkbox { appearance: none; width: 18px; height: 18px; border: 2px solid #d1d9e6; border-radius: 4px; cursor: pointer; position: relative; transition: all var(--animation-speed) ease; } .filter-checkbox:checked { background-color: var(--primary-color); border-color: var(--primary-color); } .filter-checkbox:checked::after { content: '✓'; position: absolute; color: white; font-size: 12px; top: 50%; left: 50%; transform: translate(-50%, -50%); } .filter-option-text { font-size: 14px; color: var(--text-primary); } .filter-actions { display: flex; justify-content: flex-end; gap: 8px; } .filter-button-action { padding: 8px 16px; border-radius: 6px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all var(--animation-speed) ease; } .filter-reset { background-color: transparent; color: var(--text-secondary); border: 1px solid #e1e5ee; } .filter-apply { background-color: var(--primary-color); color: white; border: none; } .filter-apply:hover { background-color: #1a5ddc; } .filter-reset:hover { background-color: #f0f3f9; } .node-badge { font-size: 10px; font-weight: 600; padding: 3px 6px; border-radius: 4px; margin-left: 8px; } .badge-new { background-color: rgba(44, 107, 237, 0.1); color: var(--primary-color); } .overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.2); z-index: 5; opacity: 0; pointer-events: none; transition: opacity var(--animation-speed) ease; } .overlay.active { opacity: 1; pointer-events: all; } .loading-spinner { display: none; width: 24px; height: 24px; border: 3px solid rgba(44, 107, 237, 0.1); border-radius: 50%; border-top-color: var(--primary-color); animation: spin 1s linear infinite; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } @keyframes spin { to { transform: translate(-50%, -50%) rotate(360deg); } } .node-loading .loading-spinner { display: block; } .pulse-animation { animation: pulse 2s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(44, 107, 237, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(44, 107, 237, 0); } 100% { box-shadow: 0 0 0 0 rgba(44, 107, 237, 0); } } .summary-panel { display: none; position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(to right, var(--primary-color), var(--secondary-color)); padding: 16px 24px; color: white; border-bottom-left-radius: var(--border-radius); border-bottom-right-radius: var(--border-radius); transform: translateY(100%); transition: transform var(--animation-speed) ease; z-index: 5; } .summary-panel.active { transform: translateY(0); display: block; } .summary-title { font-size: 16px; font-weight: 600; margin-bottom: 8px; display: flex; justify-content: space-between; } .summary-close { cursor: pointer; } .summary-content { display: flex; gap: 16px; } .summary-stat { flex: 1; } .summary-stat-value { font-size: 24px; font-weight: 700; margin-bottom: 4px; } .summary-stat-label { font-size: 12px; opacity: 0.8; } .quick-actions { display: flex; gap: 8px; margin-top: 16px; } .quick-action { padding: 6px 12px; background-color: rgba(255, 255, 255, 0.15); border-radius: 4px; font-size: 12px; cursor: pointer; transition: background-color var(--animation-speed) ease; } .quick-action:hover { background-color: rgba(255, 255, 255, 0.25); } .no-results { text-align: center; padding: 30px; color: var(--text-secondary); } .no-results-icon { font-size: 48px; margin-bottom: 16px; color: #d1d9e6; } .no-results-text { font-size: 16px; font-weight: 500; margin-bottom: 8px; } .no-results-subtext { font-size: 14px; color: var(--text-secondary); margin-bottom: 16px; } .legend { display: flex; align-items: center; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; } .legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-secondary); } .legend-color { width: 10px; height: 10px; border-radius: 50%; } </style> </head> <body> <div class="container"> <div class="header"> <h1 class="title">Enterprise Data Explorer</h1> </div> <div class="search-filter"> <div class="search-box"> <span class="search-icon"> <svg width="16" height="16" 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> </span> <input type="text" id="search-input" placeholder="Search by name, metric, or department"> </div> <div class="filter-button" id="filter-toggle"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M22 3H2L10 12.46V19L14 21V12.46L22 3Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> Filters </div> </div> <div class="breadcrumb" id="breadcrumb"> <div class="breadcrumb-item" data-id="root">All Data</div> </div> <div class="legend"> <div class="legend-item"> <div class="legend-color" style="background-color: var(--success-color)"></div> <span>Positive Growth</span> </div> <div class="legend-item"> <div class="legend-color" style="background-color: var(--warning-color)"></div> <span>Stable</span> </div> <div class="legend-item"> <div class="legend-color" style="background-color: var(--danger-color)"></div> <span>Negative Growth</span> </div> </div> <div class="tree-container" id="tree-container"> <!-- Tree nodes will be added dynamically here --> </div> <div class="loading-spinner"></div> <div class="filters-panel" id="filters-panel"> <div class="filters-heading"> <span>Advanced Filters</span> <span class="close-filters" id="close-filters"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </span> </div> <div class="filter-group"> <div class="filter-label">Performance Status</div> <div class="filter-options"> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-positive" checked> <label for="filter-positive" class="filter-option-text">Positive Growth</label> </div> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-neutral" checked> <label for="filter-neutral" class="filter-option-text">Stable</label> </div> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-negative" checked> <label for="filter-negative" class="filter-option-text">Negative Growth</label> </div> </div> </div> <div class="filter-group"> <div class="filter-label">Department</div> <div class="filter-options"> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-sales" checked> <label for="filter-sales" class="filter-option-text">Sales</label> </div> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-marketing" checked> <label for="filter-marketing" class="filter-option-text">Marketing</label> </div> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-finance" checked> <label for="filter-finance" class="filter-option-text">Finance</label> </div> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-operations" checked> <label for="filter-operations" class="filter-option-text">Operations</label> </div> </div> </div> <div class="filter-group"> <div class="filter-label">Data Update Period</div> <div class="filter-options"> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-new" checked> <label for="filter-new" class="filter-option-text">New Data (Last 24 hours)</label> </div> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-week" checked> <label for="filter-week" class="filter-option-text">Last 7 days</label> </div> <div class="filter-option"> <input type="checkbox" class="filter-checkbox" id="filter-month" checked> <label for="filter-month" class="filter-option-text">Last 30 days</label> </div> </div> </div> <div class="filter-actions"> <button class="filter-button-action filter-reset" id="reset-filters">Reset</button> <button class="filter-button-action filter-apply" id="apply-filters">Apply Filters</button> </div> </div> <div class="summary-panel" id="summary-panel"> <div class="summary-title"> <span>Department Summary</span> <span class="summary-close" id="close-summary">×</span> </div> <div class="summary-content"> <div class="summary-stat"> <div class="summary-stat-value">$842K</div> <div class="summary-stat-label">Total Revenue</div> </div> <div class="summary-stat"> <div class="summary-stat-value">+12.5%</div> <div class="summary-stat-label">Growth Rate</div> </div> <div class="summary-stat"> <div class="summary-stat-value">24</div> <div class="summary-stat-label">Active Products</div> </div> </div> <div class="quick-actions"> <div class="quick-action">View Report</div> <div class="quick-action">Export Data</div> <div class="quick-action">Share Insights</div> </div> </div> <div class="overlay" id="overlay"></div> </div> <div class="tooltip" id="tooltip"></div> <script> document.addEventListener('DOMContentLoaded', function() { // Data structure with nested hierarchy const treeData = [ { id: 'sales', name: 'Sales Department', type: 'department', metrics: { value: '+18.2%', type: 'positive' }, isNew: true, children: [ { id: 'north-america', name: 'North America', type: 'region', metrics: { value: '+22.7%', type: 'positive' }, children: [ { id: 'enterprise', name: 'Enterprise Customers', type: 'segment', metrics: { value: '+15.3%', type: 'positive' }, children: [ { id: 'cloud-solutions', name: 'Cloud Solutions', type: 'product', metrics: { value: '+31.4%', type: 'positive' }, isNew: true }, { id: 'cybersecurity', name: 'Cybersecurity Services', type: 'product', metrics: { value: '+19.8%', type: 'positive' } } ] }, { id: 'mid-market', name: 'Mid-Market Customers', type: 'segment', metrics: { value: '+23.5%', type: 'positive' }, } ] }, { id: 'europe', name: 'Europe', type: 'region', metrics: { value: '+11.2%', type: 'positive' }, children: [ { id: 'enterprise-eu', name: 'Enterprise Customers', type: 'segment', metrics: { value: '+8.5%', type: 'neutral' }, }, { id: 'mid-market-eu', name: 'Mid-Market Customers', type: 'segment', metrics: { value: '+14.7%', type: 'positive' }, isNew: true } ] }, { id: 'asia-pacific', name: 'Asia Pacific', type: 'region', metrics: { value: '+24.9%', type: 'positive' }, } ] }, { id: 'marketing', name: 'Marketing Department', type: 'department', metrics: { value: '+9.4%', type: 'neutral' }, children: [ { id: 'digital', name: 'Digital Marketing', type: 'channel', metrics: { value: '+16.8%', type: 'positive' }, children: [ { id: 'social-media', name: 'Social Media', type: 'campaign', metrics: { value: '+22.3%', type: 'positive' }, isNew: true }, { id: 'email', name: 'Email Campaigns', type: 'campaign', metrics: { value: '+11.6%', type: 'positive' }, } ] }, { id: 'traditional', name: 'Traditional Marketing', type: 'channel', metrics: { value: '-3.7%', type: 'negative' }, children: [ { id: 'print', name: 'Print Media', type: 'campaign', metrics: { value: '-8.2%', type: 'negative' }, }, { id: 'events', name: 'Events & Trade Shows', type: 'campaign', metrics: { value: '+2.1%', type: 'neutral' }, } ] } ] }, { id: 'finance', name: 'Finance Department', type: 'department', metrics: { value: '+3.2%', type: 'neutral' }, children: [ { id: 'accounts-receivable', name: 'Accounts Receivable', type: 'division', metrics: { value: '-1.9%', type: 'negative' }, }, { id: 'accounts-payable', name: 'Accounts Payable', type: 'division', metrics: { value: '+2.5%', type: 'neutral' }, }, { id: 'financial-planning', name: 'Financial Planning', type: 'division', metrics: { value: '+4.8%', type: 'neutral' }, children: [ { id: 'budget-forecasting', name: 'Budget & Forecasting', type: 'team', metrics: { value: '+5.7%', type: 'positive' }, }, { id: 'investment-analysis', name: 'Investment Analysis', type: 'team', metrics: { value: '+6.3%', type: 'positive' }, isNew: true } ] } ] }, { id: 'operations', name: 'Operations Department', type: 'department', metrics: { value: '-2.5%', type: 'negative' }, children: [ { id: 'supply-chain', name: 'Supply Chain', type: 'division', metrics: { value: '-6.1%', type: 'negative' }, children: [ { id: 'procurement', name: 'Procurement', type: 'team', metrics: { value: '-4.2%', type: 'negative' }, }, { id: 'logistics', name: 'Logistics', type: 'team', metrics: { value: '-8.7%', type: 'negative' }, } ] }, { id: 'facilities', name: 'Facilities Management', type: 'division', metrics: { value: '+1.3%', type: 'neutral' }, } ] } ]; // DOM elements const treeContainer = document.getElementById('tree-container'); const searchInput = document.getElementById('search-input'); const filterToggle = document.getElementById('filter-toggle'); const filtersPanel = document.getElementById('filters-panel'); const closeFilters = document.getElementById('close-filters'); const applyFilters = document.getElementById('apply-filters'); const resetFilters = document.getElementById('reset-filters'); const overlay = document.getElementById('overlay'); const tooltip = document.getElementById('tooltip'); const breadcrumb = document.getElementById('breadcrumb'); const summaryPanel = document.getElementById('summary-panel'); const closeSummary = document.getElementById('close-summary'); // State let currentPath = []; let searchTerm = ''; let filters = { status: { positive: true, neutral: true, negative: true }, department: { sales: true, marketing: true, finance: true, operations: true }, update: { new: true, week: true, month: true } }; // Render tree structure function renderTree(parentElement, nodes, level = 0) { parentElement.innerHTML = ''; if (nodes.length === 0) { parentElement.innerHTML = ` <div class="no-results"> <div class="no-results-icon">🔍</div> <div class="no-results-text">No data matches your criteria</div> <div class="no-results-subtext">Try adjusting your search or filters</div> </div> `; return; } nodes.forEach(node => { const nodeElement = document.createElement('div'); nodeElement.className = 'tree-node'; nodeElement.dataset.id = node.id; nodeElement.dataset.type = node.type; nodeElement.dataset.metricsType = node.metrics?.type || ''; const hasChildren = node.children && node.children.length > 0; const nodeContent = document.createElement('div'); nodeContent.className = 'node-content'; const toggle = document.createElement('div'); toggle.className = 'node-toggle'; toggle.innerHTML = hasChildren ? '›' : ''; const icon = document.createElement('div'); icon.className = 'node-icon'; // Different icon based on node type let iconSvg = ''; switch(node.type) { case 'department': iconSvg = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M3 5H21V19H3V5Z" stroke="${getColorByType(node.metrics?.type)}" stroke-width="2"/> <path d="M10 9V15" stroke="${getColorByType(node.metrics?.type)}" stroke-width="2"/> <path d="M14 9V15" stroke="${getColorByType(node.metrics?.type)}" stroke-width="2"/></svg>`; break; case 'region': case 'channel': case 'division': iconSvg = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L2 7L12 12L22 7L12 2Z" stroke="${getColorByType(node.metrics?.type)}" stroke-width="2"/> <path d="M2 17L12 22L22 17" stroke="${getColorByType(node.metrics?.type)}" stroke-width="2"/> <path d="M2 12L12 17L22 12" stroke="${getColorByType(node.metrics?.type)}" stroke-width="2"/></svg>`; break; case 'segment': case 'campaign': case 'team': iconSvg = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M17 21V19C17 17.9391 16.5786 16.9217 15.8284 16.1716C15.0783 15.4214 14.0609 15 13 15H5C3.93913 15 2.92172 15.4214 2.17157 16.1716C1.42143 16.9217 1 17.9391 1 19V21" stroke="${getColorByType(node.metrics?.type)}" stroke-width="2"/> <path d="M9 11C11.2091 11 13 9.20914 13 7C13 4.79086 11.2091 3 9 3C6.79086 3 5 4.79086 5 7C