From 918cc65a0da33ddc20cb97d6c19a42051b959b38 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 3 Apr 2026 11:22:43 +0200 Subject: [PATCH] Provider selection as tabs --- src/ifcchat/app.js | 14 ++++++++---- src/ifcchat/index.html | 24 +++++++++++++++----- src/ifcchat/style.css | 51 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 12 deletions(-) diff --git a/src/ifcchat/app.js b/src/ifcchat/app.js index c0046491b5..7a7eb1adab 100644 --- a/src/ifcchat/app.js +++ b/src/ifcchat/app.js @@ -112,13 +112,17 @@ const baseUrlLabelEl = $("baseUrlLabel"); const baseUrlEl = $("baseUrl"); const thinkingIndicatorEl = $("thinkingIndicator"); const modelEl = $("model"); -const providerEl = $("provider"); +const providerEls = document.querySelectorAll('input[name="provider"]'); const ifcFileEl = $("ifcFile"); const newBtn = $("newModel"); const downloadBtn = $("downloadIfc"); +function getProviderValue() { + return document.querySelector('input[name="provider"]:checked')?.value || "openai"; +} + function onProviderChange() { - const provider = PROVIDERS[providerEl.value]; + const provider = PROVIDERS[getProviderValue()]; apiKeyLabelEl.innerHTML = `${provider.apiKeyLabel}stored in browser memory; only sent to provider servers`; apiKeyEl.placeholder = provider.apiKeyPlaceholder; baseUrlRowEl.hidden = !provider.baseUrlDefault; @@ -133,7 +137,9 @@ function onProviderChange() { modelEl.innerHTML = provider.models.map(m => ``).join(""); } -providerEl.addEventListener("change", onProviderChange); +for (const providerEl of providerEls) { + providerEl.addEventListener("change", onProviderChange); +} onProviderChange(); function setBusy(isBusy, reason = "") { @@ -467,7 +473,7 @@ async function runAgentTurn(userText) { const apiKey = apiKeyEl.value.trim(); if (!apiKey) throw new Error("Missing API key"); - const provider = PROVIDERS[providerEl.value]; + const provider = PROVIDERS[getProviderValue()]; const { chat } = provider.api; const baseURL = provider.baseUrlDefault ? baseUrlEl.value.trim() : undefined; diff --git a/src/ifcchat/index.html b/src/ifcchat/index.html index e919b1ae8f..daf6146126 100644 --- a/src/ifcchat/index.html +++ b/src/ifcchat/index.html @@ -14,12 +14,24 @@
- +
+ + + + +
diff --git a/src/ifcchat/style.css b/src/ifcchat/style.css index b84fb1fb30..105e0d574f 100644 --- a/src/ifcchat/style.css +++ b/src/ifcchat/style.css @@ -32,7 +32,7 @@ main { .side { border-right: 1px solid #ddd; - padding: 100px 12px 12px 12px; + padding: 12px; overflow: auto; background: #f9f9f9; } @@ -234,7 +234,54 @@ section > .row > label .small { } .side .row { - margin-bottom: 32px; + margin-bottom: 20px; +} + +.provider-tabs { + display: flex; + flex-wrap: wrap; + gap: 6px; + background: #00000010; + padding: 6px 0 0 6px; +} + +.provider-tab { + position: relative; + display: inline-flex; +} + +.provider-tab input { + position: absolute; + opacity: 0; + pointer-events: none; +} + +.provider-tab span { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 38px; + padding: 8px; + border: 1px solid #d0d0d0; + border-radius: 2px 2px 0 0; + background: #e8e8e8; + color: #555; + cursor: pointer; + user-select: none; + transition: background 0.15s, border-color 0.15s, color 0.15s; + font-size: 75%; +} + +.provider-tab input:checked + span { + background: #f9f9f9; + border-color: #999; + color: #111; + border-bottom: none; +} + +.provider-tab input:focus-visible + span { + outline: 2px solid #666; + outline-offset: 2px; } .row button {