Skip to content

Commit 918cc65

Browse files
committed
Provider selection as tabs
1 parent 7350ccd commit 918cc65

File tree

3 files changed

+77
-12
lines changed

3 files changed

+77
-12
lines changed

src/ifcchat/app.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,17 @@ const baseUrlLabelEl = $("baseUrlLabel");
112112
const baseUrlEl = $("baseUrl");
113113
const thinkingIndicatorEl = $("thinkingIndicator");
114114
const modelEl = $("model");
115-
const providerEl = $("provider");
115+
const providerEls = document.querySelectorAll('input[name="provider"]');
116116
const ifcFileEl = $("ifcFile");
117117
const newBtn = $("newModel");
118118
const downloadBtn = $("downloadIfc");
119119

120+
function getProviderValue() {
121+
return document.querySelector('input[name="provider"]:checked')?.value || "openai";
122+
}
123+
120124
function onProviderChange() {
121-
const provider = PROVIDERS[providerEl.value];
125+
const provider = PROVIDERS[getProviderValue()];
122126
apiKeyLabelEl.innerHTML = `${provider.apiKeyLabel}<span class="small">stored in browser memory; only sent to provider servers</span>`;
123127
apiKeyEl.placeholder = provider.apiKeyPlaceholder;
124128
baseUrlRowEl.hidden = !provider.baseUrlDefault;
@@ -133,7 +137,9 @@ function onProviderChange() {
133137
modelEl.innerHTML = provider.models.map(m => `<option value="${m.value}">${m.label}</option>`).join("");
134138
}
135139

136-
providerEl.addEventListener("change", onProviderChange);
140+
for (const providerEl of providerEls) {
141+
providerEl.addEventListener("change", onProviderChange);
142+
}
137143
onProviderChange();
138144

139145
function setBusy(isBusy, reason = "") {
@@ -467,7 +473,7 @@ async function runAgentTurn(userText) {
467473
const apiKey = apiKeyEl.value.trim();
468474
if (!apiKey) throw new Error("Missing API key");
469475

470-
const provider = PROVIDERS[providerEl.value];
476+
const provider = PROVIDERS[getProviderValue()];
471477
const { chat } = provider.api;
472478
const baseURL = provider.baseUrlDefault ? baseUrlEl.value.trim() : undefined;
473479

src/ifcchat/index.html

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,24 @@
1414
<section class="side">
1515
<div class="row">
1616
<label>Provider</label>
17-
<select id="provider" style="width: 100%;">
18-
<option value="openai">OpenAI</option>
19-
<option value="anthropic">Anthropic (Claude)</option>
20-
<option value="gemini">Gemini</option>
21-
<option value="openrouter">OpenRouter</option>
22-
</select>
17+
<div class="provider-tabs" role="radiogroup" aria-label="Provider">
18+
<label class="provider-tab">
19+
<input type="radio" name="provider" value="openai" checked />
20+
<span>OpenAI</span>
21+
</label>
22+
<label class="provider-tab">
23+
<input type="radio" name="provider" value="anthropic" />
24+
<span>Claude</span>
25+
</label>
26+
<label class="provider-tab">
27+
<input type="radio" name="provider" value="gemini" />
28+
<span>Gemini</span>
29+
</label>
30+
<label class="provider-tab">
31+
<input type="radio" name="provider" value="openrouter" />
32+
<span>OpenRouter</span>
33+
</label>
34+
</div>
2335
</div>
2436

2537
<div class="row">

src/ifcchat/style.css

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ main {
3232

3333
.side {
3434
border-right: 1px solid #ddd;
35-
padding: 100px 12px 12px 12px;
35+
padding: 12px;
3636
overflow: auto;
3737
background: #f9f9f9;
3838
}
@@ -234,7 +234,54 @@ section > .row > label .small {
234234
}
235235

236236
.side .row {
237-
margin-bottom: 32px;
237+
margin-bottom: 20px;
238+
}
239+
240+
.provider-tabs {
241+
display: flex;
242+
flex-wrap: wrap;
243+
gap: 6px;
244+
background: #00000010;
245+
padding: 6px 0 0 6px;
246+
}
247+
248+
.provider-tab {
249+
position: relative;
250+
display: inline-flex;
251+
}
252+
253+
.provider-tab input {
254+
position: absolute;
255+
opacity: 0;
256+
pointer-events: none;
257+
}
258+
259+
.provider-tab span {
260+
display: inline-flex;
261+
align-items: center;
262+
justify-content: center;
263+
min-height: 38px;
264+
padding: 8px;
265+
border: 1px solid #d0d0d0;
266+
border-radius: 2px 2px 0 0;
267+
background: #e8e8e8;
268+
color: #555;
269+
cursor: pointer;
270+
user-select: none;
271+
transition: background 0.15s, border-color 0.15s, color 0.15s;
272+
font-size: 75%;
273+
}
274+
275+
.provider-tab input:checked + span {
276+
background: #f9f9f9;
277+
border-color: #999;
278+
color: #111;
279+
border-bottom: none;
280+
}
281+
282+
.provider-tab input:focus-visible + span {
283+
outline: 2px solid #666;
284+
outline-offset: 2px;
238285
}
239286

240287
.row button {

0 commit comments

Comments
 (0)