diff --git a/models.go b/models.go
index b9a7297..8d03672 100644
--- a/models.go
+++ b/models.go
@@ -167,5 +167,9 @@ func GetModelTags(model openrouter.Model, m *Model) {
}
}
+ if model.Pricing.Prompt == "0" && model.Pricing.Completion == "0" {
+ m.Tags = append(m.Tags, "free")
+ }
+
sort.Strings(m.Tags)
}
diff --git a/static/css/dropdown.css b/static/css/dropdown.css
index 170e7d5..8da726f 100644
--- a/static/css/dropdown.css
+++ b/static/css/dropdown.css
@@ -26,6 +26,7 @@
background-size: contain;
background-repeat: no-repeat;
transform: rotate(180deg);
+ flex-shrink: 0;
}
.dropdown .cont {
@@ -74,8 +75,13 @@
background: #2c2f44;
}
+.dropdown .opt.active {
+ background: #24273a;
+}
+
.dropdown .opt.filtered {
display: none;
+ font-weight: 500;
}
.dropdown .label {
@@ -98,26 +104,52 @@
background-repeat: no-repeat;
}
+.dropdown .selected:not(.all-tags) .tags:has(.tag:nth-child(3)) {
+ display: flex;
+ height: 2px;
+ gap: 1px;
+ width: 100%;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+}
+
+.dropdown .selected:not(.all-tags) .tags:has(.tag:nth-child(3)) .tag {
+ background: var(--color);
+ width: 100%;
+ height: 2px;
+}
+
.tags .tag.reasoning {
+ --color: #c6a0f6;
background-image: url(icons/tags/reasoning.svg);
}
.tags .tag.tools {
+ --color: #eed49f;
background-image: url(icons/tags/tools.svg);
}
.tags .tag.vision {
+ --color: #ed8796;
background-image: url(icons/tags/vision.svg);
}
.tags .tag.json {
+ --color: #7dc4e4;
background-image: url(icons/tags/json.svg);
}
.tags .tag.image {
+ --color: #f4dbd6;
background-image: url(icons/tags/image.svg);
}
+.tags .tag.free {
+ --color: #a6da95;
+ background-image: url(icons/tags/free.svg);
+}
+
.tags .tag.all {
background-image: url(icons/tags/all.svg);
}
@@ -127,4 +159,4 @@
border-top: 2px solid #494d64;
font-size: 15px;
padding: 4px 6px;
-}
+}
\ No newline at end of file
diff --git a/static/css/icons/tags/free.svg b/static/css/icons/tags/free.svg
new file mode 100644
index 0000000..49103a2
--- /dev/null
+++ b/static/css/icons/tags/free.svg
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/static/css/icons/tags/image.svg b/static/css/icons/tags/image.svg
index 57ca652..409d25c 100644
--- a/static/css/icons/tags/image.svg
+++ b/static/css/icons/tags/image.svg
@@ -1,7 +1,7 @@
-
+
\ No newline at end of file
diff --git a/static/css/icons/tags/vision.svg b/static/css/icons/tags/vision.svg
index 2c11e48..63ecf2f 100644
--- a/static/css/icons/tags/vision.svg
+++ b/static/css/icons/tags/vision.svg
@@ -1,7 +1,7 @@
-
+
\ No newline at end of file
diff --git a/static/js/chat.js b/static/js/chat.js
index 8fd1426..7fdc6c9 100644
--- a/static/js/chat.js
+++ b/static/js/chat.js
@@ -1641,7 +1641,8 @@
el.title = [
model.name,
separator,
- `Created:\t\t${formatTimestamp(model.created)}`,
+ `Tags:\t\t${model.tags?.join(", ") || "-"}`,
+ `Created:\t${formatTimestamp(model.created)}`,
`Pricing/1M:\t${formatMoney(model.pricing.input)} In | ${formatMoney(model.pricing.output)} Out`,
model.pricing.image ? `Images/1K:\t${formatMoney(model.pricing.image * 1000)} Out` : null,
separator,
@@ -1659,7 +1660,7 @@
modelList.push(model);
});
- dropdown($model, 4);
+ dropdown($model, 6);
// render prompts
data.prompts.unshift({
diff --git a/static/js/dropdown.js b/static/js/dropdown.js
index 75efbd5..7e7bb48 100644
--- a/static/js/dropdown.js
+++ b/static/js/dropdown.js
@@ -64,6 +64,10 @@
this.#_selected.addEventListener("click", () => {
this.#_dropdown.classList.toggle("open");
+
+ const selection = this.#options[this.#selected];
+
+ selection.el.scrollIntoView();
});
this.#_dropdown.appendChild(this.#_selected);
@@ -171,8 +175,18 @@
return;
}
+ for (const key in this.#options) {
+ const option = this.#options[key];
+
+ option.el.classList.remove("active");
+ }
+
const selection = this.#options[this.#selected];
+ selection.el.classList.add("active");
+
+ this.#_selected.classList.toggle("all-tags", selection.tags.length >= this.#maxTags);
+
this.#_selected.title = selection.title || this.#_select.title;
this.#_selected.innerHTML = selection.el.innerHTML;