hermes/frontend/css/sidebar.css
Nico ccee249618 v0.6.42: Hermes chat UI — Vue3/TS/Vite, audio STT/TTS, sidebar rail, MCP event loop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:35:10 +02:00

786 lines
20 KiB
CSS

/* ── Sidebar layout ───────────────────────────────────────────── */
:root {
--sidebar-width: 240px;
--sidebar-collapsed-width: 48px;
--sidebar-header-height: 40px; /* aligns with content-top in views */
}
/* ── App body: sidebar + content column ── */
.app-body {
flex: 1;
min-height: 0;
display: flex;
flex-direction: row;
overflow: hidden;
}
.main-column {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* ── Sidebar ── */
.app-sidebar {
position: fixed;
top: var(--panel-gap);
left: var(--panel-gap);
height: calc(100% - var(--panel-gap) * 2);
width: var(--sidebar-width);
flex-shrink: 0;
display: flex;
flex-direction: column;
background: var(--panel-bg);
border-radius: var(--radius-panel);
box-shadow: var(--panel-shadow);
padding: 0 6px;
transition: width 0.2s cubic-bezier(0.4, 0, 0.2, 1);
overflow: visible;
z-index: 100;
}
/* Fade text/indicators on expand/collapse */
.sidebar-logo-label,
.sidebar-room-name,
.sidebar-segment-label,
.sidebar-channel-indicators,
.sidebar-room-mode-btn,
.sidebar-chevron-btn,
.sidebar-capture-btn,
.sidebar-link span,
.sidebar-user-name {
opacity: 1;
transition: opacity 0.15s ease 0.1s; /* 0.1s delay so width expands first */
}
.app-sidebar.is-collapsed .sidebar-logo-label,
.app-sidebar.is-collapsed .sidebar-room-name,
.app-sidebar.is-collapsed .sidebar-segment-label,
.app-sidebar.is-collapsed .sidebar-channel-indicators,
.app-sidebar.is-collapsed .sidebar-room-mode-btn,
.app-sidebar.is-collapsed .sidebar-chevron-btn,
.app-sidebar.is-collapsed .sidebar-capture-btn,
.app-sidebar.is-collapsed .sidebar-link span,
.app-sidebar.is-collapsed .sidebar-user-name {
opacity: 0;
transition: opacity 0.05s ease; /* fade out fast */
pointer-events: none;
position: relative;
z-index: 20;
}
.app-sidebar.is-collapsed {
width: var(--sidebar-collapsed-width);
}
/* When expanded: enable click target */
.app-sidebar:not(.is-collapsed) .sidebar-close-target {
pointer-events: auto;
}
/* Legacy gradient shadow — replaced by panel box-shadow */
.sidebar-shadow {
display: none;
}
/* Invisible click target to close sidebar — behind sidebar content */
.sidebar-close-target {
position: fixed;
inset: 0;
z-index: -1;
opacity: 0;
pointer-events: none;
}
/* ── Sidebar header (logo + collapse) ── */
.sidebar-header {
height: var(--sidebar-header-height);
display: flex;
align-items: center;
flex-shrink: 0;
gap: 0;
}
.sidebar-header { overflow: hidden; }
.app-sidebar.is-collapsed .sidebar-header { cursor: pointer; }
/* Brand: logo + name centered (flex:1 fills remaining space) */
.sidebar-brand {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
height: 100%;
color: var(--text);
text-decoration: none;
cursor: pointer;
transition: opacity 0.15s;
overflow: hidden;
white-space: nowrap;
/* Offset for chevron width so brand is visually centered in sidebar */
padding-right: var(--sidebar-collapsed-width);
}
.sidebar-brand:hover { opacity: 0.8; text-decoration: none; }
/* Chevron rotation animation */
.sidebar-chevron-anim {
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.sidebar-brand-logo,
.sidebar-brand-icon {
width: 18px;
height: 18px;
flex-shrink: 0;
}
.sidebar-brand-name {
font-weight: 600;
font-size: var(--text-base);
color: var(--text);
white-space: nowrap;
}
/* Toggle button: right side when expanded, centered when collapsed */
.sidebar-toggle-btn {
width: var(--sidebar-collapsed-width);
height: 100%;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
background: none;
border: none;
cursor: pointer;
color: var(--text-dim);
transition: color 0.15s, background 0.15s;
}
.sidebar-toggle-btn:hover { color: var(--text); background: color-mix(in srgb, var(--accent) 8%, transparent); }
/* Icon slot: fixed 48px centered area — never moves on collapse */
.sidebar-logo-img,
.sidebar-theme-icon {
flex-shrink: 0;
width: var(--sidebar-collapsed-width);
display: flex;
align-items: center;
justify-content: center;
}
.sidebar-logo-img {
height: 18px;
object-fit: contain;
padding: 0 14px;
box-sizing: border-box;
}
.sidebar-theme-icon {
height: 20px;
stroke-width: 1.5;
color: var(--accent);
padding: 0 14px;
box-sizing: border-box;
}
.sidebar-logo-label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--text);
letter-spacing: 0.02em;
}
.sidebar-chevron-icon {
margin-left: auto;
opacity: 0.5;
flex-shrink: 0;
}
.sidebar-chevron-btn {
width: var(--sidebar-collapsed-width);
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
background: none;
border: none;
cursor: pointer;
color: var(--text-dim);
transition: color 0.15s, background 0.15s;
}
.sidebar-chevron-btn:hover { color: var(--text); background: color-mix(in srgb, var(--accent) 8%, transparent); }
/* ── Rooms (agents) ── */
.sidebar-rooms {
flex: 1 1 0;
min-height: 0;
padding: 4px 0;
display: flex;
flex-direction: column;
gap: 1px;
overflow-x: hidden;
overflow-y: auto;
}
/* Segment label */
.sidebar-segment-label {
padding: 8px 14px 2px;
height: 27px;
flex-shrink: 0;
font-size: var(--text-base);
font-weight: 600;
letter-spacing: 0.08em;
text-transform: capitalize;
color: var(--text-dim);
opacity: 0.5;
user-select: none;
}
/* Agent row: icon slot is always 48px wide, centered */
.sidebar-room {
display: flex;
align-items: center;
gap: 0;
padding: 0 10px 0 0;
height: 30px;
min-height: 30px;
flex-shrink: 0;
color: var(--text-dim);
text-decoration: none;
font-size: var(--text-base);
white-space: nowrap;
overflow: hidden;
transition: background 0.12s, color 0.12s;
border-radius: var(--radius-sm);
cursor: pointer;
}
.sidebar-room:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--text); }
.sidebar-room.active { color: var(--text); background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* ── Role dots ── */
.sidebar-room-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
position: relative;
/* Center dot in 48px icon slot (minus 6px panel padding when expanded) */
margin-left: 14px;
margin-right: 12px;
}
/* owner: solid filled dot */
.dot-owner {
background: var(--accent);
box-shadow: 0 0 0 0px transparent;
}
/* member: outlined ring (dot + same-color ring) */
.dot-member {
background: transparent;
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 60%, transparent);
}
/* common: small dot + outer ring gap */
.dot-common {
background: #34d399;
box-shadow: 0 0 0 2px color-mix(in srgb, #34d399 40%, transparent);
}
/* guest: dashed ring (simulate with border) */
.dot-guest {
background: transparent;
box-shadow: 0 0 0 2px color-mix(in srgb, var(--text-dim) 40%, transparent);
}
/* utility: dim solid */
.dot-utility {
background: color-mix(in srgb, var(--text-dim) 35%, transparent);
}
.sidebar-room-placeholder { pointer-events: none; opacity: 0; }
.sidebar-room-name {
overflow: hidden;
text-overflow: ellipsis;
}
.sidebar-room-mode-btn {
margin-left: auto;
color: var(--text-dim);
opacity: 0.55;
white-space: nowrap;
flex-shrink: 0;
text-decoration: none;
padding: 1px 6px;
border-radius: 4px;
cursor: pointer;
}
.sidebar-room-mode-btn:hover { opacity: 1; color: var(--text); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.sidebar-room-mode-btn.active { opacity: 1; color: var(--accent); }
/* Collapsed: keep segment labels same height for Y alignment, just hide text */
.sidebar-segment-label.is-collapsed {
visibility: hidden;
}
/* ── Spacer ── */
.sidebar-spacer {
flex: 1;
}
/* ── Home section (above agents) ── */
.sidebar-home-section {
}
/* ── Nav links (viewer, dev) ── */
.sidebar-nav-links {
display: flex;
flex-direction: column;
gap: 2px;
padding: 4px 0;
overflow: hidden;
}
/* Shared row style: icon in fixed 48px slot, text after */
.sidebar-link {
display: flex;
align-items: center;
gap: 0;
padding: 0;
height: 32px;
color: var(--text-dim);
text-decoration: none;
font-size: var(--text-base);
white-space: nowrap;
overflow: hidden;
transition: background 0.12s, color 0.12s;
cursor: pointer;
background: none;
border: none;
width: 100%;
text-align: left;
}
.sidebar-link:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--text); }
.sidebar-link.active { color: var(--accent); }
.sidebar-link svg {
flex-shrink: 0;
/* Center 16px icon in 48px slot (minus 6px panel padding) */
width: 16px;
height: 16px;
margin-left: 10px;
margin-right: 10px;
}
/* ── Channel state indicators (dual: private + public) ── */
.sidebar-room { position: relative; }
.sidebar-channel-indicators {
position: absolute;
right: 44px;
top: 0;
display: flex;
gap: 3px;
align-items: center;
height: 30px;
pointer-events: none;
font-size: var(--text-base);
}
.sidebar-ch-dot { opacity: 0.7; }
.sidebar-ch-dot.ch-running { animation: pulse 2s infinite; }
.sidebar-ch-dot.ch-ready { opacity: 0.3; }
.sidebar-ch-dot.ch-fresh { opacity: 0.6; }
.sidebar-ch-dot.ch-nosession { opacity: 0.15; }
.sidebar-ch-dot.ch-none { opacity: 0.15; }
/* ── Connection status ── */
.sidebar-connection {
padding: 0;
}
.sidebar-connection .sidebar-link { color: var(--text-dim); opacity: 0.4; }
.sidebar-connection.active .sidebar-link { color: var(--success, #22c55e); opacity: 0.7; }
/* ── Connection status panel ── */
.sidebar-conn-wrap {
position: relative;
}
/* ── Takeover status ── */
.sidebar-takeover-wrap {
padding: 0;
position: relative;
}
.sidebar-takeover-row {
display: flex;
align-items: center;
}
.sidebar-takeover-row .sidebar-link { flex: 1; }
.sidebar-takeover-wrap .sidebar-link { color: var(--text-dim); opacity: 0.4; }
.sidebar-takeover-wrap.active .sidebar-link { color: var(--success, #22c55e); opacity: 0.7; }
.sidebar-takeover-wrap.active .sidebar-link svg { animation: pulse 2s infinite; }
.sidebar-capture-btn {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
border-radius: var(--radius-sm);
background: none;
border: none;
cursor: pointer;
color: var(--text-dim);
opacity: 0.5;
transition: opacity 0.15s, color 0.15s, background 0.15s;
}
.sidebar-capture-btn:hover { opacity: 1; background: color-mix(in srgb, var(--accent) 8%, transparent); }
.sidebar-capture-btn.active { color: var(--success, #22c55e); opacity: 1; }
.sidebar-capture-btn.active svg { animation: pulse 2s infinite; }
/* ── Bottom (user) ── */
.sidebar-bottom {
padding: 4px 0;
position: relative;
}
.sidebar-user-wrap {
position: relative;
}
.sidebar-user-btn {
display: flex;
align-items: center;
gap: 0;
padding: 0;
height: 32px;
width: 100%;
background: none;
border: none;
cursor: pointer;
color: var(--text-dim);
font-size: var(--text-base);
white-space: nowrap;
overflow: hidden;
transition: background 0.12s, color 0.12s;
text-align: left;
}
.sidebar-user-btn:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--text); }
.sidebar-user-btn svg {
flex-shrink: 0;
width: 16px;
height: 16px;
margin-left: 10px;
margin-right: 10px;
}
.sidebar-user-name { overflow: hidden; text-overflow: ellipsis; }
/* ── Panel backdrop: closes any open panel on click ── */
.sidebar-panel-backdrop {
position: fixed;
inset: 0;
z-index: 150;
}
/* ── Shared popup panel style ── */
.sidebar-panel,
.sidebar-user-menu {
position: absolute;
bottom: 0;
left: 100%;
margin-left: 4px;
width: 220px;
background: var(--panel-bg);
border-radius: var(--radius-panel);
box-shadow: var(--panel-shadow);
z-index: 200; /* above .sidebar-panel-backdrop (150) */
overflow: hidden;
}
.sidebar-panel-header {
padding: 8px 12px 4px;
font-size: var(--text-base);
font-weight: 600;
letter-spacing: 0.06em;
text-transform: capitalize;
color: var(--text-dim);
}
.sidebar-panel-token {
padding: 8px 12px;
cursor: pointer;
transition: background 0.12s;
position: relative;
}
.sidebar-panel-token:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.sidebar-panel-token code {
font-size: var(--text-base);
color: var(--accent);
word-break: break-all;
}
.sidebar-panel-copied {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
font-size: var(--text-base);
color: var(--success, #22c55e);
}
.sidebar-panel-row {
display: flex;
justify-content: space-between;
padding: 6px 12px;
font-size: var(--text-base);
color: var(--text-dim);
}
.sidebar-panel-item {
display: block;
width: 100%;
padding: 7px 12px;
background: none;
border: none;
cursor: pointer;
color: var(--text);
font-size: var(--text-base);
text-align: left;
transition: background 0.12s;
}
.sidebar-panel-item:hover { background: color-mix(in srgb, var(--error) 12%, transparent); color: var(--error); }
.sidebar-user-menu-header {
padding: 8px 12px 4px;
font-size: var(--text-base);
color: var(--text-dim);
}
.sidebar-user-menu-item {
display: block;
width: 100%;
padding: 7px 12px;
background: none;
border: none;
cursor: pointer;
color: var(--text);
font-size: var(--text-base);
text-align: left;
transition: background 0.12s;
}
.sidebar-user-menu-item:hover { background: color-mix(in srgb, var(--error) 12%, transparent); color: var(--error); }
/* Collapsed: smaller menu width */
.app-sidebar.is-collapsed .sidebar-user-menu {
width: 160px;
}
/* ── Sidebar spacer (reserves rail width on all screens) ── */
.sidebar-spacer {
display: block;
width: var(--sidebar-collapsed-width);
min-width: var(--sidebar-collapsed-width);
max-width: var(--sidebar-collapsed-width);
flex: 0 0 var(--sidebar-collapsed-width);
}
/* ── Version ── */
.sidebar-version-wrap {
position: relative;
flex-shrink: 0;
}
.sidebar-version-wrap.is-hidden {
visibility: hidden;
pointer-events: none;
}
.sidebar-version {
display: block;
width: 100%;
padding: 4px 12px;
text-align: left;
font-size: var(--text-base);
color: var(--text-dim);
opacity: 0.4;
cursor: pointer;
user-select: none;
background: none;
border: none;
transition: opacity 0.15s;
}
.sidebar-version:hover { opacity: 0.8; }
.sidebar-version-panel {
bottom: 100%;
margin-bottom: 4px;
}
/* ── Large screens: sidebar in flow, pushes content ── */
@media (min-width: 1024px) {
.app-sidebar {
position: relative;
top: auto;
left: auto;
height: auto;
z-index: auto;
margin: var(--panel-gap);
margin-right: 0;
}
.app-sidebar:not(.is-collapsed) .sidebar-close-target {
pointer-events: none;
}
/* Spacer matches sidebar width (not fixed 48px) */
.sidebar-spacer {
display: none;
}
}
/* ── Mobile tweaks ── */
@media (max-width: 480px) {
/* Panels: constrain to viewport */
.sidebar-panel,
.sidebar-user-menu {
width: min(220px, calc(100vw - var(--sidebar-collapsed-width) - 16px)) !important;
}
/* Hide takeover panel on mobile — use /dev on desktop */
.sidebar-takeover-wrap .sidebar-panel { display: none !important; }
}
/* Top section: default agent + files — shrink-to-fit, shrink when needed */
.sidebar-top-section {
flex-shrink: 0;
display: flex;
flex-direction: column;
min-height: 0;
}
.sidebar-top-section.has-tree {
flex-shrink: 1;
overflow: hidden;
}
.sidebar-top-section .sidebar-home {
flex-shrink: 0;
padding: 4px 0;
}
.sidebar-file-scroll {
min-height: 0;
font-size: var(--text-base);
overflow: hidden;
}
/* File sections: toggle row + collapsible tree */
.sidebar-file-section {
display: flex;
flex-direction: column;
min-height: 0;
flex-shrink: 0;
}
.sidebar-file-section.is-open {
flex-shrink: 1;
min-height: 0;
overflow: hidden;
}
.sidebar-file-toggle {
flex-shrink: 0;
}
.sidebar-file-chev {
margin-left: auto;
color: var(--text-dim);
opacity: 0.3;
flex-shrink: 0;
margin-right: 10px;
}
.sidebar-file-toggle:hover .sidebar-file-chev { opacity: 1; }
/* Agents nav link */
.sidebar-nav-agents {
flex-shrink: 0;
padding: 4px 0;
}
/* File tree in sidebar — inherit sidebar font */
.sidebar-panel-section .file-tree {
font-size: var(--text-base);
font-family: inherit;
}
/* Segment divider inside agents panel */
.sidebar-segment-divider {
font-size: var(--text-base);
text-transform: capitalize;
letter-spacing: 0.05em;
color: var(--text-dim);
opacity: 0.5;
padding: 6px 14px 2px;
}
/* ── Collapsed top ── */
.sidebar-collapsed-top {
display: flex;
flex-direction: column;
gap: 2px;
padding: 4px 0;
}
/* ── Flex spacer (both states) ── */
.sidebar-flex-spacer {
flex: 1;
}
/* ── Unified bottom section ── */
.sidebar-bottom-section {
display: flex;
flex-direction: column;
gap: 2px;
padding: 4px 0;
position: relative;
z-index: 160; /* above backdrop (150) so buttons remain clickable */
}
.sidebar-bottom {
position: relative;
z-index: 160;
}
.sidebar-bottom-section .sidebar-conn-link.active { color: var(--success, #22c55e); }
.sidebar-bottom-section .sidebar-takeover-wrap.active .sidebar-link { color: var(--success, #22c55e); }
.sidebar-bottom-section .sidebar-takeover-wrap.active .sidebar-link svg { animation: pulse 2s infinite; }
.sidebar-version-link {
color: var(--text-dim) !important;
opacity: 0.5;
}
.sidebar-version-link:hover { opacity: 0.8 !important; }
.sidebar-version-text {
font-size: 0.65rem;
white-space: nowrap;
width: var(--sidebar-collapsed-width);
text-align: center;
/* Don't fade on collapse — it's the only content */
opacity: 1 !important;
pointer-events: auto;
}
/* SidebarPanel and system section above backdrop */
.sidebar-panel-section { position: relative; z-index: 160; }
.sidebar-system-section { position: relative; z-index: 160; overflow: visible; }
.sidebar-system-content { overflow: visible; }
.sidebar-system-toggle { opacity: 0.5; }
.sidebar-system-toggle:hover { opacity: 0.8; }
/* Clean up inside SidebarPanel */
.sidebar-panel-section .sidebar-nav-links { padding: 0; }
/* Compact bottom items: same size expanded and collapsed */
.sidebar-bottom-section .sidebar-link,
.sidebar-panel-content .sidebar-conn-link,
.sidebar-panel-content .sidebar-takeover-wrap .sidebar-link,
.sidebar-panel-content .sidebar-version-link {
height: 30px;
}
.sidebar-panel-content .sidebar-conn-link svg,
.sidebar-panel-content .sidebar-takeover-wrap .sidebar-link svg {
width: 14px;
height: 14px;
margin-left: 11px;
margin-right: 10px;
}
.sidebar-bottom-section .sidebar-link svg {
width: 14px;
height: 14px;
margin-left: 11px;
margin-right: 10px;
}