From 882381868676b6e09335f6d51ec2d0c85efac8a1 Mon Sep 17 00:00:00 2001 From: Joseph Yaksich <294273268+gitcommit90@users.noreply.github.com> Date: Mon, 20 Jul 2026 19:32:50 +0000 Subject: [PATCH] fix routes open as full-page editor Clicking a route replaces the list with the editor, focuses the model ID, and drops the laggy card lift so open feels immediate. --- CHANGELOG.md | 7 ++++ package-lock.json | 4 +-- package.json | 2 +- src/renderer/app.js | 71 +++++++++++++++++++++++++++++++---------- src/renderer/styles.css | 17 ++++++++-- 5 files changed, 80 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 480b5c0..c3e0e4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ Release tags use the form `vX.Y.Z` and match `package.json`. GitHub Releases car ## [Unreleased] +## [0.5.6] - 2026-07-20 + +### Fixed + +- Opening a route now replaces the routes list with a full editor instead of burying an edit panel below the grid with no scroll. +- Removed the laggy route-card lift animation so clicks feel immediate. + ## [0.5.5] - 2026-07-20 ### Added diff --git a/package-lock.json b/package-lock.json index e6d3578..3901349 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@gitcommit90/rerouted", - "version": "0.5.5", + "version": "0.5.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@gitcommit90/rerouted", - "version": "0.5.5", + "version": "0.5.6", "license": "MIT", "bin": { "rerouted": "src/cli/index.js" diff --git a/package.json b/package.json index 8a8fda6..4057d2b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@gitcommit90/rerouted", "productName": "ReRouted", - "version": "0.5.5", + "version": "0.5.6", "description": "A local AI router for connected accounts, models, named routes, and automatic fallback.", "author": "gitcommit90", "license": "MIT", diff --git a/src/renderer/app.js b/src/renderer/app.js index 2a3ae43..1dbf742 100644 --- a/src/renderer/app.js +++ b/src/renderer/app.js @@ -1746,7 +1746,18 @@ function beginComboEdit(combo) { model: member.model || member.upstreamModel, })), }; - renderCombos(); + renderCombos({ focusEditor: true }); +} + +function focusRouteEditor() { + const editorEl = view.querySelector(".route-editor"); + if (!editorEl) return; + editorEl.scrollIntoView({ block: "start", behavior: "auto" }); + const name = $("#c-name"); + if (name) { + name.focus({ preventScroll: true }); + if (typeof name.select === "function") name.select(); + } } function syncComboDraft() { @@ -1767,7 +1778,7 @@ function routeAccountLabel(account) { return account.name; } -function renderCombos() { +function renderCombos(options = {}) { if (blockSensitiveRenderIfLocked()) return; const combos = state.combos || []; const models = flatModels(); @@ -1787,15 +1798,14 @@ function renderCombos() { editor.pickerModelId = null; } - view.innerHTML = ` - ${pageHeader("Routing", "Routes", "Give clients one memorable model ID while ReRouted handles account and provider failover.", '')} + const listMarkup = `
${ combos.length ? combos .map( (c, index) => ` -
+
${c.strategy === "round-robin" ? "Round robin" : "Fallback"} @@ -1804,17 +1814,21 @@ function renderCombos() {
${esc(comboRouteId(c))}
${c.strategy === "round-robin" ? "Rotates every request" : "Fills in order"} · ${(c.members || []).length} member${(c.members || []).length === 1 ? "" : "s"}
- +
` ) .join("") : `
No routes yet. Create a memorable model ID and choose where requests should go.
` } -
- ${ - editor - ? `
-
${editor.id ? "Edit route" : "New route"}
${editor.id ? esc(editor.name || "Route") : "Build a route"}
The model ID below is what clients see in /v1/models.
+ `; + + const editorMarkup = editor + ? `
+
+
${editor.id ? "Edit route" : "New route"}
+
${editor.id ? esc(editor.name || "Route") : "Build a route"}
+
The model ID below is what clients see in /v1/models.
+
Model ID
Routing behavior
@@ -1845,17 +1859,39 @@ function renderCombos() { -
+
` - : "" - } + : ""; + + // When editing, replace the list with the editor (full page take-over). No buried bottom panel. + view.innerHTML = ` + ${pageHeader( + "Routing", + editor ? (editor.id ? editor.name || "Edit route" : "New route") : "Routes", + editor + ? "Change the model ID, order, and failover for this route." + : "Give clients one memorable model ID while ReRouted handles account and provider failover.", + editor + ? '' + : '' + )} + ${editor ? editorMarkup : listMarkup} `; - $("#btn-new-route").onclick = () => beginComboEdit(null); + + const backToList = () => { + comboDraft = null; + renderCombos(); + }; + const backBtn = $("#btn-back-routes"); + if (backBtn) backBtn.onclick = backToList; + const newBtn = $("#btn-new-route"); + if (newBtn) newBtn.onclick = () => beginComboEdit(null); view.querySelectorAll("button[data-edit-index]").forEach((btn) => { btn.onclick = () => beginComboEdit(combos[Number(btn.dataset.editIndex)]); }); view.querySelectorAll("button[data-del-index]").forEach((btn) => { - btn.onclick = async () => { + btn.onclick = async (event) => { + event.stopPropagation(); const combo = combos[Number(btn.dataset.delIndex)]; const id = combo?.storageId || combo?.id; if (!id) return; @@ -1984,6 +2020,9 @@ function renderCombos() { await refresh(); renderCombos(); }; + if (options.focusEditor) { + requestAnimationFrame(() => focusRouteEditor()); + } } let statsPeriod = "24h"; diff --git a/src/renderer/styles.css b/src/renderer/styles.css index 431908f..456e021 100644 --- a/src/renderer/styles.css +++ b/src/renderer/styles.css @@ -1593,14 +1593,18 @@ summary:focus-visible, background: linear-gradient(145deg, rgba(239, 91, 42, 0.08), transparent 58%), var(--paper-strong); - transition: transform 120ms ease, border-color 120ms ease, box-shadow 120ms ease; + transition: border-color 80ms ease, box-shadow 80ms ease; } .route-card:hover, .route-card:focus-within { border-color: rgba(239, 91, 42, 0.55); box-shadow: 0 8px 20px rgba(58, 49, 35, 0.08); - transform: translateY(-1px); +} + +.route-card:active { + border-color: rgba(239, 91, 42, 0.75); + box-shadow: none; } .route-card-hit { @@ -1613,6 +1617,15 @@ summary:focus-visible, cursor: pointer; } +.route-card-hit:active { + background: rgba(239, 91, 42, 0.04); +} + +.route-editor { + margin: 0 0 0 7px; + animation: none; +} + .route-card-top { display: flex; position: relative;