Date: 2026-01-11
Issue: Background pattern settings in SettingsPage were not updating the dashboard background in real-time.
Problem: The component was reading settings from the store once during initial render but not subscribing to changes.
Before:
const { settings } = useSettingsStore();
const currentPattern = (settings.find(s => s.key === 'ui_pattern')?.value || 'circuit') as PatternType;
const patternOpacity = (settings.find(s => s.key === 'ui_pattern_opacity')?.value || 0.03) as number;After:
// Use Zustand selectors to subscribe to specific settings for reactivity
const currentPattern = useSettingsStore(
(state) => (state.settings.find(s => s.key === 'ui_pattern')?.value || 'circuit') as PatternType
);
const patternOpacity = useSettingsStore(
(state) => (state.settings.find(s => s.key === 'ui_pattern_opacity')?.value || 0.03) as number
);Why this works: Zustand's selector pattern creates a subscription to the specific derived value. When updateSetting() is called in SettingsPage, it triggers a re-render in DashboardLayout because the selector detects the change.
Problem: The component was checking document.body.classList.contains('light-mode') which doesn't integrate with the actual theme system.
Before:
const isLightMode = document.body.classList.contains('light-mode');After:
const { theme } = useSystemStore();
const isLightMode = theme === 'light';Why this works: Now the component properly subscribes to theme changes from the systemStore, ensuring the correct light/dark pattern variant is loaded when the theme changes.
Problem: The backgroundImage style was missing quotes around the data URL, causing the browser to ignore the invalid CSS.
Before:
style={{
backgroundImage: `url(${patternUrl})`, // ❌ Invalid CSS - missing quotes
}}After:
style={{
backgroundImage: `url("${patternUrl}")`, // ✅ Valid CSS with quoted URL
}}Why this works: CSS url() function requires quotes around data URLs. Without quotes, the browser treats the data URL as an invalid value and ignores the entire background-image property, resulting in no pattern being displayed.
-
src/components/layout/DashboardLayout.tsx(The correct, active layout file)- Added imports for
useSettingsStoreandBackgroundPatterns - Changed from destructuring entire settings array to using Zustand selectors
- Removed static
bg-grid-patternCSS class - Added
<BackgroundPatterns />component with reactive props - Ensures component re-renders when pattern settings change
- Added imports for
-
src/components/ui/backgroundpatterns.tsx- Integrated
useSystemStore()for proper theme detection - Fixed import paths to match actual folder casing (
Patterns/Dark/instead ofpatterns/dark/) - Fixed critical CSS bug: Added quotes around data URL in
backgroundImagestyle - Fixed className concatenation to avoid "undefined" in class list
- Added debug logging for troubleshooting
- Integrated
-
src/lib/store/useSettingsStore.tsx- No changes needed (already using Zustand persist middleware correctly)
All tests passed successfully:
| Test | Result |
|---|---|
| Pattern Visibility | ✅ All patterns (geometric, circuit, wave, grid) render correctly |
| Real-time Updates | ✅ Changing pattern in settings updates background immediately |
| Opacity Control | ✅ Opacity slider works from 0.1 (subtle) to 0.8 (prominent) |
| Theme Integration | ✅ Patterns switch between light/dark variants with theme |
| Persistence | ✅ Settings saved to localStorage and restored on reload |
| Navigation | ✅ Patterns persist when navigating between pages |
| "None" Option | ✅ Selecting "none" removes the pattern completely |
- Login to CortexBridge at
http://localhost:6001 - Navigate to Settings (sidebar → Settings)
- Go to Appearance tab
- Test Pattern Changes:
- Change "Background Pattern" dropdown between:
geometric,circuit,wave,grid,none - Expected: Background should update immediately without page refresh
- Change "Background Pattern" dropdown between:
- Test Opacity Changes:
- Adjust "Pattern Opacity" slider (0.0 - 1.0)
- Expected: Background pattern opacity should change in real-time
- Test Theme Integration:
- Toggle between Light/Dark theme
- Expected: Pattern should switch to appropriate light/dark variant
The key insight is that Zustand requires selector functions to create subscriptions:
// ❌ NOT REACTIVE - reads once
const { settings } = useStore();
const value = settings.find(x => x.key === 'foo')?.value;
// ✅ REACTIVE - subscribes to changes
const value = useStore(state => state.settings.find(x => x.key === 'foo')?.value);The useSettingsStore uses Zustand's persist middleware with localStorage key 'cortexbridge-settings'. Changes are automatically saved and restored on page reload.
- Lint Warning: ESLint flags
window.location.hash = pageinhandleNavigate()as "modifying a value defined outside a component". This is a false positive - modifyingwindow.location.hashis standard browser API usage and is safe.
- Consider adding a "Preview" mode in settings that shows a live preview of the pattern
- Add animation transitions when switching patterns
- Consider adding custom pattern upload functionality
- Add pattern intensity/scale controls