css refactor
This commit is contained in:
@@ -31,54 +31,38 @@
|
||||
let showUserMenu = false;
|
||||
let isSearchFocused = false;
|
||||
|
||||
// Subscribe to sidebar store for responsive layout
|
||||
$: isExpanded = $sidebarStore?.isExpanded ?? true;
|
||||
|
||||
// Subscribe to activity store
|
||||
$: activeCount = $activityStore?.activeCount || 0;
|
||||
$: recentTasks = $activityStore?.recentTasks || [];
|
||||
|
||||
// Get user from auth store
|
||||
$: user = $auth?.user || null;
|
||||
|
||||
// Toggle user menu
|
||||
function toggleUserMenu(event) {
|
||||
event.stopPropagation();
|
||||
showUserMenu = !showUserMenu;
|
||||
console.log(`[TopNavbar][Action] Toggle user menu: ${showUserMenu}`);
|
||||
}
|
||||
|
||||
// Close user menu
|
||||
function closeUserMenu() {
|
||||
showUserMenu = false;
|
||||
}
|
||||
|
||||
// Handle logout
|
||||
function handleLogout() {
|
||||
console.log("[TopNavbar][Action] Logout");
|
||||
auth.logout();
|
||||
closeUserMenu();
|
||||
// Navigate to login
|
||||
window.location.href = "/login";
|
||||
}
|
||||
|
||||
// Handle activity indicator click - open Task Drawer with most recent task
|
||||
function handleActivityClick() {
|
||||
console.log("[TopNavbar][Action] Activity indicator clicked");
|
||||
// Open drawer with the most recent running task, or list mode
|
||||
const runningTask = recentTasks.find((t) => t.status === "RUNNING");
|
||||
if (runningTask) {
|
||||
openDrawerForTask(runningTask.taskId);
|
||||
} else if (recentTasks.length > 0) {
|
||||
openDrawerForTask(recentTasks[recentTasks.length - 1].taskId);
|
||||
} else {
|
||||
// No tracked tasks — open in list mode to show recent tasks from API
|
||||
openDrawer();
|
||||
}
|
||||
dispatch("activityClick");
|
||||
}
|
||||
|
||||
// Handle search focus
|
||||
function handleSearchFocus() {
|
||||
isSearchFocused = true;
|
||||
}
|
||||
@@ -87,34 +71,31 @@
|
||||
isSearchFocused = false;
|
||||
}
|
||||
|
||||
// Close dropdowns when clicking outside
|
||||
function handleDocumentClick(event) {
|
||||
if (!event.target.closest(".user-menu-container")) {
|
||||
closeUserMenu();
|
||||
}
|
||||
}
|
||||
|
||||
// Listen for document clicks
|
||||
if (typeof document !== "undefined") {
|
||||
document.addEventListener("click", handleDocumentClick);
|
||||
}
|
||||
|
||||
// Handle hamburger menu click for mobile
|
||||
function handleHamburgerClick(event) {
|
||||
event.stopPropagation();
|
||||
console.log("[TopNavbar][Action] Toggle mobile sidebar");
|
||||
toggleMobileSidebar();
|
||||
}
|
||||
</script>
|
||||
|
||||
<nav
|
||||
class="navbar {isExpanded ? 'with-sidebar' : 'with-collapsed-sidebar'} mobile"
|
||||
class="bg-white border-b border-gray-200 fixed top-0 right-0 left-0 h-16 flex items-center justify-between px-4 z-40
|
||||
{isExpanded ? 'md:left-[240px]' : 'md:left-16'}"
|
||||
>
|
||||
<!-- Left section: Hamburger (mobile) + Logo -->
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- Hamburger Menu (mobile only) -->
|
||||
<button
|
||||
class="hamburger-btn"
|
||||
class="p-2 rounded-lg hover:bg-gray-100 text-gray-600 md:hidden"
|
||||
on:click={handleHamburgerClick}
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
@@ -134,9 +115,12 @@
|
||||
</button>
|
||||
|
||||
<!-- Logo/Brand -->
|
||||
<a href="/" class="logo-link">
|
||||
<a
|
||||
href="/"
|
||||
class="flex items-center text-xl font-bold text-gray-800 hover:text-primary transition-colors"
|
||||
>
|
||||
<svg
|
||||
class="logo-icon"
|
||||
class="w-8 h-8 mr-2 text-primary"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
@@ -148,10 +132,11 @@
|
||||
</div>
|
||||
|
||||
<!-- Search placeholder (non-functional for now) -->
|
||||
<div class="search-container">
|
||||
<div class="flex-1 max-w-xl mx-4 hidden md:block">
|
||||
<input
|
||||
type="text"
|
||||
class="search-input {isSearchFocused ? 'focused' : ''}"
|
||||
class="w-full px-4 py-2 bg-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-ring transition-all
|
||||
{isSearchFocused ? 'bg-white border border-primary-ring' : ''}"
|
||||
placeholder={$t.common.search || "Search..."}
|
||||
on:focus={handleSearchFocus}
|
||||
on:blur={handleSearchBlur}
|
||||
@@ -159,10 +144,10 @@
|
||||
</div>
|
||||
|
||||
<!-- Nav Actions -->
|
||||
<div class="nav-actions">
|
||||
<div class="flex items-center space-x-4">
|
||||
<!-- Activity Indicator -->
|
||||
<div
|
||||
class="activity-indicator"
|
||||
class="relative cursor-pointer p-2 rounded-lg hover:bg-gray-100 transition-colors"
|
||||
on:click={handleActivityClick}
|
||||
on:keydown={(e) =>
|
||||
(e.key === "Enter" || e.key === " ") && handleActivityClick()}
|
||||
@@ -171,7 +156,7 @@
|
||||
aria-label="Activity"
|
||||
>
|
||||
<svg
|
||||
class="activity-icon"
|
||||
class="w-6 h-6 text-gray-600"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
@@ -183,14 +168,17 @@
|
||||
/>
|
||||
</svg>
|
||||
{#if activeCount > 0}
|
||||
<span class="activity-badge">{activeCount}</span>
|
||||
<span
|
||||
class="absolute -top-1 -right-1 bg-destructive text-white text-xs font-bold rounded-full w-5 h-5 flex items-center justify-center"
|
||||
>{activeCount}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- User Menu -->
|
||||
<div class="user-menu-container">
|
||||
<div class="user-menu-container relative">
|
||||
<div
|
||||
class="user-avatar"
|
||||
class="w-8 h-8 rounded-full bg-primary text-white flex items-center justify-center cursor-pointer hover:bg-primary-hover transition-colors"
|
||||
on:click={toggleUserMenu}
|
||||
on:keydown={(e) =>
|
||||
(e.key === "Enter" || e.key === " ") && toggleUserMenu(e)}
|
||||
@@ -208,13 +196,17 @@
|
||||
</div>
|
||||
|
||||
<!-- User Dropdown -->
|
||||
<div class="user-dropdown {showUserMenu ? '' : 'hidden'}">
|
||||
<div class="dropdown-item">
|
||||
<div
|
||||
class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50 {showUserMenu
|
||||
? ''
|
||||
: 'hidden'}"
|
||||
>
|
||||
<div class="px-4 py-2 text-sm text-gray-700">
|
||||
<strong>{user?.username || "User"}</strong>
|
||||
</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="border-t border-gray-200 my-1"></div>
|
||||
<div
|
||||
class="dropdown-item"
|
||||
class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer"
|
||||
on:click={() => {
|
||||
window.location.href = "/settings";
|
||||
}}
|
||||
@@ -227,7 +219,7 @@
|
||||
{$t.nav?.settings || "Settings"}
|
||||
</div>
|
||||
<div
|
||||
class="dropdown-item danger"
|
||||
class="px-4 py-2 text-sm text-destructive hover:bg-destructive-light cursor-pointer"
|
||||
on:click={handleLogout}
|
||||
on:keydown={(e) =>
|
||||
(e.key === "Enter" || e.key === " ") && handleLogout()}
|
||||
@@ -242,96 +234,3 @@
|
||||
</nav>
|
||||
|
||||
<!-- [/DEF:TopNavbar:Component] -->
|
||||
|
||||
<style>
|
||||
.navbar {
|
||||
@apply bg-white border-b border-gray-200 fixed top-0 right-0 left-0 h-16 flex items-center justify-between px-4 z-40;
|
||||
}
|
||||
|
||||
.navbar.with-sidebar {
|
||||
@apply md:left-64;
|
||||
}
|
||||
|
||||
.navbar.with-collapsed-sidebar {
|
||||
@apply md:left-16;
|
||||
}
|
||||
|
||||
.navbar.mobile {
|
||||
@apply left-0;
|
||||
}
|
||||
|
||||
.logo-link {
|
||||
@apply flex items-center text-xl font-bold text-gray-800 hover:text-blue-600 transition-colors;
|
||||
}
|
||||
|
||||
.logo-icon {
|
||||
@apply w-8 h-8 mr-2 text-blue-600;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
@apply flex-1 max-w-xl mx-4;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
@apply w-full px-4 py-2 bg-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all;
|
||||
}
|
||||
|
||||
.search-input.focused {
|
||||
@apply bg-white border border-blue-500;
|
||||
}
|
||||
|
||||
.nav-actions {
|
||||
@apply flex items-center space-x-4;
|
||||
}
|
||||
|
||||
.hamburger-btn {
|
||||
@apply p-2 rounded-lg hover:bg-gray-100 text-gray-600 md:hidden;
|
||||
}
|
||||
|
||||
.activity-indicator {
|
||||
@apply relative cursor-pointer p-2 rounded-lg hover:bg-gray-100 transition-colors;
|
||||
}
|
||||
|
||||
.activity-badge {
|
||||
@apply absolute -top-1 -right-1 bg-red-500 text-white text-xs font-bold rounded-full w-5 h-5 flex items-center justify-center;
|
||||
}
|
||||
|
||||
.activity-icon {
|
||||
@apply w-6 h-6 text-gray-600;
|
||||
}
|
||||
|
||||
.user-menu-container {
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
@apply w-8 h-8 rounded-full bg-blue-600 text-white flex items-center justify-center cursor-pointer hover:bg-blue-700 transition-colors;
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
@apply absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50;
|
||||
}
|
||||
|
||||
.user-dropdown.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
@apply px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer;
|
||||
}
|
||||
|
||||
.dropdown-item.danger {
|
||||
@apply text-red-600 hover:bg-red-50;
|
||||
}
|
||||
|
||||
.dropdown-divider {
|
||||
@apply border-t border-gray-200 my-1;
|
||||
}
|
||||
|
||||
/* Mobile responsive */
|
||||
@media (max-width: 768px) {
|
||||
.search-container {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user