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"}
${(c.members || []).slice(0, 5).map((_, index) => `${index ? '' : ""}${index + 1}`).join("")}${(c.members || []).length > 5 ? '+' : ""}
-
Edit route →
+
${editor && (editor.id === (c.storageId || c.id)) ? "Editing" : "Open"} →
`
)
.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;