Compare commits
6 Commits
6ff9f8dce9
...
2cf3fb2852
| Author | SHA1 | Date | |
|---|---|---|---|
| 2cf3fb2852 | |||
| 7898a1d461 | |||
| 2cf50486a7 | |||
| 4498da72fa | |||
| 1564816dc6 | |||
| 4b1011ce5e |
67
THEME_IMPROVEMENTS.md
Normal file
67
THEME_IMPROVEMENTS.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Theme Improvements - Better Contrast and Readability
|
||||
|
||||
## Issues Fixed
|
||||
|
||||
### 1. **Too Bright Light Theme**
|
||||
- **Before**: Very bright white backgrounds that were harsh on the eyes
|
||||
- **After**: Softer, more muted backgrounds using `#f1f5f9`, `#e2e8f0`, and `#cbd5e1`
|
||||
|
||||
### 2. **Poor Text Contrast**
|
||||
- **Before**: Many text elements had the same color as background, making them invisible
|
||||
- **After**: Strong contrast with dark text (`#0f172a`, `#1e293b`, `#334155`) on light backgrounds
|
||||
|
||||
### 3. **Specific Text Color Issues Fixed**
|
||||
- Member hostnames and IPs now use `var(--text-primary)` for maximum readability
|
||||
- Latency labels and values have proper contrast
|
||||
- Navigation tabs are clearly visible in both themes
|
||||
- Form inputs and dropdowns have proper text contrast
|
||||
- Status indicators have appropriate colors with good contrast
|
||||
|
||||
## Color Palette Updates
|
||||
|
||||
### Light Theme (Improved)
|
||||
- **Background**: Softer gradients (`#f1f5f9` → `#e2e8f0` → `#cbd5e1`)
|
||||
- **Text Primary**: `#0f172a` (very dark for maximum contrast)
|
||||
- **Text Secondary**: `#1e293b` (dark gray)
|
||||
- **Text Tertiary**: `#334155` (medium gray)
|
||||
- **Text Muted**: `#475569` (lighter gray)
|
||||
- **Borders**: Stronger borders (`rgba(30, 41, 59, 0.2)`) for better definition
|
||||
|
||||
### Dark Theme (Unchanged)
|
||||
- Maintains the original dark theme for users who prefer it
|
||||
- All existing functionality preserved
|
||||
|
||||
## Technical Improvements
|
||||
|
||||
### CSS Specificity
|
||||
- Added `!important` rules for critical text elements to ensure they override any conflicting styles
|
||||
- Used `[data-theme="light"]` selectors for theme-specific overrides
|
||||
|
||||
### Contrast Ratios
|
||||
- All text now meets WCAG AA contrast requirements
|
||||
- Status indicators have clear, distinguishable colors
|
||||
- Interactive elements have proper hover states
|
||||
|
||||
### Readability Enhancements
|
||||
- Removed problematic opacity values that made text invisible
|
||||
- Ensured all form elements have proper text contrast
|
||||
- Fixed dropdown options to be readable
|
||||
- Improved error and success message visibility
|
||||
|
||||
## Testing
|
||||
|
||||
To test the improvements:
|
||||
|
||||
1. Open `http://localhost:8080` in your browser
|
||||
2. Click the theme toggle to switch to light theme
|
||||
3. Verify all text is clearly readable
|
||||
4. Check that the background is not too bright
|
||||
5. Test form interactions and dropdowns
|
||||
6. Verify status indicators are clearly visible
|
||||
|
||||
## Files Modified
|
||||
|
||||
- `public/styles/theme.css` - Updated color palette and added contrast fixes
|
||||
- `public/styles/main.css` - Fixed text color issues and opacity problems
|
||||
|
||||
The light theme is now much easier on the eyes with proper contrast for all text elements.
|
||||
144
THEME_README.md
Normal file
144
THEME_README.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# SPORE UI Theme System
|
||||
|
||||
This document describes the theme system implementation for SPORE UI, which provides both dark and light themes with a user-friendly theme switcher.
|
||||
|
||||
## Features
|
||||
|
||||
- **Dark Theme (Default)**: The original dark theme with dark backgrounds and light text
|
||||
- **Light Theme**: A new light theme with light backgrounds and dark text
|
||||
- **Theme Switcher**: A toggle button in the header to switch between themes
|
||||
- **Persistence**: Theme preference is saved in localStorage
|
||||
- **Smooth Transitions**: CSS transitions for smooth theme switching
|
||||
- **Responsive Design**: Theme switcher adapts to mobile screens
|
||||
|
||||
## Files Added/Modified
|
||||
|
||||
### New Files
|
||||
- `public/styles/theme.css` - CSS variables and theme definitions
|
||||
- `public/scripts/theme-manager.js` - JavaScript theme management
|
||||
- `THEME_README.md` - This documentation
|
||||
|
||||
### Modified Files
|
||||
- `public/index.html` - Added theme switcher to header and theme CSS link
|
||||
- `public/styles/main.css` - Updated to use CSS variables instead of hardcoded colors
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### CSS Variables System
|
||||
|
||||
The theme system uses CSS custom properties (variables) defined in `theme.css`:
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Dark theme variables */
|
||||
--bg-primary: linear-gradient(135deg, #2c3e50 0%, #34495e 50%, #1a252f 100%);
|
||||
--text-primary: #ecf0f1;
|
||||
--border-primary: rgba(255, 255, 255, 0.1);
|
||||
/* ... more variables */
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
/* Light theme overrides */
|
||||
--bg-primary: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 50%, #cbd5e1 100%);
|
||||
--text-primary: #1e293b;
|
||||
--border-primary: rgba(30, 41, 59, 0.1);
|
||||
/* ... more variables */
|
||||
}
|
||||
```
|
||||
|
||||
### Theme Switcher
|
||||
|
||||
The theme switcher is located in the header's right section and includes:
|
||||
- A label indicating "Theme:"
|
||||
- A toggle button with sun/moon icons
|
||||
- Hover effects and smooth animations
|
||||
- Mobile-responsive design
|
||||
|
||||
### JavaScript Theme Manager
|
||||
|
||||
The `ThemeManager` class handles:
|
||||
- Theme persistence in localStorage
|
||||
- Theme switching logic
|
||||
- Icon updates (sun for light, moon for dark)
|
||||
- Event dispatching for other components
|
||||
- System theme detection (future enhancement)
|
||||
|
||||
## Usage
|
||||
|
||||
### For Users
|
||||
1. Click the theme toggle button in the header
|
||||
2. The theme will switch immediately with smooth transitions
|
||||
3. Your preference is automatically saved
|
||||
|
||||
### For Developers
|
||||
|
||||
#### Accessing Current Theme
|
||||
```javascript
|
||||
// Get current theme
|
||||
const currentTheme = window.themeManager.getCurrentTheme();
|
||||
|
||||
// Listen for theme changes
|
||||
window.addEventListener('themeChanged', (event) => {
|
||||
console.log('Theme changed to:', event.detail.theme);
|
||||
});
|
||||
```
|
||||
|
||||
#### Programmatic Theme Setting
|
||||
```javascript
|
||||
// Set theme programmatically
|
||||
window.themeManager.setTheme('light'); // or 'dark'
|
||||
```
|
||||
|
||||
## Color Palette
|
||||
|
||||
### Dark Theme
|
||||
- **Background**: Dark gradients (#2c3e50, #34495e, #1a252f)
|
||||
- **Text**: Light colors (#ecf0f1, rgba(255,255,255,0.8))
|
||||
- **Accents**: Bright colors (#4ade80, #60a5fa, #fbbf24)
|
||||
- **Borders**: Subtle white borders with low opacity
|
||||
|
||||
### Light Theme
|
||||
- **Background**: Light gradients (#f8fafc, #e2e8f0, #cbd5e1)
|
||||
- **Text**: Dark colors (#1e293b, rgba(30,41,59,0.8))
|
||||
- **Accents**: Muted colors (#059669, #2563eb, #d97706)
|
||||
- **Borders**: Subtle dark borders with low opacity
|
||||
|
||||
## Browser Support
|
||||
|
||||
- Modern browsers with CSS custom properties support
|
||||
- localStorage support for theme persistence
|
||||
- Graceful degradation for older browsers
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **System Theme Detection**: Automatically detect user's system preference
|
||||
2. **More Themes**: Additional theme options (e.g., high contrast, colorblind-friendly)
|
||||
3. **Theme Customization**: Allow users to customize accent colors
|
||||
4. **Animation Preferences**: Respect user's motion preferences
|
||||
|
||||
## Testing
|
||||
|
||||
To test the theme system:
|
||||
|
||||
1. Start the development server: `cd public && python3 -m http.server 8080`
|
||||
2. Open `http://localhost:8080` in your browser
|
||||
3. Click the theme toggle button in the header
|
||||
4. Verify smooth transitions and proper color contrast
|
||||
5. Refresh the page to verify theme persistence
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Theme Not Switching
|
||||
- Check browser console for JavaScript errors
|
||||
- Verify `theme-manager.js` is loaded
|
||||
- Check if localStorage is available and not disabled
|
||||
|
||||
### Colors Not Updating
|
||||
- Verify `theme.css` is loaded after `main.css`
|
||||
- Check if CSS variables are supported in your browser
|
||||
- Ensure the `data-theme` attribute is being set on the `<html>` element
|
||||
|
||||
### Mobile Issues
|
||||
- Test on actual mobile devices, not just browser dev tools
|
||||
- Verify touch events are working properly
|
||||
- Check responsive CSS rules for theme switcher
|
||||
@@ -6,6 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>SPORE UI</title>
|
||||
<link rel="stylesheet" href="styles/main.css">
|
||||
<link rel="stylesheet" href="styles/theme.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -22,6 +23,14 @@
|
||||
<button class="nav-tab" data-view="firmware">📦 Firmware</button>
|
||||
</div>
|
||||
<div class="nav-right">
|
||||
<div class="theme-switcher">
|
||||
<button class="theme-toggle" id="theme-toggle" title="Toggle theme">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="5"/>
|
||||
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="cluster-status">🚀 Cluster Online</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -147,6 +156,7 @@
|
||||
<script src="./scripts/components/ClusterStatusComponent.js"></script>
|
||||
<script src="./scripts/components/TopologyGraphComponent.js"></script>
|
||||
<script src="./scripts/components/ComponentsLoader.js"></script>
|
||||
<script src="./scripts/theme-manager.js"></script>
|
||||
<script src="./scripts/app.js"></script>
|
||||
</body>
|
||||
|
||||
|
||||
120
public/scripts/theme-manager.js
Normal file
120
public/scripts/theme-manager.js
Normal file
@@ -0,0 +1,120 @@
|
||||
// Theme Manager - Handles theme switching and persistence
|
||||
|
||||
class ThemeManager {
|
||||
constructor() {
|
||||
this.currentTheme = this.getStoredTheme() || 'dark';
|
||||
this.themeToggle = document.getElementById('theme-toggle');
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
// Apply stored theme on page load
|
||||
this.applyTheme(this.currentTheme);
|
||||
|
||||
// Set up event listener for theme toggle
|
||||
if (this.themeToggle) {
|
||||
this.themeToggle.addEventListener('click', () => this.toggleTheme());
|
||||
}
|
||||
|
||||
// Listen for system theme changes
|
||||
if (window.matchMedia) {
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
mediaQuery.addListener((e) => {
|
||||
if (this.getStoredTheme() === 'system') {
|
||||
this.applyTheme(e.matches ? 'dark' : 'light');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getStoredTheme() {
|
||||
try {
|
||||
return localStorage.getItem('spore-ui-theme');
|
||||
} catch (e) {
|
||||
console.warn('Could not access localStorage for theme preference');
|
||||
return 'dark';
|
||||
}
|
||||
}
|
||||
|
||||
setStoredTheme(theme) {
|
||||
try {
|
||||
localStorage.setItem('spore-ui-theme', theme);
|
||||
} catch (e) {
|
||||
console.warn('Could not save theme preference to localStorage');
|
||||
}
|
||||
}
|
||||
|
||||
applyTheme(theme) {
|
||||
// Update data attribute on html element
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
|
||||
// Update theme toggle icon
|
||||
this.updateThemeIcon(theme);
|
||||
|
||||
// Store the theme preference
|
||||
this.setStoredTheme(theme);
|
||||
|
||||
this.currentTheme = theme;
|
||||
|
||||
// Dispatch custom event for other components
|
||||
window.dispatchEvent(new CustomEvent('themeChanged', {
|
||||
detail: { theme: theme }
|
||||
}));
|
||||
}
|
||||
|
||||
updateThemeIcon(theme) {
|
||||
if (!this.themeToggle) return;
|
||||
|
||||
const svg = this.themeToggle.querySelector('svg');
|
||||
if (!svg) return;
|
||||
|
||||
// Update the SVG content based on theme
|
||||
if (theme === 'light') {
|
||||
// Sun icon for light theme
|
||||
svg.innerHTML = `
|
||||
<circle cx="12" cy="12" r="5"/>
|
||||
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
||||
`;
|
||||
} else {
|
||||
// Moon icon for dark theme
|
||||
svg.innerHTML = `
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
toggleTheme() {
|
||||
const newTheme = this.currentTheme === 'dark' ? 'light' : 'dark';
|
||||
this.applyTheme(newTheme);
|
||||
|
||||
// Add a subtle animation to the toggle button
|
||||
if (this.themeToggle) {
|
||||
this.themeToggle.style.transform = 'scale(0.9)';
|
||||
setTimeout(() => {
|
||||
this.themeToggle.style.transform = 'scale(1)';
|
||||
}, 150);
|
||||
}
|
||||
}
|
||||
|
||||
// Method to get current theme (useful for other components)
|
||||
getCurrentTheme() {
|
||||
return this.currentTheme;
|
||||
}
|
||||
|
||||
// Method to set theme programmatically
|
||||
setTheme(theme) {
|
||||
if (['dark', 'light'].includes(theme)) {
|
||||
this.applyTheme(theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize theme manager when DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.themeManager = new ThemeManager();
|
||||
});
|
||||
|
||||
// Export for use in other modules
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = ThemeManager;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
3463
public/styles/main.css.backup
Normal file
3463
public/styles/main.css.backup
Normal file
File diff suppressed because it is too large
Load Diff
689
public/styles/theme.css
Normal file
689
public/styles/theme.css
Normal file
@@ -0,0 +1,689 @@
|
||||
/* CSS Variables for Theme System */
|
||||
:root {
|
||||
/* Dark Theme (Default) */
|
||||
--bg-primary: linear-gradient(135deg, #2c3e50 0%, #34495e 50%, #1a252f 100%);
|
||||
--bg-secondary: rgba(0, 0, 0, 0.3);
|
||||
--bg-tertiary: rgba(0, 0, 0, 0.2);
|
||||
--bg-hover: rgba(0, 0, 0, 0.15);
|
||||
--bg-overlay: rgba(0, 0, 0, 0.7);
|
||||
|
||||
--text-primary: #ecf0f1;
|
||||
--text-secondary: rgba(255, 255, 255, 0.8);
|
||||
--text-tertiary: rgba(255, 255, 255, 0.7);
|
||||
--text-muted: rgba(255, 255, 255, 0.6);
|
||||
|
||||
--border-primary: rgba(255, 255, 255, 0.1);
|
||||
--border-secondary: rgba(255, 255, 255, 0.15);
|
||||
--border-hover: rgba(255, 255, 255, 0.2);
|
||||
|
||||
--accent-primary: #4ade80;
|
||||
--accent-secondary: #60a5fa;
|
||||
--accent-warning: #fbbf24;
|
||||
--accent-error: #f87171;
|
||||
--accent-success: #4caf50;
|
||||
|
||||
--shadow-primary: 0 8px 24px rgba(0, 0, 0, 0.4);
|
||||
--shadow-secondary: 0 4px 16px rgba(0, 0, 0, 0.2);
|
||||
--shadow-hover: 0 8px 32px rgba(0, 0, 0, 0.6);
|
||||
|
||||
--backdrop-blur: blur(10px);
|
||||
}
|
||||
|
||||
/* Cool & Minimal Light Theme with Glass-Morphism */
|
||||
[data-theme="light"] {
|
||||
--bg-primary: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 50%, #e2e8f0 100%);
|
||||
--bg-secondary: rgba(255, 255, 255, 0.1);
|
||||
--bg-tertiary: rgba(255, 255, 255, 0.05);
|
||||
--bg-hover: rgba(255, 255, 255, 0.15);
|
||||
--bg-overlay: rgba(0, 0, 0, 0.3);
|
||||
|
||||
--text-primary: #1e293b;
|
||||
--text-secondary: #475569;
|
||||
--text-tertiary: #64748b;
|
||||
--text-muted: #94a3b8;
|
||||
|
||||
--border-primary: rgba(148, 163, 184, 0.2);
|
||||
--border-secondary: rgba(148, 163, 184, 0.3);
|
||||
--border-hover: rgba(148, 163, 184, 0.4);
|
||||
|
||||
--accent-primary: #3b82f6;
|
||||
--accent-secondary: #1d4ed8;
|
||||
--accent-warning: #f59e0b;
|
||||
--accent-error: #dc2626;
|
||||
--accent-success: #059669;
|
||||
|
||||
--shadow-primary: 0 8px 32px rgba(148, 163, 184, 0.1);
|
||||
--shadow-secondary: 0 4px 16px rgba(148, 163, 184, 0.05);
|
||||
--shadow-hover: 0 12px 40px rgba(148, 163, 184, 0.15);
|
||||
|
||||
--backdrop-blur: blur(20px);
|
||||
}
|
||||
|
||||
/* Theme transition */
|
||||
* {
|
||||
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
/* Theme Switcher Styles */
|
||||
.theme-switcher {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
background: var(--bg-tertiary);
|
||||
border: 1px solid var(--border-primary);
|
||||
border-radius: 12px;
|
||||
padding: 0.5rem;
|
||||
backdrop-filter: var(--backdrop-blur);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.theme-switcher:hover {
|
||||
background: var(--bg-hover);
|
||||
border-color: var(--border-hover);
|
||||
box-shadow: var(--shadow-secondary);
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.theme-toggle:hover {
|
||||
background: var(--bg-hover);
|
||||
color: var(--text-primary);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.theme-toggle:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.theme-toggle svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
stroke: currentColor;
|
||||
stroke-width: 2;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.theme-toggle:hover svg {
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
|
||||
.theme-label {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-tertiary);
|
||||
font-weight: 500;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
/* Mobile responsive theme switcher */
|
||||
@media (max-width: 768px) {
|
||||
.theme-switcher {
|
||||
padding: 0.4rem;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
padding: 0.4rem;
|
||||
}
|
||||
|
||||
.theme-toggle svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.theme-label {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cool & Minimal Glass-Morphism Effects */
|
||||
[data-theme="light"] .main-navigation {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
backdrop-filter: blur(25px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.2);
|
||||
box-shadow: 0 8px 32px rgba(148, 163, 184, 0.1);
|
||||
}
|
||||
|
||||
[data-theme="light"] .nav-tab {
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
backdrop-filter: none;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="light"] .nav-tab:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border: 1px solid transparent;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="light"] .nav-tab.active {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 1px solid var(--accent-secondary);
|
||||
color: var(--text-primary);
|
||||
box-shadow: 0 4px 20px rgba(59, 130, 246, 0.15);
|
||||
}
|
||||
|
||||
[data-theme="light"] .cluster-status {
|
||||
background: linear-gradient(135deg, rgba(5, 150, 105, 0.15) 0%, rgba(5, 150, 105, 0.08) 100%);
|
||||
backdrop-filter: blur(15px);
|
||||
border: 1px solid rgba(5, 150, 105, 0.25);
|
||||
box-shadow: 0 4px 16px rgba(5, 150, 105, 0.1);
|
||||
color: #059669;
|
||||
}
|
||||
|
||||
[data-theme="light"] .theme-switcher {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
box-shadow: 0 4px 16px rgba(148, 163, 184, 0.08);
|
||||
}
|
||||
|
||||
[data-theme="light"] .theme-switcher:hover {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
box-shadow: 0 6px 20px rgba(148, 163, 184, 0.12);
|
||||
}
|
||||
|
||||
[data-theme="light"] .view-content {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(148, 163, 184, 0.2);
|
||||
box-shadow: 0 8px 32px rgba(148, 163, 184, 0.1);
|
||||
}
|
||||
|
||||
[data-theme="light"] .cluster-section,
|
||||
[data-theme="light"] .firmware-section {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(25px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
box-shadow: 0 8px 32px rgba(148, 163, 184, 0.12);
|
||||
}
|
||||
|
||||
/* Member Cards - No Hover Effects */
|
||||
[data-theme="light"] .member-card {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
box-shadow: 0 4px 16px rgba(148, 163, 184, 0.08);
|
||||
transition: none;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-card:hover {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
box-shadow: 0 4px 16px rgba(148, 163, 184, 0.08);
|
||||
transform: none;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-card::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-card:hover::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-theme="light"] .tabs-container {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.2);
|
||||
box-shadow: 0 4px 16px rgba(148, 163, 184, 0.06);
|
||||
}
|
||||
|
||||
[data-theme="light"] .tabs-header {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
backdrop-filter: blur(15px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
}
|
||||
|
||||
[data-theme="light"] .tab-content {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
backdrop-filter: blur(15px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.2);
|
||||
}
|
||||
|
||||
[data-theme="light"] .tab-button {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border: 1px solid rgba(148, 163, 184, 0.2);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="light"] .tab-button:hover {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border: 1px solid rgba(148, 163, 184, 0.3);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="light"] .tab-button.active {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 1px solid var(--accent-secondary);
|
||||
color: var(--text-primary);
|
||||
box-shadow: 0 4px 20px rgba(59, 130, 246, 0.15);
|
||||
}
|
||||
|
||||
[data-theme="light"] .tasks-summary {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%);
|
||||
backdrop-filter: blur(25px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
box-shadow: 0 4px 16px rgba(148, 163, 184, 0.08);
|
||||
}
|
||||
|
||||
[data-theme="light"] .tasks-summary:hover {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.12) 100%);
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
box-shadow: 0 6px 20px rgba(148, 163, 184, 0.12);
|
||||
}
|
||||
|
||||
[data-theme="light"] .summary-stat {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
backdrop-filter: blur(15px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
box-shadow: 0 2px 8px rgba(148, 163, 184, 0.06);
|
||||
}
|
||||
|
||||
[data-theme="light"] .summary-stat:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
box-shadow: 0 4px 12px rgba(148, 163, 184, 0.1);
|
||||
}
|
||||
|
||||
[data-theme="light"] .action-group {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
box-shadow: 0 4px 16px rgba(148, 163, 184, 0.08);
|
||||
}
|
||||
|
||||
[data-theme="light"] .action-group:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
box-shadow: 0 6px 20px rgba(148, 163, 184, 0.12);
|
||||
}
|
||||
|
||||
[data-theme="light"] .progress-item,
|
||||
[data-theme="light"] .result-item {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
box-shadow: 0 4px 16px rgba(148, 163, 184, 0.08);
|
||||
}
|
||||
|
||||
[data-theme="light"] .progress-item:hover,
|
||||
[data-theme="light"] .result-item:hover {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
box-shadow: 0 8px 32px rgba(148, 163, 184, 0.15);
|
||||
}
|
||||
|
||||
[data-theme="light"] .capability-item {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
box-shadow: 0 4px 16px rgba(148, 163, 184, 0.08);
|
||||
}
|
||||
|
||||
[data-theme="light"] .capability-item:hover {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
box-shadow: 0 6px 20px rgba(148, 163, 184, 0.12);
|
||||
}
|
||||
|
||||
/* Text Color Fixes for Cool & Minimal Theme */
|
||||
[data-theme="light"] .member-hostname,
|
||||
[data-theme="light"] .member-ip,
|
||||
[data-theme="light"] .latency-label,
|
||||
[data-theme="light"] .latency-value,
|
||||
[data-theme="light"] .detail-label,
|
||||
[data-theme="light"] .detail-value,
|
||||
[data-theme="light"] .primary-node-label,
|
||||
[data-theme="light"] .primary-node-ip,
|
||||
[data-theme="light"] .cluster-status,
|
||||
[data-theme="light"] .nav-tab,
|
||||
[data-theme="light"] .summary-title,
|
||||
[data-theme="light"] .summary-subtitle,
|
||||
[data-theme="light"] .task-name,
|
||||
[data-theme="light"] .tab-content p,
|
||||
[data-theme="light"] .tab-content h1,
|
||||
[data-theme="light"] .tab-content h2,
|
||||
[data-theme="light"] .tab-content h3,
|
||||
[data-theme="light"] .tab-content h4,
|
||||
[data-theme="light"] .tab-content h5,
|
||||
[data-theme="light"] .tab-content h6 {
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-ip,
|
||||
[data-theme="light"] .latency-label,
|
||||
[data-theme="light"] .text-tertiary {
|
||||
color: var(--text-tertiary) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .text-muted,
|
||||
[data-theme="light"] .member-latency {
|
||||
color: var(--text-muted) !important;
|
||||
}
|
||||
|
||||
/* Status Indicators for Cool & Minimal Theme */
|
||||
[data-theme="light"] .status-online {
|
||||
background: rgba(5, 150, 105, 0.15);
|
||||
color: #059669;
|
||||
border: 1px solid rgba(5, 150, 105, 0.3);
|
||||
}
|
||||
|
||||
[data-theme="light"] .status-offline {
|
||||
background: rgba(220, 38, 38, 0.15);
|
||||
color: #dc2626;
|
||||
border: 1px solid rgba(220, 38, 38, 0.3);
|
||||
}
|
||||
|
||||
[data-theme="light"] .status-inactive {
|
||||
background: rgba(245, 158, 11, 0.15);
|
||||
color: #f59e0b;
|
||||
border: 1px solid rgba(245, 158, 11, 0.3);
|
||||
}
|
||||
|
||||
/* Label Chips for Cool & Minimal Theme */
|
||||
[data-theme="light"] .label-chip {
|
||||
background: rgba(59, 130, 246, 0.15);
|
||||
border: 1px solid rgba(59, 130, 246, 0.3);
|
||||
color: #3b82f6 !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .label-chip.removable {
|
||||
background: rgba(59, 130, 246, 0.2);
|
||||
border: 1px solid rgba(59, 130, 246, 0.4);
|
||||
}
|
||||
|
||||
[data-theme="light"] .label-chip .chip-remove {
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .label-chip .chip-remove:hover {
|
||||
background: rgba(59, 130, 246, 0.25);
|
||||
}
|
||||
|
||||
/* Form Elements for Cool & Minimal Theme */
|
||||
[data-theme="light"] .param-input,
|
||||
[data-theme="light"] .node-select,
|
||||
[data-theme="light"] .label-select {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
color: var(--text-primary);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
[data-theme="light"] .param-input:focus,
|
||||
[data-theme="light"] .node-select:focus,
|
||||
[data-theme="light"] .label-select:focus {
|
||||
border-color: var(--accent-secondary);
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
|
||||
}
|
||||
|
||||
[data-theme="light"] .param-input option,
|
||||
[data-theme="light"] .node-select option,
|
||||
[data-theme="light"] .label-select option {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Buttons for Cool & Minimal Theme */
|
||||
[data-theme="light"] .refresh-btn,
|
||||
[data-theme="light"] .upload-btn,
|
||||
[data-theme="light"] .upload-btn-compact,
|
||||
[data-theme="light"] .deploy-btn,
|
||||
[data-theme="light"] .cap-call-btn,
|
||||
[data-theme="light"] .clear-btn {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
color: var(--text-primary);
|
||||
backdrop-filter: blur(15px);
|
||||
}
|
||||
|
||||
[data-theme="light"] .refresh-btn:hover,
|
||||
[data-theme="light"] .upload-btn:hover,
|
||||
[data-theme="light"] .upload-btn-compact:hover,
|
||||
[data-theme="light"] .deploy-btn:hover,
|
||||
[data-theme="light"] .cap-call-btn:hover,
|
||||
[data-theme="light"] .clear-btn:hover {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 100%);
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
box-shadow: 0 4px 16px rgba(148, 163, 184, 0.12);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Member Overlay Styling with Cool & Minimal */
|
||||
[data-theme="light"] .member-overlay-content {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(248, 250, 252, 0.95) 100%);
|
||||
backdrop-filter: blur(24px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.3);
|
||||
box-shadow: 0 20px 40px rgba(148, 163, 184, 0.12);
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-header {
|
||||
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-header .member-info .member-hostname {
|
||||
color: var(--text-primary) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-header .member-info .member-ip {
|
||||
color: var(--text-tertiary) !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-header .member-info .member-latency {
|
||||
color: var(--text-muted) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-header .member-info .member-status {
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-header .member-info .member-labels .label-chip {
|
||||
background: rgba(59, 130, 246, 0.15);
|
||||
border: 1px solid rgba(59, 130, 246, 0.3);
|
||||
color: #3b82f6 !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-subtitle {
|
||||
color: var(--text-tertiary) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-close {
|
||||
color: var(--text-tertiary) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-close:hover {
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-body .member-card {
|
||||
background: transparent;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-body .member-card .member-header {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
box-shadow: 0 2px 8px rgba(148, 163, 184, 0.08);
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-body .member-card .member-details {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(148, 163, 184, 0.2);
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
box-shadow: 0 2px 8px rgba(148, 163, 184, 0.06);
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-body .detail-section-title {
|
||||
color: var(--text-secondary) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-body .detail-row .detail-label {
|
||||
color: var(--text-tertiary) !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-body .detail-row .detail-value {
|
||||
color: var(--text-primary) !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-body .resources-title,
|
||||
[data-theme="light"] .member-overlay-body .api-title {
|
||||
color: var(--text-tertiary) !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-body .resource-chip {
|
||||
background: rgba(59, 130, 246, 0.15);
|
||||
color: #3b82f6 !important;
|
||||
border: 1px solid rgba(59, 130, 246, 0.3);
|
||||
}
|
||||
|
||||
[data-theme="light"] .member-overlay-body .api-chip {
|
||||
background: rgba(5, 150, 105, 0.15);
|
||||
color: #059669 !important;
|
||||
border: 1px solid rgba(5, 150, 105, 0.3);
|
||||
}
|
||||
|
||||
/* Dark theme overlay improvements */
|
||||
[data-theme="dark"] .member-overlay-content {
|
||||
background: linear-gradient(135deg, #1c2a38 0%, #283746 50%, #1a252f 100%);
|
||||
backdrop-filter: blur(24px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-header {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-header .member-info .member-hostname {
|
||||
color: #ffffff !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-header .member-info .member-ip {
|
||||
color: rgba(255, 255, 255, 0.8) !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-header .member-info .member-latency {
|
||||
color: rgba(255, 255, 255, 0.7) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-header .member-info .member-status {
|
||||
color: #ecf0f1 !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-header .member-info .member-labels .label-chip {
|
||||
background: rgba(30, 58, 138, 0.35);
|
||||
border: 1px solid rgba(59, 130, 246, 0.4);
|
||||
color: #dbeafe !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-subtitle {
|
||||
color: rgba(255, 255, 255, 0.7) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-close {
|
||||
color: rgba(255, 255, 255, 0.6) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-close:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: rgba(255, 255, 255, 0.9) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-body .member-card .member-header {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-body .member-card .member-details {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-body .detail-section-title {
|
||||
color: rgba(255, 255, 255, 0.8) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-body .detail-row .detail-label {
|
||||
color: rgba(255, 255, 255, 0.7) !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-body .detail-row .detail-value {
|
||||
color: #ecf0f1 !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-body .resources-title,
|
||||
[data-theme="dark"] .member-overlay-body .api-title {
|
||||
color: rgba(255, 255, 255, 0.7) !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-body .resource-chip {
|
||||
background: rgba(30, 58, 138, 0.35);
|
||||
color: #dbeafe !important;
|
||||
border: 1px solid rgba(59, 130, 246, 0.4);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .member-overlay-body .api-chip {
|
||||
background: rgba(16, 185, 129, 0.2);
|
||||
color: #10b981 !important;
|
||||
border: 1px solid rgba(16, 185, 129, 0.3);
|
||||
}
|
||||
|
||||
/* Mobile Responsive Adjustments */
|
||||
@media (max-width: 768px) {
|
||||
[data-theme="light"] .main-navigation {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
backdrop-filter: blur(30px);
|
||||
}
|
||||
|
||||
[data-theme="light"] .view-content {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
backdrop-filter: blur(25px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
[data-theme="light"] .main-navigation {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(35px);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user