Fix messages layout and improve scrollbar styling
Switch messages area to fixed positioning with centered transform for better layout stability. Enhance scrollbar appearance with thin style, improved colors
This commit is contained in:
parent
42f5ce609c
commit
8c2b17c615
4 changed files with 459 additions and 39 deletions
|
|
@ -195,14 +195,16 @@ body::before {
|
|||
position: relative;
|
||||
}
|
||||
#messages {
|
||||
flex: 1;
|
||||
overflow-y: scroll;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 100px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 20px 20px 140px;
|
||||
padding: 80px 20px 40px;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
scroll-behavior: smooth;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
|
@ -320,6 +322,7 @@ footer {
|
|||
z-index: 100;
|
||||
transition: all 0.3s;
|
||||
backdrop-filter: blur(20px);
|
||||
height: 90px;
|
||||
}
|
||||
.suggestions-container {
|
||||
display: flex;
|
||||
|
|
@ -617,47 +620,83 @@ footer {
|
|||
text-decoration: underline;
|
||||
}
|
||||
/* Claude-style scrollbar - thin, subtle, always visible but more prominent on hover */
|
||||
#messages::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
#messages {
|
||||
/* Firefox scrollbar */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(128, 128, 128, 0.3) transparent;
|
||||
}
|
||||
|
||||
[data-theme="dark"] #messages {
|
||||
scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
|
||||
}
|
||||
|
||||
/* Webkit (Chrome, Safari, Edge) scrollbar */
|
||||
#messages::-webkit-scrollbar {
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
#messages::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#messages::-webkit-scrollbar-thumb {
|
||||
background: rgba(128, 128, 128, 0.2);
|
||||
border-radius: 4px;
|
||||
background: rgba(128, 128, 128, 0.3);
|
||||
border-radius: 6px;
|
||||
border: 3px solid transparent;
|
||||
background-clip: padding-box;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
#messages:hover::-webkit-scrollbar-thumb {
|
||||
background: rgba(128, 128, 128, 0.4);
|
||||
background: rgba(128, 128, 128, 0.5);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
#messages::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(128, 128, 128, 0.6);
|
||||
background: rgba(128, 128, 128, 0.7);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
[data-theme="dark"] #messages::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
[data-theme="dark"] #messages:hover::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
[data-theme="dark"] #messages::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
/* Fallback for other elements */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--border) transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--border);
|
||||
border-radius: 3px;
|
||||
border-radius: 5px;
|
||||
border: 2px solid transparent;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--fg);
|
||||
opacity: 0.3;
|
||||
opacity: 0.5;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.sidebar {
|
||||
|
|
@ -665,7 +704,9 @@ footer {
|
|||
left: -100%;
|
||||
}
|
||||
#messages {
|
||||
padding: 20px 16px 140px;
|
||||
padding: 80px 16px 40px;
|
||||
top: 0;
|
||||
bottom: 100px;
|
||||
}
|
||||
.float-menu {
|
||||
left: 12px;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
</footer>
|
||||
<button class="scroll-to-bottom" id="scrollToBottom">↓</button>
|
||||
<div class="context-indicator" id="contextIndicator">
|
||||
<div>Context</div>
|
||||
<div>Context</div></div>
|
||||
<div id="contextPercentage">0%</div>
|
||||
<div class="context-progress">
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -5,21 +5,364 @@
|
|||
<title>General Bots</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="css/app.css" />
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
background: #ffffff;
|
||||
color: #202124;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Floating minimal header */
|
||||
.float-header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 64px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
z-index: 1000;
|
||||
background: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.float-header > * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* Left side - Logo */
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.logo-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
cursor: pointer;
|
||||
padding: 8px 12px;
|
||||
border-radius: 12px;
|
||||
transition: all 0.3s;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.logo-wrapper:hover {
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.logo-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: url("https://pragmatismo.com.br/icons/general-bots.svg")
|
||||
center/contain no-repeat;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #202124;
|
||||
}
|
||||
|
||||
/* Right side - Apps menu and avatar */
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* Google-style dots menu button */
|
||||
.apps-menu-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s;
|
||||
color: #5f6368;
|
||||
position: relative;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.apps-menu-btn:hover {
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.apps-menu-btn:active {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* Apps dropdown */
|
||||
.apps-dropdown {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
right: 80px;
|
||||
width: 320px;
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow:
|
||||
0 1px 2px 0 rgba(60, 64, 67, 0.3),
|
||||
0 2px 6px 2px rgba(60, 64, 67, 0.15);
|
||||
padding: 20px;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(-10px);
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.apps-dropdown.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.app-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.app-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 16px 8px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: #202124;
|
||||
transition: background 0.2s;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.app-item:hover {
|
||||
background: rgba(26, 115, 232, 0.04);
|
||||
border-color: rgba(26, 115, 232, 0.2);
|
||||
}
|
||||
|
||||
.app-item.active {
|
||||
background: rgba(26, 115, 232, 0.08);
|
||||
border-color: rgba(26, 115, 232, 0.3);
|
||||
}
|
||||
|
||||
.app-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
margin-bottom: 8px;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.app-item.active .app-icon {
|
||||
background: #e8f0fe;
|
||||
}
|
||||
|
||||
.app-item span {
|
||||
font-size: 13px;
|
||||
color: #5f6368;
|
||||
}
|
||||
|
||||
/* User avatar */
|
||||
.user-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: #1a73e8;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.user-avatar:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* Main content area */
|
||||
#main-content {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Dark mode support */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: #202124;
|
||||
color: #e8eaed;
|
||||
}
|
||||
|
||||
.float-header {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.logo-wrapper {
|
||||
background: rgba(32, 33, 36, 0.9);
|
||||
}
|
||||
|
||||
.logo-wrapper:hover {
|
||||
background: rgba(32, 33, 36, 1);
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: #e8eaed;
|
||||
}
|
||||
|
||||
.apps-menu-btn {
|
||||
color: #9aa0a6;
|
||||
}
|
||||
|
||||
.apps-menu-btn {
|
||||
background: rgba(32, 33, 36, 0.9);
|
||||
}
|
||||
|
||||
.apps-menu-btn:hover {
|
||||
background: rgba(32, 33, 36, 1);
|
||||
}
|
||||
|
||||
.apps-dropdown {
|
||||
background: #292a2d;
|
||||
box-shadow:
|
||||
0 1px 3px 1px rgba(0, 0, 0, 0.15),
|
||||
0 4px 8px 3px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.app-item {
|
||||
color: #e8eaed;
|
||||
}
|
||||
|
||||
.app-item:hover {
|
||||
background: rgba(138, 180, 248, 0.08);
|
||||
border-color: rgba(138, 180, 248, 0.2);
|
||||
}
|
||||
|
||||
.app-icon {
|
||||
background: #3c4043;
|
||||
}
|
||||
|
||||
.app-item.active .app-icon {
|
||||
background: #394457;
|
||||
}
|
||||
|
||||
.app-item span {
|
||||
color: #9aa0a6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav id="main-nav">
|
||||
<div class="logo">⚡ General Bots</div>
|
||||
<a href="#chat" class="nav-link active" data-section="chat"
|
||||
>💬 Chat</a
|
||||
>
|
||||
<a href="#drive" class="nav-link" data-section="drive">📁 Drive</a>
|
||||
<a href="#tasks" class="nav-link" data-section="tasks">✓ Tasks</a>
|
||||
<a href="#mail" class="nav-link" data-section="mail">✉ Mail</a>
|
||||
</nav>
|
||||
<!-- Minimal floating header -->
|
||||
<div class="float-header">
|
||||
<!-- Left: General Bots logo -->
|
||||
<div class="header-left">
|
||||
<div class="logo-wrapper" onclick="window.location.reload()">
|
||||
<div class="logo-icon"></div>
|
||||
<div class="logo-text">General Bots</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right: Apps menu and user avatar -->
|
||||
<div class="header-right">
|
||||
<button class="apps-menu-btn" id="appsMenuBtn" title="Apps">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
>
|
||||
<circle cx="5" cy="5" r="2"></circle>
|
||||
<circle cx="12" cy="5" r="2"></circle>
|
||||
<circle cx="19" cy="5" r="2"></circle>
|
||||
<circle cx="5" cy="12" r="2"></circle>
|
||||
<circle cx="12" cy="12" r="2"></circle>
|
||||
<circle cx="19" cy="12" r="2"></circle>
|
||||
<circle cx="5" cy="19" r="2"></circle>
|
||||
<circle cx="12" cy="19" r="2"></circle>
|
||||
<circle cx="19" cy="19" r="2"></circle>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="apps-dropdown" id="appsDropdown">
|
||||
<div class="app-grid">
|
||||
<a
|
||||
class="app-item active"
|
||||
href="#chat"
|
||||
data-section="chat"
|
||||
>
|
||||
<div class="app-icon">💬</div>
|
||||
<span>Chat</span>
|
||||
</a>
|
||||
<a class="app-item" href="#drive" data-section="drive">
|
||||
<div class="app-icon">📁</div>
|
||||
<span>Drive</span>
|
||||
</a>
|
||||
<a class="app-item" href="#tasks" data-section="tasks">
|
||||
<div class="app-icon">✔</div>
|
||||
<span>Tasks</span>
|
||||
</a>
|
||||
<a class="app-item" href="#mail" data-section="mail">
|
||||
<div class="app-icon">✉</div>
|
||||
<span>Mail</span>
|
||||
</a>
|
||||
<a
|
||||
class="app-item"
|
||||
href="#calendar"
|
||||
data-section="calendar"
|
||||
>
|
||||
<div class="app-icon">📅</div>
|
||||
<span>Calendar</span>
|
||||
</a>
|
||||
<a class="app-item" href="#notes" data-section="notes">
|
||||
<div class="app-icon">📝</div>
|
||||
<span>Notes</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-avatar" id="userAvatar" title="User Account">
|
||||
<span>U</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content">
|
||||
<!-- Sections will be loaded dynamically -->
|
||||
|
|
@ -28,24 +371,54 @@
|
|||
<!-- Load scripts -->
|
||||
<script src="js/layout.js"></script>
|
||||
<script>
|
||||
// Simple navigation state management without Alpine
|
||||
// Apps menu toggle
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const nav = document.getElementById("main-nav");
|
||||
const links = nav.querySelectorAll(".nav-link");
|
||||
const appsBtn = document.getElementById("appsMenuBtn");
|
||||
const appsDropdown = document.getElementById("appsDropdown");
|
||||
const appItems = document.querySelectorAll(".app-item");
|
||||
|
||||
links.forEach((link) => {
|
||||
link.addEventListener("click", (e) => {
|
||||
// Toggle apps menu
|
||||
appsBtn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
appsDropdown.classList.toggle("show");
|
||||
});
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
document.addEventListener("click", () => {
|
||||
appsDropdown.classList.remove("show");
|
||||
});
|
||||
|
||||
// Prevent dropdown from closing when clicking inside
|
||||
appsDropdown.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// Handle app selection
|
||||
appItems.forEach((item) => {
|
||||
item.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
const section = link.dataset.section;
|
||||
const section = item.dataset.section;
|
||||
|
||||
// Update active state
|
||||
links.forEach((l) => l.classList.remove("active"));
|
||||
link.classList.add("active");
|
||||
appItems.forEach((i) => i.classList.remove("active"));
|
||||
item.classList.add("active");
|
||||
|
||||
// Switch section
|
||||
window.switchSection(section);
|
||||
if (window.switchSection) {
|
||||
window.switchSection(section);
|
||||
}
|
||||
|
||||
// Close dropdown
|
||||
appsDropdown.classList.remove("show");
|
||||
});
|
||||
});
|
||||
|
||||
// Load default section (chat) after a short delay to ensure layout.js is loaded
|
||||
setTimeout(() => {
|
||||
if (window.switchSection) {
|
||||
window.switchSection("chat");
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ const sectionCache = {};
|
|||
|
||||
function getBasePath() {
|
||||
// All static assets (HTML, CSS, JS) are served from the site root.
|
||||
// Returning a leading slash ensures URLs like "/drive/drive.html" resolve correctly
|
||||
return "/";
|
||||
// Returning empty string for relative paths when served from same directory
|
||||
return "";
|
||||
}
|
||||
|
||||
// Preload chat CSS to avoid flash on first load
|
||||
|
|
@ -176,10 +176,16 @@ function getInitialSection() {
|
|||
return section || "chat";
|
||||
}
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
switchSection(getInitialSection());
|
||||
// Small delay to ensure all resources are loaded
|
||||
setTimeout(() => {
|
||||
switchSection(getInitialSection());
|
||||
}, 50);
|
||||
});
|
||||
|
||||
// Handle browser back/forward navigation
|
||||
window.addEventListener("popstate", () => {
|
||||
switchSection(getInitialSection());
|
||||
});
|
||||
|
||||
// Make switchSection globally accessible
|
||||
window.switchSection = switchSection;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue