diff --git a/ui/suite/chat/chat.css b/ui/suite/chat/chat.css index 2b3cd00..d670f7b 100644 --- a/ui/suite/chat/chat.css +++ b/ui/suite/chat/chat.css @@ -73,6 +73,7 @@ opacity: 0; transform: translateX(20px); } + to { opacity: 1; transform: translateX(0); @@ -97,11 +98,13 @@ /* Connection Status - use shared styles from app.css */ @keyframes pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.5; transform: scale(1.2); @@ -216,6 +219,7 @@ opacity: 0; transform: translateY(10px); } + to { opacity: 1; transform: translateY(0); @@ -551,9 +555,9 @@ footer { .suggestion-button { padding: 6px 12px; border-radius: 20px; - border: 2px solid var(--chat-color1, var(--suggestion-color, #4a9eff)); - background: var(--chat-color2, rgba(255, 255, 255, 0.15)); - color: var(--chat-color1, #ffffff); + border: 2px solid var(--chat-color2, #002147); + background: var(--chat-color2, #002147); + color: #ffffff; font-size: 12px; font-weight: 600; cursor: pointer; @@ -615,8 +619,8 @@ form.input-container { } .input-container:focus-within { - border-color: var(--accent, var(--accent-color, #3b82f6)); - box-shadow: 0 0 0 3px var(--accent-glow, rgba(59, 130, 246, 0.1)); + border-color: var(--chat-color1, var(--accent, #3b82f6)); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--chat-color1, var(--accent, #3b82f6)) 20%, transparent); } #messageInput { @@ -637,10 +641,14 @@ form.input-container { } @keyframes cursor-blink { - 0%, 50% { + + 0%, + 50% { caret-color: var(--accent, #3b82f6); } - 51%, 100% { + + 51%, + 100% { caret-color: transparent; } } @@ -673,7 +681,7 @@ form.input-container { } #sendBtn { - background: var(--accent, var(--accent-color, #3b82f6)); + background: var(--chat-color1, var(--accent, #3b82f6)); } #voiceBtn { @@ -689,7 +697,7 @@ form.input-container { } #sendBtn:hover { - background: var(--accent-hover, var(--accent, #2563eb)); + background: var(--chat-color1, var(--accent-hover, #2563eb)); } #voiceBtn:active, @@ -700,8 +708,8 @@ form.input-container { /* Dark/Sentient theme overrides */ [data-theme="dark"] #sendBtn, [data-theme="sentient"] #sendBtn { - background: var(--accent, #d4f505); - color: #000000; + background: var(--chat-color1, #d4f505); + color: #ffffff; } [data-theme="dark"] #voiceBtn, @@ -784,6 +792,7 @@ form.input-container { from { opacity: 0; } + to { opacity: 1; } @@ -1271,10 +1280,14 @@ form.input-container { } @keyframes thinkingBounce { - 0%, 80%, 100% { + + 0%, + 80%, + 100% { transform: scale(0.8); opacity: 0.5; } + 40% { transform: scale(1); opacity: 1; @@ -1331,6 +1344,7 @@ form.input-container { opacity: 0; transform: translateY(20px) scale(0.95); } + to { opacity: 1; transform: translateY(0) scale(1); @@ -1396,9 +1410,12 @@ form.input-container { } @keyframes bounce { - 0%, 100% { + + 0%, + 100% { transform: translateX(-50%) translateY(0); } + 50% { transform: translateX(-50%) translateY(-5px); } @@ -1432,10 +1449,14 @@ form.input-container { } @keyframes typing { - 0%, 60%, 100% { + + 0%, + 60%, + 100% { transform: translateY(0); } + 30% { transform: translateY(-8px); } -} +} \ No newline at end of file diff --git a/ui/suite/chat/chat.html b/ui/suite/chat/chat.html index 7cc89cb..de54398 100644 --- a/ui/suite/chat/chat.html +++ b/ui/suite/chat/chat.html @@ -979,13 +979,14 @@ // Get the theme manager's theme for this bot to check if user selected a different theme var botId = botName.toLowerCase(); + var botThemeKey = "gb-theme-" + botId; var botTheme = window.ThemeManager ? ( // Get bot-specific theme from theme manager's mapping (window.ThemeManager.getAvailableThemes && window.ThemeManager.getAvailableThemes().find(t => t.id === botId)) || // Fallback to localStorage - localStorage.getItem("gb-theme") - ) : localStorage.getItem("gb-theme"); + localStorage.getItem(botThemeKey) + ) : localStorage.getItem(botThemeKey); // Check if bot config has a theme-base setting var configThemeBase = config.theme_base || config["theme-base"] || "light"; @@ -993,7 +994,7 @@ // Only use bot config colors if: // 1. No theme has been explicitly selected by user (localStorage empty or default) // 2. AND the bot config's theme-base matches the current theme - var localStorageTheme = localStorage.getItem("gb-theme"); + var localStorageTheme = localStorage.getItem(botThemeKey); var useBotConfigColors = !localStorageTheme || localStorageTheme === "default" || localStorageTheme === configThemeBase; @@ -1006,6 +1007,7 @@ // Only set bot config colors if user hasn't selected a different theme if (useBotConfigColors) { + document.documentElement.setAttribute("data-has-bot-colors", "true"); document.documentElement.style.setProperty("--chat-color1", color1); document.documentElement.style.setProperty("--chat-color2", color2); document.documentElement.style.setProperty("--suggestion-color", color1); diff --git a/ui/suite/js/theme-manager.js b/ui/suite/js/theme-manager.js index 34e2ba1..ce433de 100644 --- a/ui/suite/js/theme-manager.js +++ b/ui/suite/js/theme-manager.js @@ -67,7 +67,8 @@ const ThemeManager = (() => { if (!theme.file) { currentThemeId = "default"; - localStorage.setItem("gb-theme", "default"); + const botId = getCurrentBotId(); + localStorage.setItem(`gb-theme-${botId}`, "default"); // Re-enable sentient theme for default document.documentElement.setAttribute("data-theme", "sentient"); updateDropdown(); @@ -81,7 +82,8 @@ const ThemeManager = (() => { link.onload = () => { console.log("✓ Theme loaded:", theme.name); currentThemeId = id; - localStorage.setItem("gb-theme", id); + const botId = getCurrentBotId(); + localStorage.setItem(`gb-theme-${botId}`, id); // Keep data-theme="sentient" on html so CSS selectors work // The inline styles will override the colors @@ -150,14 +152,16 @@ const ThemeManager = (() => { document.documentElement.style.setProperty("--border", borderHex); } - // Update ALL color-related CSS variables to match the theme - // This overrides any bot config colors - document.documentElement.style.setProperty("--chat-color1", `hsl(${primary})`); - document.documentElement.style.setProperty("--chat-color2", `hsl(${card})`); - document.documentElement.style.setProperty("--suggestion-color", `hsl(${primary})`); - document.documentElement.style.setProperty("--suggestion-bg", `hsl(${card})`); - document.documentElement.style.setProperty("--color1", `hsl(${primary})`); - document.documentElement.style.setProperty("--color2", `hsl(${card})`); + // Check if config.csv already set the primary color, we shouldn't wipe it + // Only update color and suggestion variables if they aren't marked as bot-config + if (document.documentElement.getAttribute("data-has-bot-colors") !== "true") { + document.documentElement.style.setProperty("--chat-color1", `hsl(${primary})`); + document.documentElement.style.setProperty("--chat-color2", `hsl(${card})`); + document.documentElement.style.setProperty("--suggestion-color", `hsl(${primary})`); + document.documentElement.style.setProperty("--suggestion-bg", `hsl(${card})`); + document.documentElement.style.setProperty("--color1", `hsl(${primary})`); + document.documentElement.style.setProperty("--color2", `hsl(${card})`); + } console.log("✓ Theme colors applied:", { bg: background, primary: primary }); updateDropdown(); @@ -198,13 +202,13 @@ const ThemeManager = (() => { // Then load the UI theme (CSS theme) // Priority: 1) localStorage user preference, 2) bot-specific theme, 3) default - let saved = localStorage.getItem("gb-theme"); + const botId = getCurrentBotId(); + let saved = localStorage.getItem(`gb-theme-${botId}`); if (!saved || !themes.find((t) => t.id === saved)) { // No user preference, try bot-specific theme - const botId = getCurrentBotId(); saved = botThemeMap[botId] || "light"; // Save to localStorage so it persists - localStorage.setItem("gb-theme", saved); + localStorage.setItem(`gb-theme-${botId}`, saved); } if (!themes.find((t) => t.id === saved)) saved = "default"; currentThemeId = saved; @@ -219,7 +223,8 @@ const ThemeManager = (() => { function setThemeFromServer(data) { // Save theme to localStorage for persistence across page loads - localStorage.setItem("gb-theme-data", JSON.stringify(data)); + const botId = getCurrentBotId(); + localStorage.setItem(`gb-theme-data-${botId}`, JSON.stringify(data)); // Load base theme if specified if (data.theme_base) { @@ -263,12 +268,13 @@ const ThemeManager = (() => { // Load saved theme from localStorage on page load function loadSavedTheme() { - const savedTheme = localStorage.getItem("gb-theme-data"); + const botId = getCurrentBotId(); + const savedTheme = localStorage.getItem(`gb-theme-data-${botId}`); if (savedTheme) { try { const data = JSON.parse(savedTheme); setThemeFromServer(data); - console.log("✓ Theme loaded from localStorage"); + console.log(`✓ Theme loaded from localStorage for ${botId}`); } catch (e) { console.warn("Failed to load saved theme:", e); }