Skip to content

Commit bfdd7d4

Browse files
committed
improve themes + user avatars
1 parent e8ed377 commit bfdd7d4

File tree

16 files changed

+445
-368
lines changed

16 files changed

+445
-368
lines changed

llms/extensions/app/__init__.py

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -435,9 +435,20 @@ async def compact_thread(request):
435435

436436
async def get_user_avatar(req):
437437
user = ctx.get_username(req)
438-
mode = req.query.get("mode", "light")
438+
theme = req.query.get("theme")
439+
440+
# Fall back to default 'user' avatar
441+
mode = "dark" if theme == "dark" else "light"
442+
bg_color = "#1e3a8a" if mode == "dark" else "#dbeafe"
443+
text_color = "#f3f4f6" if mode == "dark" else "#111827"
444+
445+
if theme:
446+
config = get_theme_config(theme, req)
447+
vars = config.get("vars", {})
448+
mode = vars.get("colorScheme", mode)
449+
bg_color = vars.get("--user-bg", bg_color)
450+
text_color = vars.get("--user-text", text_color)
439451

440-
# Cache for 1 hour # "Cache-Control": "public, max-age=3600",
441452
headers = {"Content-Type": "image/svg+xml"}
442453

443454
candidate_paths = [
@@ -456,10 +467,6 @@ async def get_user_avatar(req):
456467
headers["Content-Type"] = "image/png" if path.endswith(".png") else "image/svg+xml"
457468
return web.FileResponse(path, headers=headers)
458469

459-
# Fall back to default 'user' avatar
460-
bg_color = "#1e3a8a" if mode == "dark" else "#bfdbfe"
461-
text_color = "#f3f4f6" if mode == "dark" else "#111827"
462-
463470
default_avatar = f"""
464471
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" style="color:{text_color}">
465472
<circle cx="16" cy="16" r="16" fill="{bg_color}"/>
@@ -473,9 +480,21 @@ async def get_user_avatar(req):
473480
ctx.add_get("/avatar/user", get_user_avatar)
474481

475482
async def get_agent_avatar(req):
476-
mode = req.query.get("mode", "light")
483+
theme = req.query.get("theme")
484+
485+
# Fall back to default 'user' avatar
486+
mode = "dark" if theme == "dark" else "light"
487+
# Fall back to default 'agent' avatar
488+
bg_color = "#1e293b" if mode == "dark" else "#f3f4f6"
489+
text_color = "#f1f5f9" if mode == "dark" else "#111827"
490+
491+
if theme:
492+
config = get_theme_config(theme, req)
493+
vars = config.get("vars", {})
494+
mode = vars.get("colorScheme", mode)
495+
bg_color = vars.get("--assistant-bg", bg_color)
496+
text_color = vars.get("--assistant-text", text_color)
477497

478-
# Cache for 1 hour # "Cache-Control": "public, max-age=3600",
479498
headers = {"Content-Type": "image/svg+xml"}
480499

481500
candidate_paths = [
@@ -490,10 +509,6 @@ async def get_agent_avatar(req):
490509
headers["Content-Type"] = "image/png" if path.endswith(".png") else "image/svg+xml"
491510
return web.FileResponse(path, headers=headers)
492511

493-
# Fall back to default 'agent' avatar
494-
bg_color = "#1f2937" if mode == "dark" else "#eceef1"
495-
text_color = "#f3f4f6" if mode == "dark" else "#111827"
496-
497512
default_avatar = f"""
498513
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" style="color:{text_color}">
499514
<circle cx="16" cy="16" r="16" fill="{bg_color}"/>
@@ -622,6 +637,20 @@ def get_theme_roots(request):
622637
themes_dirs.append(os.path.join(ctx.get_user_path(user), "themes"))
623638
return themes_dirs
624639

640+
def get_theme_config(theme, request=None):
641+
themes_dirs = get_theme_roots(request)
642+
for themes_dir in themes_dirs:
643+
if os.path.exists(themes_dir):
644+
theme_path = os.path.join(themes_dir, theme)
645+
config_path = os.path.join(theme_path, "theme.json")
646+
if os.path.isdir(theme_path) and os.path.exists(config_path):
647+
try:
648+
with open(config_path) as f:
649+
return json.load(f)
650+
except Exception as e:
651+
ctx.dbg(f"Error loading theme {theme}: {e}")
652+
return None
653+
625654
# THEMES
626655
async def get_themes(request):
627656
themes = {}
@@ -631,10 +660,10 @@ async def get_themes(request):
631660
if os.path.exists(themes_dir):
632661
for theme_name in os.listdir(themes_dir):
633662
theme_path = os.path.join(themes_dir, theme_name)
634-
styles_path = os.path.join(theme_path, "theme.json")
635-
if os.path.isdir(theme_path) and os.path.exists(styles_path):
663+
config_path = os.path.join(theme_path, "theme.json")
664+
if os.path.isdir(theme_path) and os.path.exists(config_path):
636665
try:
637-
with open(styles_path, encoding="utf-8") as f:
666+
with open(config_path, encoding="utf-8") as f:
638667
themes[theme_name] = json.load(f)
639668
except Exception as e:
640669
if hasattr(ctx, "err"):

llms/extensions/app/themes/blue_smoke/theme.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,20 @@
1010
"colorScheme": "dark",
1111
"--background-image": "url(/themes/blue_smoke/ui/bg.webp)",
1212
"--scrollbar-track-bg": "#0a0a1a",
13-
"--scrollbar-thumb-bg": "#1e3a5f"
13+
"--scrollbar-thumb-bg": "#1e3a5f",
14+
"--user-bg": "#1e40af66",
15+
"--user-text": "#eff6ff",
16+
"--user-border": "#60a5fa33",
17+
"--assistant-bg": "#0000004D",
18+
"--assistant-text": "#eff6ff",
19+
"--assistant-border": "#60a5fa33",
20+
"--tw-prose-code": "#93c5fd",
21+
"--tw-prose-code-bg": "#1e3a8a66",
22+
"--tw-prose-code-border": "#1e40af",
23+
"--tw-prose-table-bg": "#00000066",
24+
"--tw-prose-th-bg": "#1e3a8a66",
25+
"--tw-prose-th-borders": "#1e40af",
26+
"--tw-prose-td-borders": "#1e40af"
1427
},
1528
"styles": {
1629
"chromeBorder": "border-blue-500/60",

llms/extensions/app/themes/dark.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@
1616
"--scrollbar-thumb-bg": "#4b5563",
1717
"--primary-bg": "#1f2937",
1818
"--secondary-bg": "#1f2937",
19-
"--secondary-border": "#374151"
19+
"--secondary-border": "#374151",
20+
"--user-bg": "#1e3a8a",
21+
"--user-text": "#f3f4f6",
22+
"--user-border": "#374151",
23+
"--assistant-bg": "#1e293b",
24+
"--assistant-text": "#f1f5f9",
25+
"--assistant-border": "#334155"
2026
},
2127
"styles": {
2228
"chromeBorder": "border-gray-700",
@@ -76,8 +82,6 @@
7682
"threadItemActiveBorder": "border-blue-600",
7783
"threadItemActive": "bg-blue-900 border-blue-700",
7884
"threadItem": "border-transparent hover:bg-gray-800",
79-
"tabButton": "text-gray-400 hover:text-white hover:bg-white",
80-
"messageUser": "bg-blue-900 text-gray-100 border border-blue-700",
81-
"messageAssistant": "bg-gray-800 text-gray-100 border border-gray-700"
85+
"tabButton": "text-gray-400 hover:text-white hover:bg-white"
8286
}
8387
}

llms/extensions/app/themes/light.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@
1616
"--scrollbar-thumb-bg": "#d1d5db",
1717
"--primary-bg": "#ffffff",
1818
"--secondary-bg": "#f9fafb",
19-
"--secondary-border": "#e5e7eb"
19+
"--secondary-border": "#e5e7eb",
20+
"--user-bg": "#dbeafe",
21+
"--user-text": "#111827",
22+
"--user-border": "#bfdbfe",
23+
"--assistant-bg": "#f3f4f6",
24+
"--assistant-text": "#111827",
25+
"--assistant-border": "#e5e7eb"
2026
},
2127
"styles": {
2228
"chromeBorder": "border-gray-200",
@@ -76,8 +82,6 @@
7682
"threadItemActiveBorder": "border-blue-300",
7783
"threadItemActive": "bg-blue-100 border-blue-200",
7884
"threadItem": "border-transparent hover:bg-gray-100",
79-
"tabButton": "text-gray-500 hover:text-gray-900 hover:bg-gray-200",
80-
"messageUser": "bg-blue-100 text-gray-900 border border-blue-200",
81-
"messageAssistant": "bg-gray-100 text-gray-900 border border-gray-200"
85+
"tabButton": "text-gray-500 hover:text-gray-900 hover:bg-gray-200"
8286
}
8387
}

llms/extensions/app/themes/light_sky/theme.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
"--primary-bg": "#ffffff",
1111
"--secondary-bg": "#f0f9ff",
1212
"--secondary-border": "#bae6fd",
13+
"--user-bg": "#dbeafe",
14+
"--user-text": "#111827",
15+
"--user-border": "#bfdbfe",
16+
"--assistant-bg": "#f3f4f6",
17+
"--assistant-text": "#111827",
18+
"--assistant-border": "#e5e7eb",
1319
"--tw-prose-counters": "#7dd3fc",
1420
"--tw-prose-bullets": "#7dd3fc"
1521
},

llms/extensions/app/themes/light_slate/theme.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99
"--scrollbar-thumb-bg": "#cbd5e1cc",
1010
"--primary-bg": "#ffffff",
1111
"--secondary-bg": "#f8fafc",
12-
"--secondary-border": "#e2e8f0"
12+
"--secondary-border": "#e2e8f0",
13+
"--user-bg": "#dbeafe",
14+
"--user-text": "#111827",
15+
"--user-border": "#bfdbfe",
16+
"--assistant-bg": "#f3f4f6",
17+
"--assistant-text": "#111827",
18+
"--assistant-border": "#e5e7eb"
1319
},
1420
"styles": {
1521
"chromeBorder": "border-slate-300",

llms/extensions/app/themes/matrix/theme.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,22 @@
1313
"--scrollbar-thumb-bg": "#064e3b",
1414
"--secondary-bg": "#052e16",
1515
"--secondary-border": "#166534",
16+
"--user-bg": "#052e1666",
17+
"--user-text": "#4ade80",
18+
"--user-border": "#166534",
19+
"--assistant-bg": "#00000066",
20+
"--assistant-text": "#86efac",
21+
"--assistant-border": "#22c55e4D",
1622
"--tw-prose-counters": "#22c55e",
1723
"--tw-prose-bullets": "#22c55e",
18-
"--tw-prose-links": "#4ade80"
24+
"--tw-prose-links": "#4ade80",
25+
"--tw-prose-code": "#4ade80",
26+
"--tw-prose-code-bg": "#052e1666",
27+
"--tw-prose-code-border": "#166534",
28+
"--tw-prose-table-bg": "#00000066",
29+
"--tw-prose-th-bg": "#052e1666",
30+
"--tw-prose-th-borders": "#166534",
31+
"--tw-prose-td-borders": "#166534"
1932
},
2033
"styles": {
2134
"chromeBorder": "border-green-500/50",

llms/extensions/app/themes/nord/theme.json

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,20 @@
1717
"--scrollbar-thumb-bg": "#2e3440",
1818
"--primary-bg": "#1f2937",
1919
"--secondary-bg": "#5e81ac",
20-
"--secondary-border": "#5e81ac"
20+
"--secondary-border": "#5e81ac",
21+
"--user-bg": "#3b4252",
22+
"--user-text": "#eceff4",
23+
"--user-border": "#5e81ac80",
24+
"--assistant-bg": "#0000001A",
25+
"--assistant-text": "#eceff4",
26+
"--assistant-border": "#d8dee977",
27+
"--tw-prose-code": "#eceff4",
28+
"--tw-prose-code-bg": "#3b4252",
29+
"--tw-prose-code-border": "#5e81ac",
30+
"--tw-prose-table-bg": "#2e344066",
31+
"--tw-prose-th-bg": "#5e81ac",
32+
"--tw-prose-th-borders": "#5e81ac",
33+
"--tw-prose-td-borders": "#5e81ac"
2134
},
2235
"nord": {
2336
"--color-nord-100": "#eceff4",
@@ -64,13 +77,10 @@
6477
"popoverButton": "hover:bg-nord-700",
6578
"popoverButtonActive": "bg-nord-900/30",
6679
"codeTag": "text-nord-300 bg-nord-700",
67-
"codeTagStrong": "border border-blue-800 text-nord-300 bg-blue-900/30",
80+
"codeTagStrong": "border border-frost-700 text-nord-300 bg-nord-900/30",
6881
"tagButtonGroup": "rounded-xl bg-frost-700/30 border border-frost-700/80",
6982
"tagButton": "cursor-pointer border border-transparent bg-nord-800 text-nord-300 hover:bg-nord-700 hover:text-nord-100 transition-all duration-200",
7083
"tagButtonActive": "border border-transparent bg-frost-700 text-white shadow-sm transition-all duration-200",
71-
"tagButtonStrongActive": "border border-transparent bg-nord-green text-nord-900 font-medium shadow-md hover:opacity-90 transition-all duration-200",
72-
"tagLabel": "border border-transparent text-nord-300 bg-nord-800 shadow-sm transition-all duration-200",
73-
"tagLabelHover": "hover:bg-nord-700 hover:text-nord-100 transition-all duration-200",
7484
"panel": "border-gray-700 bg-gray-800/50",
7585
"infoCard": "rounded-lg bg-nord-900/80 border border-nord-700 backdrop-blur-sm",
7686
"card": "rounded-lg bg-nord-800 border border-nord-300/40",
@@ -95,7 +105,6 @@
95105
"threadItemActiveBorder": "border-nord-100",
96106
"threadItemActive": "bg-nord-700/80 border-nord-300/50",
97107
"threadItem": "border-transparent hover:bg-nord-700/40",
98-
"messageUser": "bg-nord-800 text-nord-100 border border-frost-700/50",
99-
"messageAssistant": "text-nord-100 border border-nord-300/30 bg-black/10 backdrop-blur-md"
108+
"messageAssistant": "bg-[var(--assistant-bg)] text-[var(--assistant-text)] border-[var(--assistant-border)] backdrop-blur-md"
100109
}
101110
}

llms/extensions/app/themes/soft_pink/theme.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,21 @@
1313
"--scrollbar-thumb-bg": "#fbcfe899",
1414
"--secondary-bg": "#fdf2f8",
1515
"--secondary-border": "#fbcfe8",
16+
"--user-bg": "#dbeafe",
17+
"--user-text": "#111827",
18+
"--user-border": "#bfdbfe",
19+
"--assistant-bg": "#f3f4f6",
20+
"--assistant-text": "#111827",
21+
"--assistant-border": "#e5e7eb",
1622
"--tw-prose-counters": "#f472b6",
1723
"--tw-prose-bullets": "#f472b6",
18-
"--tw-prose-links": "#ec4899"
24+
"--tw-prose-links": "#ec4899",
25+
"--tw-prose-code": "#831843",
26+
"--tw-prose-code-bg": "#fbcfe866",
27+
"--tw-prose-code-border": "#fbcfe8",
28+
"--tw-prose-th-bg": "#fbcfe866",
29+
"--tw-prose-th-borders": "#fbcfe8",
30+
"--tw-prose-td-borders": "#fbcfe8"
1931
},
2032
"styles": {
2133
"chromeBorder": "border-pink-200",

0 commit comments

Comments
 (0)