feat: cog menu for layout modes, mobile viewport fix, better separation
Header UX: - Replace 5 icon buttons with single cog (gear) dropdown menu - Cog menu shows all layout options with icons + labels - Help and Close buttons stay visible outside the cog - Active mode highlighted in green Mobile fixes: - Fix viewport overflow (100vw + max-width: 100vw) - Stronger shadow (0 -4px 20px) for clear CV/chat separation - Rounded corners (12px) on top for recognizable chat window - Hide desktop-only modes (side panel, floating, full) from cog on mobile - max-height: 50vh ensures CV always visible above Dark mode: - Cog menu styled for dark backgrounds
This commit is contained in:
@@ -224,12 +224,12 @@
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
/* Header actions — icon buttons with tooltips */
|
||||
/* Header actions — cog menu + help + close */
|
||||
.chat-header-actions {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1px;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.chat-mode-btn {
|
||||
@@ -244,7 +244,6 @@
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
transition: all 0.15s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chat-mode-btn:hover {
|
||||
@@ -252,36 +251,60 @@
|
||||
background: rgba(255,255,255,0.15);
|
||||
}
|
||||
|
||||
.chat-mode-btn.active {
|
||||
color: #fff;
|
||||
background: rgba(255,255,255,0.2);
|
||||
/* Cog dropdown wrapper */
|
||||
.chat-cog-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Native tooltip via title attr — enhanced with CSS for consistent look */
|
||||
.chat-mode-btn[title]:hover::after {
|
||||
content: attr(title);
|
||||
.chat-cog-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: calc(100% + 6px);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--black-bar, #2b2b2b);
|
||||
color: #fff;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.65rem;
|
||||
font-family: 'Source Sans Pro', sans-serif;
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
z-index: 1001;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
||||
right: 0;
|
||||
background: var(--paper-bg, #fff);
|
||||
border: 1px solid var(--border-light, #e0e0e0);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2);
|
||||
padding: 4px;
|
||||
z-index: 1002;
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.chat-header-divider {
|
||||
width: 1px;
|
||||
height: 16px;
|
||||
background: rgba(255,255,255,0.25);
|
||||
margin: 0 3px;
|
||||
.chat-cog-menu.chat-cog-open {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.chat-cog-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 10px;
|
||||
border: none;
|
||||
background: none;
|
||||
border-radius: 5px;
|
||||
font-size: 0.72rem;
|
||||
font-family: 'Source Sans Pro', sans-serif;
|
||||
color: var(--text-secondary, #333);
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.chat-cog-item:hover {
|
||||
background: var(--accent-green, #27ae60);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.chat-cog-item.active {
|
||||
background: rgba(39, 174, 96, 0.12);
|
||||
color: var(--accent-green, #27ae60);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.chat-cog-item iconify-icon {
|
||||
font-size: 0.9rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
@@ -751,6 +774,20 @@
|
||||
border-bottom-color: #4eca81;
|
||||
}
|
||||
|
||||
[data-color-theme="dark"] .chat-cog-menu {
|
||||
background: #333;
|
||||
border-color: #555;
|
||||
}
|
||||
|
||||
[data-color-theme="dark"] .chat-cog-item {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
[data-color-theme="dark"] .chat-cog-item.active {
|
||||
background: rgba(78, 202, 129, 0.15);
|
||||
color: #4eca81;
|
||||
}
|
||||
|
||||
/* Auto dark (system preference) */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
[data-color-theme="auto"] .chat-panel {
|
||||
@@ -787,6 +824,20 @@
|
||||
color: #4eca81;
|
||||
border-bottom-color: #4eca81;
|
||||
}
|
||||
|
||||
[data-color-theme="auto"] .chat-cog-menu {
|
||||
background: #333;
|
||||
border-color: #555;
|
||||
}
|
||||
|
||||
[data-color-theme="auto"] .chat-cog-item {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
[data-color-theme="auto"] .chat-cog-item.active {
|
||||
background: rgba(78, 202, 129, 0.15);
|
||||
color: #4eca81;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
@@ -794,14 +845,17 @@
|
||||
========================================================================== */
|
||||
|
||||
@media (max-width: 480px) {
|
||||
/* Default compact: bottom sheet */
|
||||
/* Default compact: bottom sheet with clear separation */
|
||||
.chat-panel {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
max-height: 55vh;
|
||||
border-radius: 8px 8px 0 0;
|
||||
width: 100vw;
|
||||
max-width: 100vw;
|
||||
max-height: 50vh;
|
||||
border-radius: 12px 12px 0 0;
|
||||
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.25);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-toggle-btn {
|
||||
@@ -810,31 +864,28 @@
|
||||
}
|
||||
|
||||
.chat-messages {
|
||||
max-height: 180px;
|
||||
max-height: 160px;
|
||||
}
|
||||
|
||||
/* Hide desktop-only layout modes on mobile */
|
||||
.chat-mode-btn[data-mode="chat-half"],
|
||||
.chat-mode-btn[data-mode="chat-float"],
|
||||
.chat-mode-btn[data-mode="chat-full"] {
|
||||
/* Hide desktop-only cog items on mobile */
|
||||
.chat-cog-item[data-mode="chat-half"],
|
||||
.chat-cog-item[data-mode="chat-float"],
|
||||
.chat-cog-item[data-mode="chat-full"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Show mobile split button */
|
||||
.chat-mode-btn[data-mode="chat-split"] {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Mobile split: CV on top, chat on bottom half */
|
||||
.chat-panel.chat-split {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: auto;
|
||||
width: 100%;
|
||||
width: 100vw;
|
||||
max-width: 100vw;
|
||||
height: 50vh;
|
||||
max-height: 50vh;
|
||||
border-radius: 8px 8px 0 0;
|
||||
border-radius: 12px 12px 0 0;
|
||||
box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.3);
|
||||
border-top: 2px solid var(--accent-green, #27ae60);
|
||||
}
|
||||
|
||||
@@ -851,12 +902,14 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: auto;
|
||||
width: 100%;
|
||||
width: 100vw;
|
||||
max-width: 100vw;
|
||||
height: auto;
|
||||
max-height: 55vh;
|
||||
border-radius: 8px 8px 0 0;
|
||||
border: 1px solid var(--border-light, #e0e0e0);
|
||||
max-height: 50vh;
|
||||
border-radius: 12px 12px 0 0;
|
||||
border: none;
|
||||
resize: none;
|
||||
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
/* Wave position follows mobile button */
|
||||
@@ -865,11 +918,6 @@
|
||||
right: calc(1rem + 38px);
|
||||
}
|
||||
|
||||
/* Tooltips: prevent overflow on mobile */
|
||||
.chat-mode-btn[title]:hover::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Tighter header on mobile */
|
||||
.chat-header {
|
||||
padding: 8px 10px;
|
||||
@@ -880,11 +928,10 @@
|
||||
font-size: 0.85rem;
|
||||
padding: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide mobile split button on desktop */
|
||||
@media (min-width: 481px) {
|
||||
.chat-mode-btn[data-mode="chat-split"] {
|
||||
display: none;
|
||||
/* Cog menu on mobile */
|
||||
.chat-cog-menu {
|
||||
right: -8px;
|
||||
min-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,29 +17,40 @@
|
||||
<iconify-icon icon="mdi:robot-happy-outline"></iconify-icon>
|
||||
<span>{{if eq .Lang "es"}}Asistente del CV{{else}}CV Assistant{{end}}</span>
|
||||
<div class="chat-header-actions">
|
||||
<button class="chat-mode-btn active" data-mode="" title="{{if eq .Lang "es"}}Compacto{{else}}Compact{{end}}" onclick="setChatSize('')">
|
||||
<iconify-icon icon="mdi:message-outline"></iconify-icon>
|
||||
</button>
|
||||
<button class="chat-mode-btn" data-mode="chat-split" title="{{if eq .Lang "es"}}Mitad de pantalla{{else}}Half screen{{end}}" onclick="setChatSize('chat-split')">
|
||||
<iconify-icon icon="mdi:arrow-split-horizontal"></iconify-icon>
|
||||
</button>
|
||||
<button class="chat-mode-btn" data-mode="chat-half" title="{{if eq .Lang "es"}}Panel lateral{{else}}Side panel{{end}}" onclick="setChatSize('chat-half')">
|
||||
<iconify-icon icon="mdi:page-layout-sidebar-right"></iconify-icon>
|
||||
</button>
|
||||
<button class="chat-mode-btn" data-mode="chat-float" title="{{if eq .Lang "es"}}Flotante — arrastra para mover{{else}}Floating — drag to move{{end}}" onclick="setChatSize('chat-float')">
|
||||
<iconify-icon icon="mdi:cursor-move"></iconify-icon>
|
||||
</button>
|
||||
<button class="chat-mode-btn" data-mode="chat-full" title="{{if eq .Lang "es"}}Pantalla completa{{else}}Full screen{{end}}" onclick="setChatSize('chat-full')">
|
||||
<iconify-icon icon="mdi:arrow-expand-all"></iconify-icon>
|
||||
</button>
|
||||
<span class="chat-header-divider"></span>
|
||||
<!-- Cog menu for layout modes -->
|
||||
<div class="chat-cog-wrapper">
|
||||
<button class="chat-mode-btn" title="{{if eq .Lang "es"}}Opciones{{else}}Options{{end}}" onclick="toggleChatCog()">
|
||||
<iconify-icon icon="mdi:cog"></iconify-icon>
|
||||
</button>
|
||||
<div id="chat-cog-menu" class="chat-cog-menu">
|
||||
<button class="chat-cog-item active" data-mode="" onclick="setChatSize(''); closeChatCog()">
|
||||
<iconify-icon icon="mdi:message-outline"></iconify-icon>
|
||||
{{if eq .Lang "es"}}Compacto{{else}}Compact{{end}}
|
||||
</button>
|
||||
<button class="chat-cog-item" data-mode="chat-split" onclick="setChatSize('chat-split'); closeChatCog()">
|
||||
<iconify-icon icon="mdi:arrow-split-horizontal"></iconify-icon>
|
||||
{{if eq .Lang "es"}}Mitad{{else}}Half screen{{end}}
|
||||
</button>
|
||||
<button class="chat-cog-item" data-mode="chat-half" onclick="setChatSize('chat-half'); closeChatCog()">
|
||||
<iconify-icon icon="mdi:page-layout-sidebar-right"></iconify-icon>
|
||||
{{if eq .Lang "es"}}Lateral{{else}}Side panel{{end}}
|
||||
</button>
|
||||
<button class="chat-cog-item" data-mode="chat-float" onclick="setChatSize('chat-float'); closeChatCog()">
|
||||
<iconify-icon icon="mdi:cursor-move"></iconify-icon>
|
||||
{{if eq .Lang "es"}}Flotante{{else}}Floating{{end}}
|
||||
</button>
|
||||
<button class="chat-cog-item" data-mode="chat-full" onclick="setChatSize('chat-full'); closeChatCog()">
|
||||
<iconify-icon icon="mdi:arrow-expand-all"></iconify-icon>
|
||||
{{if eq .Lang "es"}}Completo{{else}}Full screen{{end}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="chat-mode-btn"
|
||||
title="{{if eq .Lang "es"}}Ayuda{{else}}Help{{end}}"
|
||||
commandfor="chat-help-modal"
|
||||
command="show-modal">
|
||||
<iconify-icon icon="mdi:help-circle-outline"></iconify-icon>
|
||||
</button>
|
||||
<span class="chat-header-divider"></span>
|
||||
<button class="chat-mode-btn" title="{{if eq .Lang "es"}}Cerrar{{else}}Close{{end}}" onclick="toggleChatPanel()">
|
||||
<iconify-icon icon="mdi:close"></iconify-icon>
|
||||
</button>
|
||||
@@ -142,6 +153,18 @@ function toggleChatPanel() {
|
||||
}
|
||||
}
|
||||
|
||||
// Cog menu toggle
|
||||
function toggleChatCog() {
|
||||
document.getElementById('chat-cog-menu').classList.toggle('chat-cog-open');
|
||||
}
|
||||
function closeChatCog() {
|
||||
document.getElementById('chat-cog-menu').classList.remove('chat-cog-open');
|
||||
}
|
||||
// Close cog when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!e.target.closest('.chat-cog-wrapper')) closeChatCog();
|
||||
});
|
||||
|
||||
// Show user message bubble immediately in chat
|
||||
var chatBubblePending = false;
|
||||
function appendUserBubble(text) {
|
||||
@@ -228,9 +251,9 @@ function setChatSize(size) {
|
||||
panel.style.width = '';
|
||||
panel.style.height = '';
|
||||
if (size) panel.classList.add(size);
|
||||
// Update active button
|
||||
document.querySelectorAll('.chat-mode-btn[data-mode]').forEach(function(btn) {
|
||||
btn.classList.toggle('active', btn.getAttribute('data-mode') === size);
|
||||
// Update active item in cog menu
|
||||
document.querySelectorAll('.chat-cog-item[data-mode]').forEach(function(item) {
|
||||
item.classList.toggle('active', item.getAttribute('data-mode') === size);
|
||||
});
|
||||
// Enable/disable drag
|
||||
if (size === 'chat-float') {
|
||||
|
||||
Reference in New Issue
Block a user