diff options
| author | Gabriel Schneider <[email protected]> | 2026-08-02 12:36:54 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-08-02 17:37:58 -0300 |
| commit | e16f78b255bcf46d8c6f9a4b9e76dd7a3817edeb (patch) | |
| tree | de0db0c369522b5bf92ff32a8351de2224c5c9dc /vrsite/assets | |
| parent | 151ea12251ed876aa87bb486da1bc337e25369e9 (diff) | |
| download | notevi-e16f78b255bcf46d8c6f9a4b9e76dd7a3817edeb.tar.gz notevi-e16f78b255bcf46d8c6f9a4b9e76dd7a3817edeb.zip | |
Diffstat (limited to 'vrsite/assets')
| -rw-r--r-- | vrsite/assets/app.js | 20 | ||||
| -rw-r--r-- | vrsite/assets/style.css.tmpl | 25 |
2 files changed, 45 insertions, 0 deletions
diff --git a/vrsite/assets/app.js b/vrsite/assets/app.js index 696041c..74db8d2 100644 --- a/vrsite/assets/app.js +++ b/vrsite/assets/app.js @@ -22,6 +22,26 @@ setMode(root.dataset.mode || "trace"); const typing = e => /^(INPUT|TEXTAREA|SELECT)$/.test(e.target.tagName) || e.target.isContentEditable; +// The project hub is fully server-derived; filtering is deliberately local so +// choosing a project does not create another piece of server state. +const projectFind = document.getElementById("projectfind"); +if (projectFind) { + const apply = () => { + const q = projectFind.value.trim().toLowerCase(); + for (const card of document.querySelectorAll(".project-card")) + card.hidden = !!q && !(card.dataset.project || "").toLowerCase().includes(q); + }; + projectFind.addEventListener("input", apply); + projectFind.addEventListener("search", apply); + projectFind.addEventListener("keydown", e => { + if (e.key === "Escape") { projectFind.value = ""; apply(); projectFind.blur(); } + if (e.key === "Enter") { + const first = document.querySelector(".project-card:not([hidden]) a.project-action"); + if (first) first.click(); + } + }); +} + document.addEventListener("keydown", e => { if (e.metaKey || e.ctrlKey || e.altKey || typing(e)) return; if (e.key === "t") setMode(root.dataset.mode === "notes" ? "trace" : "notes"); diff --git a/vrsite/assets/style.css.tmpl b/vrsite/assets/style.css.tmpl index 9418087..60d2a2b 100644 --- a/vrsite/assets/style.css.tmpl +++ b/vrsite/assets/style.css.tmpl @@ -537,6 +537,31 @@ table.changed .st { color: var(--muted); font-size: 11px; width: 7ch; } table.changed .st-added { color: var(--accent); } table.changed .st-deleted { color: var(--note); } +/* ── project hub ───────────────────────────────────────────── */ +.projects-main { padding-bottom: 20vh; } +.projects-main > section { max-width: 1200px; } +.project-refresh { margin: 10px 0; } +.project-refresh button, .project-card button, .project-action { + display: inline-block; background: var(--panel); color: var(--fg); + border: 1px solid var(--border); border-radius: 5px; + font: inherit; font-size: 12px; padding: 5px 10px; cursor: pointer; +} +.project-refresh button:hover, .project-card button:hover, .project-action:hover { + background: var(--hover); text-decoration: none; +} +.project-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; } +.project-card { min-width: 0; padding: 12px; border: 1px solid var(--border); border-radius: 7px; background: var(--panel); } +.project-card > header { display: flex; align-items: center; justify-content: space-between; gap: 8px; } +.project-card h3 { min-width: 0; margin: 0; font: 600 14px/1.3 ui-monospace, Menlo, monospace; overflow: hidden; text-overflow: ellipsis; } +.project-path { margin: 8px 0; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.project-state { flex: none; padding: 1px 6px; border: 1px solid var(--border); border-radius: 99px; color: var(--muted); font-size: 10px; text-transform: uppercase; } +.project-state.active { border-color: var(--accent); color: var(--accent); } +.project-state.git { color: var(--note); } +.project-card form, .project-card .project-action { margin-top: 10px; } +.project-message { max-width: 1168px; } +.ok { margin: 12px 16px; padding: 8px 10px; border: 1px solid var(--accent); border-radius: 6px; color: var(--accent); } +.project-card[hidden] { display: none; } + /* ── agent coverage colors ────────────────────────────────── A bitmask is its agents' colors averaged. The blend is left to the browser so these rules hold for any theme: a theme only has to name |
