Deep blue-black theme with a violet-to-cyan accent, frosted floating panels, self-hosted Inter, a welcome screen with a call to action, a card-style inspector, accent tabs and toggles, animated progress, and a restyled open dialog. In 3D the WebGL walls are now lit per side with a darker foot so buildings read as solids, and the canvas clears to transparent over the new background. Renamed to CodeNavigator.
162 lines
12 KiB
HTML
162 lines
12 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||
<meta name="theme-color" content="#0b0d13">
|
||
<meta name="description" content="Explore an entire codebase as a fast, searchable 2D and 3D landscape.">
|
||
<title>CodeNavigator</title>
|
||
<link rel="icon" href="./favicon.svg" type="image/svg+xml">
|
||
<link rel="preload" href="./inter-latin.woff2" as="font" type="font/woff2" crossorigin>
|
||
<link rel="stylesheet" href="./styles.css">
|
||
</head>
|
||
<body>
|
||
<main id="app">
|
||
<header class="toolbar" aria-label="Codebase controls">
|
||
<div class="brand" aria-label="CodeNavigator"><svg viewBox="0 0 28 28" aria-hidden="true"><defs><linearGradient id="brandGradient" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#9a7dff"/><stop offset=".5" stop-color="#5f9dff"/><stop offset="1" stop-color="#36d3c2"/></linearGradient></defs><rect x="3" y="11" width="6" height="14" rx="1.6" fill="url(#brandGradient)" opacity=".7"/><rect x="11" y="3" width="6" height="22" rx="1.6" fill="url(#brandGradient)"/><rect x="19" y="15" width="6" height="10" rx="1.6" fill="url(#brandGradient)" opacity=".5"/></svg><span class="brand-name">Code<em>Navigator</em></span></div>
|
||
<div class="tool-group">
|
||
<button class="tool primary" id="loadButton" title="Open codebase" aria-label="Open codebase"><svg viewBox="0 0 24 24"><path d="M3.5 7.5h6l2-2h4l2 2h3v11h-17z"/><path d="M3.5 9.5h17"/></svg></button>
|
||
<button class="tool active" id="mapButton" title="Code landscape" aria-label="Code landscape"><svg viewBox="0 0 24 24"><rect x="3.5" y="3.5" width="17" height="17" rx="2"/><path d="M3.5 10h17M10 3.5v17M10 15h10.5"/></svg></button>
|
||
<button class="tool" id="layersButton" title="Semantic layers" aria-label="Semantic layers"><svg viewBox="0 0 24 24"><path d="m4 8 8-4 8 4-8 4zM4 12l8 4 8-4M4 16l8 4 8-4"/></svg></button>
|
||
</div>
|
||
<span class="separator"></span>
|
||
<div class="tool-group view-switch" role="group" aria-label="View mode">
|
||
<button class="tool active" data-view="2d" title="Flat map" aria-label="Flat map"><svg viewBox="0 0 24 24"><rect x="3.5" y="3.5" width="17" height="17" rx="1.5"/><path d="M3.5 11h17M12 3.5v17"/></svg></button>
|
||
<button class="tool" data-view="3d" title="3D landscape" aria-label="3D landscape"><svg viewBox="0 0 24 24"><path d="m12 3 8 4.5v9L12 21l-8-4.5v-9zM4 7.5l8 4.5 8-4.5M12 12v9"/></svg></button>
|
||
<button class="tool" id="codeButton" title="Toggle source texture" aria-label="Toggle source texture"><svg viewBox="0 0 24 24"><path d="M4 18 9 6l4 8 2-5 5 9z"/><path d="M4 20h16"/></svg></button>
|
||
</div>
|
||
<span class="separator"></span>
|
||
<div class="metric-switch" role="group" aria-label="Map metric">
|
||
<button class="metric active" data-metric="lines"><b>#</b> <span>Lines</span></button>
|
||
<button class="metric" data-metric="references"><b>⌁</b> <span>References</span></button>
|
||
</div>
|
||
<button class="tool palette" id="paletteButton" title="Change palette" aria-label="Change palette"><svg viewBox="0 0 24 24"><path d="M20 13a8 8 0 1 0-8 7h1.5a1.5 1.5 0 0 0 0-3H12a2 2 0 0 1 0-4z"/><circle cx="7.5" cy="11" r="1"/><circle cx="10" cy="7.5" r="1"/><circle cx="14.5" cy="7.5" r="1"/><circle cx="17" cy="11" r="1"/></svg></button>
|
||
<div class="toolbar-spacer"></div>
|
||
<div class="scene-stats" id="sceneStats" aria-live="polite">
|
||
<span id="headlineStats">No codebase loaded</span>
|
||
<small id="fileStats">Open a folder or public repository</small>
|
||
</div>
|
||
<label class="filter-wrap">
|
||
<span class="sr-only">Filter files and symbols</span>
|
||
<input id="searchInput" type="search" placeholder="Find a file or symbol…" autocomplete="off" spellcheck="false">
|
||
<kbd>/</kbd>
|
||
</label>
|
||
<button class="tool" id="settingsButton" title="Performance details" aria-label="Performance details" aria-haspopup="dialog" aria-controls="settingsDialog"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19 13.5v-3l-2-.7-.7-1.7.9-1.9-2.1-2.1-1.9.9-1.7-.7-.7-2h-3l-.7 2-1.7.7-1.9-.9-2.1 2.1.9 1.9-.7 1.7-2 .7v3l2 .7.7 1.7-.9 1.9 2.1 2.1 1.9-.9 1.7.7.7 2h3l.7-2 1.7-.7 1.9.9 2.1-2.1-.9-1.9.7-1.7z"/></svg></button>
|
||
<span class="live-dot" role="status" aria-label="Connecting to indexer" title="Connecting to indexer"></span>
|
||
</header>
|
||
|
||
<section class="workspace">
|
||
<div class="viewport" id="viewport">
|
||
<canvas id="glCanvas"></canvas>
|
||
<canvas id="overlayCanvas"></canvas>
|
||
<div class="welcome" id="welcome">
|
||
<span class="eyebrow"><i></i>Codebase landscapes</span>
|
||
<h1>See your code<br><span>as a place.</span></h1>
|
||
<p>Every file becomes a tile sized by its lines, grouped by folder and coloured by purpose. Fly over it in 2D or 3D, search every symbol, and follow imports from file to file.</p>
|
||
<div class="welcome-actions"><button type="button" class="button-primary" id="welcomeOpen">Open a codebase</button><span><kbd>Ctrl</kbd> <kbd>O</kbd></span></div>
|
||
<div class="welcome-features"><span>Public & private GitHub repos</span><span>Local folders</span><span>Symbol search</span><span>Import graph</span></div>
|
||
</div>
|
||
<div class="empty-state" id="emptyState" hidden>
|
||
<strong>No source files found</strong>
|
||
<span>Try another folder or public GitHub repository.</span>
|
||
</div>
|
||
<div class="progress-card" id="progressCard" role="status" aria-live="polite" hidden>
|
||
<button type="button" class="progress-dismiss close-button" id="dismissProgress" aria-label="Dismiss notification"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m6 6 12 12M18 6 6 18"/></svg></button>
|
||
<div class="progress-copy">
|
||
<strong id="progressTitle">Indexing codebase</strong>
|
||
<span id="progressMessage">Discovering files…</span>
|
||
</div>
|
||
<div class="progress-track"><i id="progressFill"></i></div>
|
||
<span class="progress-count" id="progressCount"></span>
|
||
<a class="dialog-button progress-action" id="progressAction" hidden></a>
|
||
</div>
|
||
<div class="tooltip" id="tooltip" hidden></div>
|
||
<div class="camera-help" id="cameraHelp" hidden>
|
||
<button type="button" data-camera-preset="isometric">Isometric</button>
|
||
<button type="button" data-camera-preset="top">Top</button>
|
||
<button type="button" data-camera-preset="front">Front</button>
|
||
<span><b>Drag</b> orbit</span>
|
||
<span><b>Shift + drag</b> pan</span>
|
||
<span><b>Scroll</b> dolly</span>
|
||
<span><b>F</b> reset</span>
|
||
</div>
|
||
<nav class="breadcrumb" id="breadcrumb" aria-label="Selected file path">
|
||
<button id="homeButton" aria-label="Fit entire codebase">←</button>
|
||
<span id="breadcrumbText">No codebase loaded</span>
|
||
</nav>
|
||
<div class="fps" id="fps">— fps</div>
|
||
<div class="legend" id="legend"></div>
|
||
<div class="canvas-controls" aria-label="Landscape navigation"><button type="button" id="zoomOutButton" title="Zoom out" aria-label="Zoom out">−</button><button type="button" id="fitButton" title="Fit codebase (F)" aria-label="Fit codebase"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M8 4H4v4m12-4h4v4M4 16v4h4m12-4v4h-4"/></svg></button><button type="button" id="zoomInButton" title="Zoom in" aria-label="Zoom in">+</button></div>
|
||
</div>
|
||
|
||
<aside class="inspector" id="inspector">
|
||
<div class="tabs" role="tablist">
|
||
<button class="tab active" data-tab="inspector" role="tab">Inspector</button>
|
||
<button class="tab" data-tab="results" role="tab">Results <span id="resultBadge"></span></button>
|
||
<button class="tab" data-tab="history" role="tab">History</button>
|
||
</div>
|
||
<section class="panel active" id="panel-inspector" role="tabpanel">
|
||
<p class="panel-hint" id="inspectHint">Select an entity on the map</p>
|
||
<div id="inspectContent"></div>
|
||
</section>
|
||
<section class="panel" id="panel-results" role="tabpanel">
|
||
<div class="result-summary" id="resultSummary">Type in the filter to search files and symbols.</div>
|
||
<div class="result-list" id="resultList"></div>
|
||
</section>
|
||
<section class="panel" id="panel-history" role="tabpanel">
|
||
<div class="result-summary">Recently inspected</div>
|
||
<div class="result-list" id="historyList"></div>
|
||
</section>
|
||
</aside>
|
||
</section>
|
||
</main>
|
||
|
||
<dialog id="loadDialog" aria-labelledby="loadTitle">
|
||
<form method="dialog" class="dialog-shell">
|
||
<div class="dialog-head">
|
||
<div><small>YOUR NEXT PERSPECTIVE</small><h1 id="loadTitle">Open a codebase</h1><p class="dialog-description">See the big picture. Explore every detail.</p></div>
|
||
<button class="close-button" value="cancel" aria-label="Close"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m6 6 12 12M18 6 6 18"/></svg></button>
|
||
</div>
|
||
<button type="button" class="source-card" id="localFolderButton">
|
||
<span class="source-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 7h7l2-2h4l2 2h3v12H3zM3 10h18"/></svg></span>
|
||
<span><strong>Local folder</strong><small>Temporarily indexed by this server</small></span>
|
||
<b>→</b>
|
||
</button>
|
||
<div class="source-card github-card">
|
||
<span class="source-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="7" cy="5" r="2"/><circle cx="7" cy="19" r="2"/><circle cx="17" cy="5" r="2"/><path d="M7 7v10m10-10v3a4 4 0 0 1-4 4H7"/></svg></span>
|
||
<label for="githubInput"><strong>GitHub repository</strong><small>Public, or private once you sign in with GitHub</small></label>
|
||
<div class="github-row"><input id="githubInput" type="url" autocomplete="off" spellcheck="false" aria-describedby="githubError" placeholder="https://github.com/owner/repo"><button type="button" id="githubButton">Explore →</button></div>
|
||
<p class="form-error" id="githubError" role="alert"></p>
|
||
<p class="github-account" id="githubAccount" hidden></p>
|
||
</div>
|
||
<p class="dialog-foot">Code is held temporarily by this server, visible only to this browser, and cleared after an hour of inactivity.</p>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="settingsDialog" class="settings-dialog" aria-labelledby="settingsTitle">
|
||
<form method="dialog" class="dialog-shell settings-shell">
|
||
<div class="dialog-head">
|
||
<div><small>MAKE IT YOURS</small><h1 id="settingsTitle">Workspace settings</h1><p class="dialog-description">A workspace that feels right for you.</p></div>
|
||
<button class="close-button" value="cancel" aria-label="Close settings"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m6 6 12 12M18 6 6 18"/></svg></button>
|
||
</div>
|
||
<div id="settingsContent"></div>
|
||
<div class="preference-row"><label for="paletteSelect">Landscape palette<small>Color-code the layers of your codebase</small></label><select id="paletteSelect"><option value="0">Botanical</option><option value="1">Prismatic</option><option value="2">Autumn</option></select></div>
|
||
<div class="preference-row"><label for="sourceToggle">Source text<small>Show code directly in the landscape</small></label><input type="checkbox" class="switch" id="sourceToggle" checked></div>
|
||
<div class="preference-row"><label for="fpsToggle">Performance monitor<small>Display frame rate on the canvas</small></label><input type="checkbox" class="switch" id="fpsToggle"></div>
|
||
<div class="shortcut-guide"><span>Keyboard essentials</span><div><kbd>/</kbd> Search <kbd>F</kbd> Fit landscape <kbd>Esc</kbd> Close</div></div>
|
||
<div class="settings-note">
|
||
<span class="settings-note-icon" aria-hidden="true">⌁</span>
|
||
<p><strong>Room to explore</strong><small>Move from the whole codebase to a single line. Scroll to zoom; drag to move. In 3D, hold Shift while dragging to pan.</small></p>
|
||
</div>
|
||
<div class="settings-actions">
|
||
<button class="dialog-button" value="close">Done</button>
|
||
</div>
|
||
</form>
|
||
</dialog>
|
||
<input id="folderFallback" type="file" webkitdirectory multiple hidden>
|
||
|
||
<script src="./config.js"></script>
|
||
<script type="module" src="./app.js"></script>
|
||
</body>
|
||
</html>
|