Switch messages area to fixed positioning with centered transform for better layout stability. Enhance scrollbar appearance with thin style, improved colors
425 lines
14 KiB
HTML
425 lines
14 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<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>
|
|
<!-- 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 -->
|
|
</div>
|
|
|
|
<!-- Load scripts -->
|
|
<script src="js/layout.js"></script>
|
|
<script>
|
|
// Apps menu toggle
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
const appsBtn = document.getElementById("appsMenuBtn");
|
|
const appsDropdown = document.getElementById("appsDropdown");
|
|
const appItems = document.querySelectorAll(".app-item");
|
|
|
|
// 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 = item.dataset.section;
|
|
|
|
// Update active state
|
|
appItems.forEach((i) => i.classList.remove("active"));
|
|
item.classList.add("active");
|
|
|
|
// Switch 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>
|
|
</html>
|