mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-03-04 14:27:52 -05:00
changing main layout and styling
This commit is contained in:
@@ -1,156 +1,111 @@
|
||||
<div class="layout-wrapper" [ngClass]="{'dark-mode': darkMode(), 'sidebar-collapsed': isSidebarCollapsed()}">
|
||||
<!-- Top Bar -->
|
||||
<p-toolbar styleClass="top-bar">
|
||||
<div class="p-toolbar-group-start">
|
||||
<button pButton
|
||||
class="p-button-text p-button-rounded sidebar-toggle-mobile"
|
||||
icon="pi pi-bars"
|
||||
(click)="toggleMobileSidebar()"
|
||||
pRipple
|
||||
aria-label="Toggle menu">
|
||||
</button>
|
||||
<div class="logo-container">
|
||||
<span class="app-name">Cleanuparr</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-toolbar-group-end">
|
||||
<div class="theme-switch">
|
||||
<i class="pi pi-sun"></i>
|
||||
<p-inputSwitch [ngModel]="darkMode()" (onChange)="toggleDarkMode($event)"></p-inputSwitch>
|
||||
<i class="pi pi-moon"></i>
|
||||
</div>
|
||||
</div>
|
||||
</p-toolbar>
|
||||
|
||||
<!-- Sidebar for Mobile -->
|
||||
<p-sidebar [visible]="mobileSidebarVisible()" (visibleChange)="mobileSidebarVisible.set($event)" position="left" styleClass="mobile-sidebar">
|
||||
<div class="sidebar-content">
|
||||
<div class="sidebar-header">
|
||||
<div class="sidebar-logo">
|
||||
<i class="pi pi-bolt sidebar-icon"></i>
|
||||
<h3>Cleanuparr</h3>
|
||||
</div>
|
||||
</div>
|
||||
<p-divider></p-divider>
|
||||
<nav class="sidebar-nav">
|
||||
<!-- Main Navigation Section -->
|
||||
<div class="sidebar-section">
|
||||
<h3 class="sidebar-section-title">Main</h3>
|
||||
<ul>
|
||||
<li [ngClass]="{'active': router.isActive('/dashboard', true)}">
|
||||
<a [routerLink]="['/dashboard']" (click)="mobileSidebarVisible.set(false)">
|
||||
<svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path>
|
||||
</svg>
|
||||
<span>Dashboard</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Monitoring Section -->
|
||||
<div class="sidebar-section">
|
||||
<h3 class="sidebar-section-title">Monitoring</h3>
|
||||
<ul>
|
||||
<li [ngClass]="{'active': router.isActive('/logs', false)}">
|
||||
<a [routerLink]="['/logs']" (click)="mobileSidebarVisible.set(false)">
|
||||
<svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"></path>
|
||||
</svg>
|
||||
<span>Logs</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Section -->
|
||||
<div class="sidebar-section">
|
||||
<h3 class="sidebar-section-title">Configuration</h3>
|
||||
<ul>
|
||||
<li [ngClass]="{'active': router.isActive('/settings', false)}">
|
||||
<a [routerLink]="['/settings']" (click)="mobileSidebarVisible.set(false)">
|
||||
<svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"></path>
|
||||
</svg>
|
||||
<span>Settings</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</p-sidebar>
|
||||
|
||||
<div class="layout-wrapper">
|
||||
<!-- Main layout with sidebar and content -->
|
||||
<div class="layout-main">
|
||||
<!-- Sidebar for Desktop -->
|
||||
<div class="sidebar" [ngClass]="{'collapsed': isSidebarCollapsed()}">
|
||||
<!-- Desktop Sidebar -->
|
||||
<div class="sidebar" [class.collapsed]="isSidebarCollapsed()">
|
||||
<!-- Sidebar Header -->
|
||||
<div class="sidebar-header">
|
||||
<div class="sidebar-logo">
|
||||
<i class="pi pi-bolt sidebar-icon"></i>
|
||||
<i class="pi pi-check-circle sidebar-icon"></i>
|
||||
<span class="app-name">Cleanuparr</span>
|
||||
</div>
|
||||
<button pButton
|
||||
class="p-button-text p-button-rounded sidebar-toggle"
|
||||
[icon]="isSidebarCollapsed() ? 'pi pi-angle-right' : 'pi pi-angle-left'"
|
||||
(click)="toggleSidebar()"
|
||||
pRipple
|
||||
aria-label="Toggle sidebar">
|
||||
</button>
|
||||
</div>
|
||||
<p-divider></p-divider>
|
||||
<nav class="sidebar-nav">
|
||||
<!-- Main Navigation Section -->
|
||||
|
||||
<!-- Sidebar Navigation -->
|
||||
<div class="sidebar-nav">
|
||||
<div class="sidebar-section">
|
||||
<h3 class="sidebar-section-title">Main</h3>
|
||||
<h4 class="sidebar-section-title">MENU</h4>
|
||||
<ul>
|
||||
<li [ngClass]="{'active': router.isActive('/dashboard', true)}">
|
||||
<a [routerLink]="['/dashboard']">
|
||||
<svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path>
|
||||
</svg>
|
||||
<span>Dashboard</span>
|
||||
<li *ngFor="let item of menuItems" [class.active]="router.url.includes(item.route)">
|
||||
<a [routerLink]="item.route">
|
||||
<i [class]="item.icon"></i>
|
||||
<span>{{ item.label }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Monitoring Section -->
|
||||
<div class="sidebar-section">
|
||||
<h3 class="sidebar-section-title">Monitoring</h3>
|
||||
<ul>
|
||||
<li [ngClass]="{'active': router.isActive('/logs', false)}">
|
||||
<a [routerLink]="['/logs']">
|
||||
<svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"></path>
|
||||
</svg>
|
||||
<span>Logs</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Section -->
|
||||
<div class="sidebar-section">
|
||||
<h3 class="sidebar-section-title">Configuration</h3>
|
||||
<ul>
|
||||
<li [ngClass]="{'active': router.isActive('/settings', false)}">
|
||||
<a [routerLink]="['/settings']">
|
||||
<svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"></path>
|
||||
</svg>
|
||||
<span>Settings</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- Sponsor Section -->
|
||||
<div class="sponsor-section">
|
||||
<a href="https://github.com/sponsors/username" target="_blank" class="sponsor-link">
|
||||
<i class="pi pi-heart"></i>
|
||||
<span>Sponsor this project</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Footer -->
|
||||
<div class="sidebar-footer">
|
||||
<button pButton class="p-button-text sidebar-toggle"
|
||||
[icon]="isSidebarCollapsed() ? 'pi pi-angle-right' : 'pi pi-angle-left'"
|
||||
(click)="isSidebarCollapsed.set(!isSidebarCollapsed())"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
|
||||
<!-- Content Area -->
|
||||
<div class="layout-content">
|
||||
<!-- Content Header / Top Bar -->
|
||||
<div class="content-header">
|
||||
<div class="content-header-left">
|
||||
<button pButton class="p-button-text sidebar-toggle-mobile"
|
||||
icon="pi pi-bars"
|
||||
(click)="mobileSidebarVisible.set(true)"></button>
|
||||
<h1 class="page-title">{{ getPageTitle() }}</h1>
|
||||
</div>
|
||||
<div class="content-header-right">
|
||||
<div class="version-info">
|
||||
<span class="version-label">Version:</span>
|
||||
<span class="version-number">1.0.0</span>
|
||||
</div>
|
||||
<div class="star-counter">
|
||||
<i class="pi pi-star-fill"></i>
|
||||
<span>123</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="layout-content-inner">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Sidebar -->
|
||||
<p-sidebar styleClass="mobile-sidebar"
|
||||
[visible]="mobileSidebarVisible()"
|
||||
(visibleChange)="mobileSidebarVisible.set($event)"
|
||||
[dismissible]="true"
|
||||
[showCloseIcon]="false"
|
||||
position="left">
|
||||
<div class="sidebar-header">
|
||||
<div class="sidebar-logo">
|
||||
<i class="pi pi-check-circle sidebar-icon"></i>
|
||||
<span class="app-name">Cleanuparr</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Sidebar Navigation -->
|
||||
<div class="sidebar-nav">
|
||||
<div class="sidebar-section">
|
||||
<h4 class="sidebar-section-title">MENU</h4>
|
||||
<ul>
|
||||
<li *ngFor="let item of menuItems" [class.active]="router.url.includes(item.route)">
|
||||
<a [routerLink]="item.route" (click)="mobileSidebarVisible.set(false)">
|
||||
<i [class]="item.icon"></i>
|
||||
<span>{{ item.label }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Sponsor Section -->
|
||||
<div class="sponsor-section">
|
||||
<a href="https://github.com/sponsors/username" target="_blank" class="sponsor-link">
|
||||
<i class="pi pi-heart"></i>
|
||||
<span>Sponsor this project</span>
|
||||
</a>
|
||||
</div>
|
||||
</p-sidebar>
|
||||
</div>
|
||||
|
||||
@@ -1,487 +1,289 @@
|
||||
// Import variables
|
||||
|
||||
// Layout wrapper
|
||||
.layout-wrapper {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
background-color: var(--surface-ground);
|
||||
color: var(--text-color);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
&.dark-mode {
|
||||
// Dark mode variables are applied via documentElement.classList.add('dark')
|
||||
// which affects PrimeNG components through CSS variables
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
background-color: var(--surface-card) !important;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.app-name {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.theme-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
.pi-sun {
|
||||
color: var(--yellow-500);
|
||||
}
|
||||
|
||||
.pi-moon {
|
||||
color: var(--indigo-300);
|
||||
}
|
||||
}
|
||||
|
||||
.layout-main {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sidebar-toggle-mobile {
|
||||
display: none;
|
||||
margin-right: 0.5rem;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
font-size: 1.25rem;
|
||||
|
||||
.p-button-icon {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
color: var(--text-color-secondary);
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-color);
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
}
|
||||
|
||||
// Desktop Sidebar
|
||||
.sidebar {
|
||||
width: 260px;
|
||||
background-color: var(--surface-overlay);
|
||||
border-right: 1px solid var(--surface-border);
|
||||
height: calc(100vh - 4rem); // Adjust based on your toolbar height
|
||||
position: sticky;
|
||||
top: 4rem; // Toolbar height
|
||||
z-index: 998;
|
||||
transition: all 0.3s ease;
|
||||
// Mobile sidebar
|
||||
.mobile-sidebar {
|
||||
::ng-deep .p-sidebar-content {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
scrollbar-width: thin;
|
||||
background-color: #1a1e27;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
// Main layout
|
||||
.layout-main {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
// Sidebar
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
background-color: #1a1e27;
|
||||
color: #ffffff;
|
||||
transition: width 0.3s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
@media (max-width: 991px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--surface-border);
|
||||
border-radius: 4px;
|
||||
&.collapsed {
|
||||
width: 70px;
|
||||
|
||||
.app-name,
|
||||
.sidebar-section-title,
|
||||
.sidebar-nav span,
|
||||
.sponsor-link span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-footer {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid var(--surface-hover);
|
||||
justify-content: center;
|
||||
padding: 1.5rem 1rem;
|
||||
|
||||
.sidebar-logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
|
||||
.sidebar-icon {
|
||||
font-size: 1.5rem;
|
||||
color: var(--primary-color);
|
||||
color: #ffcc00;
|
||||
}
|
||||
|
||||
.app-name {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
transition: opacity 0.3s ease;
|
||||
font-weight: 700;
|
||||
margin-left: 0.5rem;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Huntarr-style sidebar navigation
|
||||
.sidebar-nav {
|
||||
padding: 0.5rem 1rem;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
// Sponsor section
|
||||
.sponsor-section {
|
||||
padding: 0.5rem 1rem 1rem;
|
||||
|
||||
.sidebar-section {
|
||||
margin-bottom: 1.5rem;
|
||||
.sponsor-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem 1rem;
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 4px;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
.sidebar-section-title {
|
||||
font-size: 0.85rem;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-color-secondary);
|
||||
margin: 0.5rem 0;
|
||||
padding: 0 0.5rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
transition: opacity 0.3s ease;
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
margin-bottom: 0.25rem;
|
||||
border-radius: 8px;
|
||||
|
||||
&.active a {
|
||||
background-color: var(--primary-100);
|
||||
color: var(--primary-color);
|
||||
|
||||
.svg-icon {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem 0.5rem;
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 0.75rem;
|
||||
color: var(--text-color-secondary);
|
||||
transition: margin 0.3s ease;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 0.95rem;
|
||||
white-space: nowrap;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
i {
|
||||
color: #ff5a5f;
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collapsed state
|
||||
&.collapsed {
|
||||
width: 4.5rem;
|
||||
// Sidebar footer with toggle button
|
||||
.sidebar-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 1rem;
|
||||
margin-top: auto;
|
||||
|
||||
.sidebar-header {
|
||||
padding: 1rem 0.5rem;
|
||||
justify-content: center;
|
||||
.sidebar-toggle {
|
||||
color: #ffffff;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
|
||||
.app-name {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
position: absolute;
|
||||
right: 0.25rem;
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sidebar navigation
|
||||
.sidebar-nav {
|
||||
padding: 1rem 0;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
|
||||
.sidebar-section {
|
||||
margin-bottom: 1.5rem;
|
||||
|
||||
.sidebar-nav {
|
||||
padding: 0.5rem;
|
||||
.sidebar-section-title {
|
||||
padding: 0 1rem;
|
||||
margin: 0 0 0.5rem 0;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
.sidebar-section-title {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
ul li a {
|
||||
justify-content: center;
|
||||
padding: 0.75rem;
|
||||
|
||||
.svg-icon {
|
||||
margin-right: 0;
|
||||
li {
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem 1rem;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 1.25rem;
|
||||
width: 1.5rem;
|
||||
margin-right: 0.75rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
&.active a {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: #ffffff;
|
||||
font-weight: 600;
|
||||
border-left: 3px solid #4299e1;
|
||||
padding-left: calc(1rem - 3px);
|
||||
|
||||
i {
|
||||
color: #4299e1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sidebar collapsed state
|
||||
&.sidebar-collapsed {
|
||||
.sidebar {
|
||||
width: 4.5rem;
|
||||
|
||||
.sidebar-header {
|
||||
padding: 1rem 0.5rem;
|
||||
justify-content: center;
|
||||
|
||||
.sidebar-toggle {
|
||||
position: absolute;
|
||||
right: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
a {
|
||||
justify-content: center;
|
||||
padding: 0.75rem;
|
||||
|
||||
i {
|
||||
margin-right: 0;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Menu list styling
|
||||
.menu-list {
|
||||
list-style: none;
|
||||
padding: 0.5rem;
|
||||
margin: 0;
|
||||
|
||||
.menu-item {
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 8px;
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
gap: 0.75rem;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
&.active-menu-link {
|
||||
background-color: var(--primary-100);
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
|
||||
i {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 1.2rem;
|
||||
color: var(--text-color-secondary);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.menu-label {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.badge {
|
||||
margin-left: auto;
|
||||
background-color: var(--primary-color);
|
||||
color: var(--primary-color-text);
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 8px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Content area
|
||||
.layout-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
min-height: calc(100vh - 4rem);
|
||||
padding: 1.5rem;
|
||||
background-color: #0f1319;
|
||||
color: #ffffff;
|
||||
|
||||
// Content header/top bar
|
||||
.content-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
|
||||
.content-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.sidebar-toggle-mobile {
|
||||
display: none;
|
||||
margin-right: 1rem;
|
||||
color: #ffffff;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
|
||||
@media (max-width: 991px) {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.content-header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.version-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
.version-label {
|
||||
font-size: 0.875rem;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.version-number {
|
||||
font-size: 0.875rem;
|
||||
color: #4299e1;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.star-counter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
i {
|
||||
color: #ffcc00;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layout-content-inner {
|
||||
flex: 1;
|
||||
border-radius: var(--border-radius);
|
||||
padding: 1.5rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Media queries for responsiveness
|
||||
@media screen and (max-width: 768px) {
|
||||
.layout-wrapper {
|
||||
.top-bar {
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
.app-name {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.layout-content {
|
||||
.content-header {
|
||||
padding: 0.75rem 1rem;
|
||||
}
|
||||
|
||||
.layout-content {
|
||||
|
||||
.layout-content-inner {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-toggle-mobile {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// Mobile sidebar styling
|
||||
::ng-deep {
|
||||
.mobile-sidebar {
|
||||
.p-sidebar-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.sidebar-header {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid var(--surface-hover);
|
||||
|
||||
.sidebar-logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
|
||||
.sidebar-icon {
|
||||
font-size: 1.5rem;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
padding: 0.5rem 1rem;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
|
||||
.sidebar-section {
|
||||
margin-bottom: 1.5rem;
|
||||
|
||||
.sidebar-section-title {
|
||||
font-size: 0.85rem;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-color-secondary);
|
||||
margin: 0.5rem 0;
|
||||
padding: 0 0.5rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
margin-bottom: 0.5rem;
|
||||
border-radius: 8px;
|
||||
|
||||
&.active a {
|
||||
background-color: var(--primary-100);
|
||||
color: var(--primary-color);
|
||||
|
||||
.svg-icon {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1rem 0.75rem;
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 1rem;
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 1rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Utility classes
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { Router, RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import { Router, RouterOutlet, RouterLink } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
// PrimeNG Imports
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { ToolbarModule } from 'primeng/toolbar';
|
||||
import { InputSwitchModule } from 'primeng/inputswitch';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MenuModule } from 'primeng/menu';
|
||||
import { SidebarModule } from 'primeng/sidebar';
|
||||
@@ -26,10 +26,8 @@ interface MenuItem {
|
||||
CommonModule,
|
||||
RouterOutlet,
|
||||
RouterLink,
|
||||
RouterLinkActive,
|
||||
ButtonModule,
|
||||
ToolbarModule,
|
||||
InputSwitchModule,
|
||||
FormsModule,
|
||||
MenuModule,
|
||||
SidebarModule,
|
||||
@@ -40,7 +38,6 @@ interface MenuItem {
|
||||
styleUrl: './main-layout.component.scss'
|
||||
})
|
||||
export class MainLayoutComponent {
|
||||
darkMode = signal<boolean>(false);
|
||||
isSidebarCollapsed = signal<boolean>(false);
|
||||
|
||||
// Menu items
|
||||
@@ -53,27 +50,26 @@ export class MainLayoutComponent {
|
||||
// Mobile menu state
|
||||
mobileSidebarVisible = signal<boolean>(false);
|
||||
|
||||
// Inject router
|
||||
// Inject router and title service
|
||||
public router = inject(Router);
|
||||
private titleService = inject(Title);
|
||||
|
||||
constructor() {
|
||||
// Initialize theme based on system preference
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
this.darkMode.set(prefersDark);
|
||||
}
|
||||
constructor() {}
|
||||
|
||||
toggleDarkMode(event: any): void {
|
||||
const isDark = event.checked;
|
||||
this.darkMode.set(isDark);
|
||||
/**
|
||||
* Get the current page title based on the active route
|
||||
*/
|
||||
getPageTitle(): string {
|
||||
const currentUrl = this.router.url;
|
||||
|
||||
// Apply theme to document
|
||||
const documentElement = document.documentElement;
|
||||
if (isDark) {
|
||||
documentElement.classList.add('dark');
|
||||
documentElement.style.colorScheme = 'dark';
|
||||
if (currentUrl.includes('/dashboard')) {
|
||||
return 'Dashboard';
|
||||
} else if (currentUrl.includes('/logs')) {
|
||||
return 'Logs';
|
||||
} else if (currentUrl.includes('/settings')) {
|
||||
return 'Settings';
|
||||
} else {
|
||||
documentElement.classList.remove('dark');
|
||||
documentElement.style.colorScheme = 'light';
|
||||
return 'Cleanuparr';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,9 +79,7 @@
|
||||
|
||||
.search-input {
|
||||
width: 200px;
|
||||
@media (min-width: 992px) {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -105,7 +103,6 @@
|
||||
|
||||
@media (max-width: 576px) {
|
||||
width: 100%;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.p-select-label {
|
||||
@@ -389,17 +386,6 @@
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
@media (max-width: 576px) {
|
||||
position: absolute;
|
||||
top: 0.75rem;
|
||||
right: 0.5rem;
|
||||
background-color: var(--surface-card);
|
||||
border-radius: 2rem;
|
||||
padding: 0.25rem;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.auto-scroll-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -465,13 +451,6 @@
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
.pi-search {
|
||||
position: absolute;
|
||||
left: 0.75rem;
|
||||
top: 0.75rem;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user