feat(dashboard): comprehensive filter enhancement and UI layout fixes
- Add time range selector (1H/6H/24H/7D/All) with preference persistence - Implement smart X-axis label formatting for multi-day usage data - Standardize global component spacing and fix CSS @apply limitations - Add elegant empty state UI for charts when filtered data is absent - Update i18n translations for all new dashboard features
This commit is contained in:
@@ -1,162 +1,183 @@
|
||||
:root {
|
||||
/* === Background Layers === */
|
||||
--color-space-950: #09090b;
|
||||
--color-space-900: #0f0f11;
|
||||
--color-space-850: #121214;
|
||||
--color-space-800: #18181b;
|
||||
--color-space-border: #27272a;
|
||||
/* === Background Layers === */
|
||||
--color-space-950: #09090b;
|
||||
--color-space-900: #0f0f11;
|
||||
--color-space-850: #121214;
|
||||
--color-space-800: #18181b;
|
||||
--color-space-border: #27272a;
|
||||
|
||||
/* === Neon Accents (Full Saturation) === */
|
||||
--color-neon-purple: #a855f7;
|
||||
--color-neon-green: #22c55e;
|
||||
--color-neon-cyan: #06b6d4;
|
||||
--color-neon-yellow: #eab308;
|
||||
--color-neon-red: #ef4444;
|
||||
/* === Neon Accents (Full Saturation) === */
|
||||
--color-neon-purple: #a855f7;
|
||||
--color-neon-green: #22c55e;
|
||||
--color-neon-cyan: #06b6d4;
|
||||
--color-neon-yellow: #eab308;
|
||||
--color-neon-red: #ef4444;
|
||||
|
||||
/* === Soft Neon (Reduced Saturation for Fills) === */
|
||||
--color-neon-purple-soft: #9333ea;
|
||||
--color-neon-green-soft: #16a34a;
|
||||
--color-neon-cyan-soft: #0891b2;
|
||||
/* === Soft Neon (Reduced Saturation for Fills) === */
|
||||
--color-neon-purple-soft: #9333ea;
|
||||
--color-neon-green-soft: #16a34a;
|
||||
--color-neon-cyan-soft: #0891b2;
|
||||
|
||||
/* === Text Hierarchy (WCAG AA Compliant) === */
|
||||
--color-text-primary: #ffffff; /* Emphasis: Titles, Key Numbers */
|
||||
--color-text-secondary: #d4d4d8; /* Content: Body Text (zinc-300) */
|
||||
--color-text-tertiary: #a1a1aa; /* Metadata: Timestamps, Labels (zinc-400) */
|
||||
--color-text-quaternary: #71717a; /* Subtle: Decorative (zinc-500) */
|
||||
/* === Text Hierarchy (WCAG AA Compliant) === */
|
||||
--color-text-primary: #ffffff; /* Emphasis: Titles, Key Numbers */
|
||||
--color-text-secondary: #d4d4d8; /* Content: Body Text (zinc-300) */
|
||||
--color-text-tertiary: #a1a1aa; /* Metadata: Timestamps, Labels (zinc-400) */
|
||||
--color-text-quaternary: #71717a; /* Subtle: Decorative (zinc-500) */
|
||||
|
||||
/* === Legacy Aliases (Backward Compatibility) === */
|
||||
--color-text-main: var(--color-text-secondary);
|
||||
--color-text-dim: var(--color-text-tertiary);
|
||||
--color-text-muted: var(--color-text-tertiary);
|
||||
--color-text-bright: var(--color-text-primary);
|
||||
/* === Legacy Aliases (Backward Compatibility) === */
|
||||
--color-text-main: var(--color-text-secondary);
|
||||
--color-text-dim: var(--color-text-tertiary);
|
||||
--color-text-muted: var(--color-text-tertiary);
|
||||
--color-text-bright: var(--color-text-primary);
|
||||
|
||||
/* Gradient Accents */
|
||||
--color-green-400: #4ade80;
|
||||
--color-yellow-400: #facc15;
|
||||
--color-red-400: #f87171;
|
||||
/* Gradient Accents */
|
||||
--color-green-400: #4ade80;
|
||||
--color-yellow-400: #facc15;
|
||||
--color-red-400: #f87171;
|
||||
|
||||
/* Chart Colors */
|
||||
--color-chart-1: #a855f7;
|
||||
--color-chart-2: #c084fc;
|
||||
--color-chart-3: #e879f9;
|
||||
--color-chart-4: #d946ef;
|
||||
--color-chart-5: #22c55e;
|
||||
--color-chart-6: #4ade80;
|
||||
--color-chart-7: #86efac;
|
||||
--color-chart-8: #10b981;
|
||||
--color-chart-9: #06b6d4;
|
||||
--color-chart-10: #f59e0b;
|
||||
--color-chart-11: #ef4444;
|
||||
--color-chart-12: #ec4899;
|
||||
--color-chart-13: #8b5cf6;
|
||||
--color-chart-14: #14b8a6;
|
||||
--color-chart-15: #f97316;
|
||||
--color-chart-16: #6366f1;
|
||||
/* Chart Colors */
|
||||
--color-chart-1: #a855f7;
|
||||
--color-chart-2: #c084fc;
|
||||
--color-chart-3: #e879f9;
|
||||
--color-chart-4: #d946ef;
|
||||
--color-chart-5: #22c55e;
|
||||
--color-chart-6: #4ade80;
|
||||
--color-chart-7: #86efac;
|
||||
--color-chart-8: #10b981;
|
||||
--color-chart-9: #06b6d4;
|
||||
--color-chart-10: #f59e0b;
|
||||
--color-chart-11: #ef4444;
|
||||
--color-chart-12: #ec4899;
|
||||
--color-chart-13: #8b5cf6;
|
||||
--color-chart-14: #14b8a6;
|
||||
--color-chart-15: #f97316;
|
||||
--color-chart-16: #6366f1;
|
||||
}
|
||||
|
||||
[x-cloak] {
|
||||
display: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Custom Scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgba(9, 9, 11, 0.3);
|
||||
border-radius: 4px;
|
||||
background: rgba(9, 9, 11, 0.3);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(180deg, #27272a 0%, #18181b 100%);
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
transition: background 0.2s ease;
|
||||
background: linear-gradient(180deg, #27272a 0%, #18181b 100%);
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: linear-gradient(180deg, #3f3f46 0%, #27272a 100%);
|
||||
border-color: rgba(168, 85, 247, 0.3);
|
||||
background: linear-gradient(180deg, #3f3f46 0%, #27272a 100%);
|
||||
border-color: rgba(168, 85, 247, 0.3);
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.2s ease;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(5px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(5px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.4s ease-out forwards;
|
||||
animation: fadeIn 0.4s ease-out forwards;
|
||||
}
|
||||
|
||||
/* Utility */
|
||||
.glass-panel {
|
||||
background: linear-gradient(135deg,
|
||||
rgba(15, 15, 17, 0.75) 0%,
|
||||
rgba(18, 18, 20, 0.70) 100%
|
||||
);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(255, 255, 255, 0.02) inset,
|
||||
0 4px 24px rgba(0, 0, 0, 0.4);
|
||||
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(15, 15, 17, 0.75) 0%,
|
||||
rgba(18, 18, 20, 0.7) 100%
|
||||
);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.02) inset,
|
||||
0 4px 24px rgba(0, 0, 0, 0.4);
|
||||
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.glass-panel:hover {
|
||||
border-color: rgba(255, 255, 255, 0.12);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(255, 255, 255, 0.04) inset,
|
||||
0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
border-color: rgba(255, 255, 255, 0.12);
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.04) inset,
|
||||
0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.nav-item.active {
|
||||
background: linear-gradient(90deg, theme('colors.neon.purple / 15%') 0%, transparent 100%);
|
||||
@apply border-l-4 border-neon-purple text-white;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
theme("colors.neon.purple / 15%") 0%,
|
||||
transparent 100%
|
||||
);
|
||||
@apply border-l-4 border-neon-purple text-white;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
@apply border-l-4 border-transparent transition-all duration-200;
|
||||
@apply border-l-4 border-transparent transition-all duration-200;
|
||||
}
|
||||
|
||||
.progress-gradient-success::-webkit-progress-value {
|
||||
background-image: linear-gradient(to right, var(--color-neon-green), var(--color-green-400));
|
||||
background-image: linear-gradient(
|
||||
to right,
|
||||
var(--color-neon-green),
|
||||
var(--color-green-400)
|
||||
);
|
||||
}
|
||||
|
||||
.progress-gradient-warning::-webkit-progress-value {
|
||||
background-image: linear-gradient(to right, var(--color-neon-yellow), var(--color-yellow-400));
|
||||
background-image: linear-gradient(
|
||||
to right,
|
||||
var(--color-neon-yellow),
|
||||
var(--color-yellow-400)
|
||||
);
|
||||
}
|
||||
|
||||
.progress-gradient-error::-webkit-progress-value {
|
||||
background-image: linear-gradient(to right, var(--color-neon-red), var(--color-red-400));
|
||||
background-image: linear-gradient(
|
||||
to right,
|
||||
var(--color-neon-red),
|
||||
var(--color-red-400)
|
||||
);
|
||||
}
|
||||
|
||||
/* Dashboard Grid */
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 1.5rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
/* Tooltip Customization */
|
||||
.tooltip:before {
|
||||
@apply bg-space-800 border border-space-border text-gray-200 font-mono text-xs;
|
||||
@apply bg-space-800 border border-space-border text-gray-200 font-mono text-xs;
|
||||
}
|
||||
|
||||
.tooltip-left:before {
|
||||
margin-right: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@@ -165,21 +186,25 @@
|
||||
|
||||
/* Standard Layout Constants */
|
||||
:root {
|
||||
--view-padding: 2rem; /* 32px - Standard Padding */
|
||||
--view-gap: 1.5rem; /* 24px - Standard component gap */
|
||||
--card-radius: 0.75rem; /* 12px */
|
||||
--view-padding: 2rem; /* 32px - Standard Padding */
|
||||
--view-gap: 2rem; /* 32px - Standard component gap */
|
||||
--card-radius: 0.75rem; /* 12px */
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
:root {
|
||||
--view-padding: 1rem;
|
||||
--view-gap: 1rem;
|
||||
}
|
||||
:root {
|
||||
--view-padding: 1rem;
|
||||
--view-gap: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Base View Container */
|
||||
.view-container {
|
||||
@apply mx-auto w-full animate-fade-in flex flex-col;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 100%;
|
||||
padding: var(--view-padding);
|
||||
gap: var(--view-gap);
|
||||
min-height: calc(100vh - 56px); /* Align with navbar height */
|
||||
@@ -189,128 +214,159 @@
|
||||
|
||||
/* Specialized container for data-heavy pages (Logs) */
|
||||
.view-container-full {
|
||||
@apply w-full animate-fade-in flex flex-col;
|
||||
padding: var(--view-padding);
|
||||
gap: var(--view-gap);
|
||||
min-height: calc(100vh - 56px);
|
||||
max-width: 100%;
|
||||
@apply w-full animate-fade-in flex flex-col;
|
||||
padding: var(--view-padding);
|
||||
gap: var(--view-gap);
|
||||
min-height: calc(100vh - 56px);
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Centered container for form-heavy pages (Settings/Accounts) */
|
||||
.view-container-centered {
|
||||
@apply mx-auto w-full animate-fade-in flex flex-col;
|
||||
padding: var(--view-padding);
|
||||
gap: var(--view-gap);
|
||||
min-height: calc(100vh - 56px);
|
||||
max-width: 900px; /* Comfortable reading width for forms */
|
||||
@apply mx-auto w-full animate-fade-in flex flex-col;
|
||||
padding: var(--view-padding);
|
||||
gap: var(--view-gap);
|
||||
min-height: calc(100vh - 56px);
|
||||
max-width: 900px; /* Comfortable reading width for forms */
|
||||
}
|
||||
|
||||
/* Standard Section Header */
|
||||
.view-header {
|
||||
@apply flex flex-col md:flex-row md:items-end justify-between mb-2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.5rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.view-header {
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.view-header-title {
|
||||
@apply flex flex-col;
|
||||
@apply flex flex-col;
|
||||
}
|
||||
|
||||
.view-header-title h2 {
|
||||
@apply text-2xl font-bold text-white tracking-tight;
|
||||
@apply text-2xl font-bold text-white tracking-tight;
|
||||
}
|
||||
|
||||
.view-header-title p {
|
||||
@apply text-sm text-gray-500 mt-1;
|
||||
@apply text-sm text-gray-500 mt-1;
|
||||
}
|
||||
|
||||
.view-header-actions {
|
||||
@apply flex items-center gap-3;
|
||||
@apply flex items-center gap-3;
|
||||
}
|
||||
|
||||
/* Standard Card Panel */
|
||||
.view-card {
|
||||
@apply glass-panel rounded-xl p-6 border border-space-border/50 relative overflow-hidden;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: var(--card-radius);
|
||||
padding: 1.5rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: linear-gradient(135deg,
|
||||
rgba(15, 15, 17, 0.75) 0%,
|
||||
rgba(18, 18, 20, 0.70) 100%
|
||||
);
|
||||
backdrop-filter: blur(12px);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(255, 255, 255, 0.02) inset,
|
||||
0 4px 24px rgba(0, 0, 0, 0.4);
|
||||
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.view-card:hover {
|
||||
border-color: rgba(255, 255, 255, 0.12);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(255, 255, 255, 0.04) inset,
|
||||
0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.view-card-header {
|
||||
@apply flex items-center justify-between mb-4 pb-4 border-b border-space-border/30;
|
||||
@apply flex items-center justify-between mb-4 pb-4 border-b border-space-border/30;
|
||||
}
|
||||
|
||||
/* Component Unification */
|
||||
.standard-table {
|
||||
@apply table w-full border-separate border-spacing-0;
|
||||
@apply table w-full border-separate border-spacing-0;
|
||||
}
|
||||
.standard-table thead {
|
||||
@apply bg-space-900/50 text-gray-500 font-mono text-xs uppercase border-b border-space-border;
|
||||
@apply bg-space-900/50 text-gray-500 font-mono text-xs uppercase border-b border-space-border;
|
||||
}
|
||||
.standard-table tbody tr {
|
||||
@apply transition-all duration-200 border-b border-space-border/30 last:border-0;
|
||||
@apply transition-all duration-200 border-b border-space-border/30 last:border-0;
|
||||
}
|
||||
|
||||
.standard-table tbody tr:hover {
|
||||
background: linear-gradient(90deg,
|
||||
rgba(255, 255, 255, 0.03) 0%,
|
||||
rgba(255, 255, 255, 0.05) 50%,
|
||||
rgba(255, 255, 255, 0.03) 100%
|
||||
);
|
||||
border-color: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 0.03) 0%,
|
||||
rgba(255, 255, 255, 0.05) 50%,
|
||||
rgba(255, 255, 255, 0.03) 100%
|
||||
);
|
||||
border-color: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Custom Range Slider - Simplified */
|
||||
.custom-range {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background: var(--color-space-800);
|
||||
border-radius: 999px;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background: var(--color-space-800);
|
||||
border-radius: 999px;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.custom-range::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
background: var(--range-color, var(--color-neon-purple));
|
||||
cursor: pointer;
|
||||
transition: transform 0.1s ease;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
background: var(--range-color, var(--color-neon-purple));
|
||||
cursor: pointer;
|
||||
transition: transform 0.1s ease;
|
||||
}
|
||||
|
||||
.custom-range::-webkit-slider-thumb:hover {
|
||||
transform: scale(1.15);
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
.custom-range::-moz-range-thumb {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
background: var(--range-color, var(--color-neon-purple));
|
||||
cursor: pointer;
|
||||
transition: transform 0.1s ease;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
background: var(--range-color, var(--color-neon-purple));
|
||||
cursor: pointer;
|
||||
transition: transform 0.1s ease;
|
||||
}
|
||||
|
||||
.custom-range::-moz-range-thumb:hover {
|
||||
transform: scale(1.15);
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
/* Color Variants */
|
||||
.custom-range-purple {
|
||||
--range-color: var(--color-neon-purple);
|
||||
--range-color: var(--color-neon-purple);
|
||||
}
|
||||
.custom-range-green {
|
||||
--range-color: var(--color-neon-green);
|
||||
--range-color: var(--color-neon-green);
|
||||
}
|
||||
.custom-range-cyan {
|
||||
--range-color: var(--color-neon-cyan);
|
||||
--range-color: var(--color-neon-cyan);
|
||||
}
|
||||
.custom-range-yellow {
|
||||
--range-color: var(--color-neon-yellow);
|
||||
--range-color: var(--color-neon-yellow);
|
||||
}
|
||||
.custom-range-accent {
|
||||
--range-color: var(--color-neon-cyan);
|
||||
--range-color: var(--color-neon-cyan);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user