From b0e8e1ced74b270e5488bcd609fff137ea9801a2 Mon Sep 17 00:00:00 2001 From: juanatsap Date: Wed, 8 Apr 2026 10:49:19 +0100 Subject: [PATCH] feat: evolve chat into CV Assistant mascot with help popup and suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Mascot identity: robot-happy-outline icon, "CV Assistant" branding - Help popup: onboarding card explaining what the mascot can do (EN/ES) - Suggested questions: 5 clickable chips that auto-submit (bilingual) - Typing indicator: three bouncing dots during agent response - Icon swap: mascot icon ↔ close icon via Hyperscript class toggle - Dark theme support for all new elements - Modular CSS loading in development, chat CSS always loaded separately --- static/css/04-interactive/_chat.css | 267 +++++++++++++++++--- templates/partials/widgets/chat-widget.html | 92 ++++++- 2 files changed, 313 insertions(+), 46 deletions(-) diff --git a/static/css/04-interactive/_chat.css b/static/css/04-interactive/_chat.css index f997480..45cb762 100644 --- a/static/css/04-interactive/_chat.css +++ b/static/css/04-interactive/_chat.css @@ -1,9 +1,12 @@ /* ============================================================================ - CHAT WIDGET + CHAT WIDGET — CV Assistant Mascot Floating AI chat panel for CV questions ============================================================================ */ -/* Toggle Button — left side, above the other fixed buttons */ +/* ========================================================================== + Toggle Button — left side, in the fixed button column + ========================================================================== */ + .chat-toggle-btn { position: fixed; bottom: 14rem; @@ -32,13 +35,34 @@ background: var(--accent-color-hover, #1d4ed8); } -/* Panel — anchored from the left, above the button */ +/* Icon swap: show mascot by default, close when active */ +.chat-toggle-btn .chat-icon-close { + display: none; +} + +.chat-toggle-btn.mascot-active { + opacity: 1; + background: var(--accent-color, #2563eb); +} + +.chat-toggle-btn.mascot-active .chat-icon-open { + display: none; +} + +.chat-toggle-btn.mascot-active .chat-icon-close { + display: inline-block; +} + +/* ========================================================================== + Panel — anchored from the left, above the button + ========================================================================== */ + .chat-panel { position: fixed; bottom: 18.5rem; left: 2rem; width: 380px; - max-height: 500px; + max-height: 520px; background: var(--bg-primary, #fff); border: 1px solid var(--border-color, #e2e8f0); border-radius: 12px; @@ -53,7 +77,10 @@ display: flex; } -/* Header */ +/* ========================================================================== + Header + ========================================================================== */ + .chat-header { display: flex; align-items: center; @@ -69,8 +96,25 @@ font-size: 1.2rem; } -.chat-close-btn { +.chat-help-btn { margin-left: auto; + background: none; + border: none; + color: #fff; + cursor: pointer; + font-size: 1.1rem; + opacity: 0.7; + transition: opacity 0.2s; + display: flex; + align-items: center; + padding: 0; +} + +.chat-help-btn:hover { + opacity: 1; +} + +.chat-close-btn { background: none; border: none; color: #fff; @@ -80,13 +124,73 @@ transition: opacity 0.2s; display: flex; align-items: center; + padding: 0; } .chat-close-btn:hover { opacity: 1; } -/* Messages Area */ +/* ========================================================================== + Help / Onboarding Card + ========================================================================== */ + +.chat-help-card { + display: none; + flex-direction: column; + align-items: center; + gap: 10px; + padding: 16px 20px; + margin: 12px; + background: var(--bg-secondary, #f1f5f9); + border: 1px solid var(--border-color, #e2e8f0); + border-radius: 10px; + text-align: center; + animation: helpFadeIn 0.25s ease; +} + +.chat-help-card.visible { + display: flex; +} + +@keyframes helpFadeIn { + from { opacity: 0; transform: translateY(-6px); } + to { opacity: 1; transform: translateY(0); } +} + +.chat-help-icon { + font-size: 2rem; + color: var(--accent-color, #2563eb); + line-height: 1; +} + +.chat-help-text { + font-size: 0.8rem; + line-height: 1.5; + color: var(--text-secondary, #475569); + margin: 0; +} + +.chat-help-dismiss { + background: var(--accent-color, #2563eb); + color: #fff; + border: none; + border-radius: 6px; + padding: 5px 16px; + font-size: 0.75rem; + font-weight: 600; + cursor: pointer; + transition: background 0.2s; +} + +.chat-help-dismiss:hover { + background: var(--accent-color-hover, #1d4ed8); +} + +/* ========================================================================== + Messages Area + ========================================================================== */ + .chat-messages { flex: 1; overflow-y: auto; @@ -94,8 +198,8 @@ display: flex; flex-direction: column; gap: 12px; - max-height: 340px; - min-height: 120px; + max-height: 260px; + min-height: 80px; } /* Message Bubbles */ @@ -147,12 +251,91 @@ border: 1px solid #fecaca; } -/* Input Area */ +/* ========================================================================== + Typing Indicator + ========================================================================== */ + +.chat-typing { + display: none; + align-items: center; + gap: 4px; + padding: 8px 16px; +} + +/* Show when HTMX request is in-flight */ +.chat-typing.htmx-request { + display: flex; +} + +.chat-typing-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--text-secondary, #94a3b8); + animation: typingBounce 1.4s infinite ease-in-out both; +} + +.chat-typing-dot:nth-child(1) { animation-delay: 0s; } +.chat-typing-dot:nth-child(2) { animation-delay: 0.16s; } +.chat-typing-dot:nth-child(3) { animation-delay: 0.32s; } + +@keyframes typingBounce { + 0%, 80%, 100% { + transform: scale(0.6); + opacity: 0.4; + } + 40% { + transform: scale(1); + opacity: 1; + } +} + +/* ========================================================================== + Suggested Question Chips + ========================================================================== */ + +.chat-suggestions { + display: flex; + gap: 6px; + padding: 8px 12px; + overflow-x: auto; + border-top: 1px solid var(--border-color, #e2e8f0); + scrollbar-width: none; /* Firefox */ +} + +.chat-suggestions::-webkit-scrollbar { + display: none; /* Chrome/Safari */ +} + +.chat-chip { + flex-shrink: 0; + background: var(--bg-secondary, #f1f5f9); + color: var(--text-primary, #1e293b); + border: 1px solid var(--border-color, #e2e8f0); + border-radius: 16px; + padding: 4px 12px; + font-size: 0.72rem; + cursor: pointer; + transition: all 0.2s ease; + white-space: nowrap; + line-height: 1.4; +} + +.chat-chip:hover { + background: var(--accent-color, #2563eb); + color: #fff; + border-color: var(--accent-color, #2563eb); +} + +/* ========================================================================== + Input Area + ========================================================================== */ + .chat-input-area { display: flex; align-items: center; gap: 8px; - padding: 12px; + padding: 10px 12px; border-top: 1px solid var(--border-color, #e2e8f0); background: var(--bg-primary, #fff); } @@ -193,33 +376,17 @@ background: var(--accent-color-hover, #1d4ed8); } -/* Spinner */ -.chat-spinner { - display: none; -} +/* ========================================================================== + Responsive + ========================================================================== */ -.chat-spinner.htmx-request { - display: flex; - align-items: center; -} - -.spin { - animation: spin 1s linear infinite; -} - -@keyframes spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} - -/* Responsive */ @media (max-width: 480px) { .chat-panel { bottom: 0; left: 0; right: 0; width: 100%; - max-height: 60vh; + max-height: 70vh; border-radius: 12px 12px 0 0; } @@ -227,9 +394,16 @@ bottom: 12rem; left: 1rem; } + + .chat-messages { + max-height: 200px; + } } -/* Theme: Clean (dark) */ +/* ========================================================================== + Dark Theme Support (theme-clean) + ========================================================================== */ + .theme-clean .chat-panel { background: #1e293b; border-color: #334155; @@ -256,3 +430,32 @@ border-color: #334155; color: #e2e8f0; } + +.theme-clean .chat-help-card { + background: #334155; + border-color: #475569; +} + +.theme-clean .chat-help-text { + color: #cbd5e1; +} + +.theme-clean .chat-suggestions { + border-top-color: #334155; +} + +.theme-clean .chat-chip { + background: #334155; + color: #e2e8f0; + border-color: #475569; +} + +.theme-clean .chat-chip:hover { + background: var(--accent-color, #2563eb); + color: #fff; + border-color: var(--accent-color, #2563eb); +} + +.theme-clean .chat-typing-dot { + background: #64748b; +} diff --git a/templates/partials/widgets/chat-widget.html b/templates/partials/widgets/chat-widget.html index 5299a37..01d69c2 100644 --- a/templates/partials/widgets/chat-widget.html +++ b/templates/partials/widgets/chat-widget.html @@ -1,41 +1,108 @@ {{define "chat-widget"}} {{if .ChatEnabled}} - +
- - {{if eq .Lang "es"}}Pregunta sobre este CV{{else}}Ask about this CV{{end}} + + {{if eq .Lang "es"}}Asistente del CV{{else}}CV Assistant{{end}} +
+ +
+
+ +
+

+ {{if eq .Lang "es"}}¡Soy el Asistente del CV! Puedo responder preguntas sobre la experiencia profesional, proyectos, habilidades y formación de Juan. Prueba a hacer clic en una sugerencia o escribe tu propia pregunta.{{else}}I'm the CV Assistant! I can answer questions about Juan's professional experience, projects, skills, and education. Try clicking a suggestion or type your own question.{{end}} +

+ +
+
- {{if eq .Lang "es"}}¡Hola! Puedo responder preguntas sobre este currículum. Prueba a preguntar sobre experiencia, proyectos, tecnologías o formación.{{else}}Hi! I can answer questions about this CV. Try asking about experience, projects, technologies, or education.{{end}} + {{if eq .Lang "es"}}¡Hola! Pregúntame lo que quieras sobre este CV.{{else}}Hi! Ask me anything about this CV.{{end}}
+ +
+ + + +
+ + +
+ {{if eq .Lang "es"}} + + + + + + {{else}} + + + + + + {{end}} +
+
@@ -44,15 +111,12 @@ id="chat-input" name="message" class="chat-input" - placeholder="{{if eq .Lang "es"}}Escribe una pregunta...{{else}}Type a question...{{end}}" + placeholder="{{if eq .Lang "es"}}Pregunta algo sobre el CV...{{else}}Ask something about the CV...{{end}}" autocomplete="off" required> -
- -
{{end}}