# Settings & Dark Mode Implementation

**Status**: ✅ Phase 1 Complete, Phase 2 Complete  
**Last Updated**: January 2026

---

## Overview

A comprehensive user settings system with persistent preferences, dark mode support, and customizable list display options. Settings are stored per-user in localStorage and automatically applied across the application.

---

## Architecture

### Context Hierarchy
```
<ConfigProvider>          ← Server config (image limits, etc.)
  <AuthProvider>          ← Authentication state
    <SettingsProvider>    ← User preferences (NEW)
      <App />
    </SettingsProvider>
  </AuthProvider>
</ConfigProvider>
```

### Key Components

#### SettingsContext ([frontend/src/context/SettingsContext.jsx](frontend/src/context/SettingsContext.jsx))
- Manages user preferences with localStorage persistence
- Storage key pattern: `user_preferences_${username}`
- Automatically applies theme to `document.documentElement`
- Listens for system theme changes in auto mode
- Provides `updateSettings()` and `resetSettings()` methods

#### Settings Page ([frontend/src/pages/Settings.jsx](frontend/src/pages/Settings.jsx))
- Tabbed interface: Appearance, List Display, Behavior
- Real-time preview of setting changes
- Reset to defaults functionality

---

## Settings Schema

```javascript
{
  // === Appearance ===
  theme: "light" | "dark" | "auto",  // Theme mode
  compactView: false,                 // Reduced spacing for denser lists
  
  // === List Display ===
  defaultSortMode: "zone",           // Default: "zone" | "az" | "za" | "qty-high" | "qty-low"
  showRecentlyBought: true,          // Toggle recently bought section
  recentlyBoughtCount: 10,           // Initial items shown (5-50)
  recentlyBoughtCollapsed: false,    // Start section collapsed
  
  // === Behavior ===
  confirmBeforeBuy: true,            // Show confirmation modal
  autoReloadInterval: 0,             // Auto-refresh in minutes (0 = disabled)
  hapticFeedback: true,              // Vibration on mobile interactions
  
  // === Advanced ===
  debugMode: false                   // Developer tools (future)
}
```

---

## Dark Mode Implementation

### Theme System

**Three modes**:
1. **Light**: Force light theme
2. **Dark**: Force dark theme  
3. **Auto**: Follow system preferences with live updates

### CSS Variable Architecture

All colors use CSS custom properties defined in [frontend/src/styles/theme.css](frontend/src/styles/theme.css):

**Light Mode** (`:root`):
```css
:root {
  --color-text-primary: #212529;
  --color-bg-body: #f8f9fa;
  --color-bg-surface: #ffffff;
  /* ... */
}
```

**Dark Mode** (`[data-theme="dark"]`):
```css
[data-theme="dark"] {
  --color-text-primary: #f1f5f9;
  --color-bg-body: #0f172a;
  --color-bg-surface: #1e293b;
  /* ... */
}
```

### Theme Application Logic

```javascript
// In SettingsContext.jsx
useEffect(() => {
  const applyTheme = () => {
    let theme = settings.theme;
    
    // Auto mode: check system preference
    if (theme === "auto") {
      const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
      theme = prefersDark ? "dark" : "light";
    }
    
    document.documentElement.setAttribute("data-theme", theme);
  };
  
  applyTheme();
  
  // Listen for system theme changes
  if (settings.theme === "auto") {
    const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
    mediaQuery.addEventListener("change", applyTheme);
    return () => mediaQuery.removeEventListener("change", applyTheme);
  }
}, [settings.theme]);
```

---

## Integration with Existing Features

### GroceryList Integration

**Changed**:
```javascript
// Before
const [sortMode, setSortMode] = useState("zone");
const [recentlyBoughtDisplayCount, setRecentlyBoughtDisplayCount] = useState(10);

// After
const { settings } = useContext(SettingsContext);
const [sortMode, setSortMode] = useState(settings.defaultSortMode);
const [recentlyBoughtDisplayCount, setRecentlyBoughtDisplayCount] = useState(settings.recentlyBoughtCount);
const [recentlyBoughtCollapsed, setRecentlyBoughtCollapsed] = useState(settings.recentlyBoughtCollapsed);
```

**Features**:
- Sort mode persists across sessions
- Recently bought section respects visibility setting
- Collapse state controlled by user preference
- Initial display count uses user's preference

---

## File Structure

```
frontend/src/
├── context/
│   └── SettingsContext.jsx          ← Settings state management
├── pages/
│   └── Settings.jsx                 ← Settings UI
├── styles/
│   ├── theme.css                    ← Dark mode CSS variables
│   └── pages/
│       └── Settings.css             ← Settings page styles
└── App.jsx                          ← Settings route & provider
```

---

## Usage Examples

### Access Settings in Component

```javascript
import { useContext } from "react";
import { SettingsContext } from "../context/SettingsContext";

function MyComponent() {
  const { settings, updateSettings } = useContext(SettingsContext);
  
  // Read setting
  const isDark = settings.theme === "dark";
  
  // Update setting
  const toggleTheme = () => {
    updateSettings({ 
      theme: settings.theme === "dark" ? "light" : "dark" 
    });
  };
  
  return <button onClick={toggleTheme}>Toggle Theme</button>;
}
```

### Conditional Rendering Based on Settings

```javascript
{settings.showRecentlyBought && (
  <RecentlyBoughtSection />
)}
```

### Using Theme Colors

```css
.my-component {
  background: var(--color-bg-surface);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border-light);
}
```

---

## localStorage Structure

**Key**: `user_preferences_${username}`

**Example stored value**:
```json
{
  "theme": "dark",
  "compactView": false,
  "defaultSortMode": "zone",
  "showRecentlyBought": true,
  "recentlyBoughtCount": 20,
  "recentlyBoughtCollapsed": false,
  "confirmBeforeBuy": true,
  "autoReloadInterval": 0,
  "hapticFeedback": true,
  "debugMode": false
}
```

---

## Testing Checklist

### Settings Page
- [ ] All three tabs accessible
- [ ] Theme toggle works (light/dark/auto)
- [ ] Auto mode follows system preference
- [ ] Settings persist after logout/login
- [ ] Reset button restores defaults

### Dark Mode
- [ ] All pages render correctly in dark mode
- [ ] Modals readable in dark mode
- [ ] Forms and inputs visible in dark mode
- [ ] Navigation and buttons styled correctly
- [ ] Images and borders contrast properly

### GroceryList Integration
- [ ] Default sort mode applied on load
- [ ] Recently bought visibility respected
- [ ] Collapse state persists during session
- [ ] Display count uses user preference

---

## Future Enhancements (Not Implemented)

### Phase 3: Advanced Preferences
- **Compact View**: Reduced padding/font sizes for power users
- **Confirm Before Buy**: Toggle for confirmation modal
- **Auto-reload**: Refresh list every X minutes for shared lists

### Phase 4: Account Management
- **Change Password**: Security feature (needs backend endpoint)
- **Display Name**: Friendly name separate from username

### Phase 5: Data Management
- **Export List**: Download as CSV/JSON
- **Clear History**: Remove recently bought items
- **Import Items**: Bulk add from file

### Phase 6: Accessibility
- **Font Size**: Adjustable text sizing
- **High Contrast Mode**: Increased contrast for visibility
- **Reduce Motion**: Disable animations

---

## API Endpoints

**None required** - all settings are client-side only.

Future backend endpoints may include:
- `PATCH /api/users/me` - Update user profile (password, display name)
- `GET /api/list/export` - Export grocery list data

---

## Browser Compatibility

### Theme Detection
- Chrome/Edge: ✅ Full support
- Firefox: ✅ Full support
- Safari: ✅ Full support (iOS 12.2+)
- Mobile browsers: ✅ Full support

### localStorage
- All modern browsers: ✅ Supported
- Fallback: Settings work but don't persist (rare)

---

## Troubleshooting

### Settings Don't Persist
**Issue**: Settings reset after logout  
**Cause**: Settings tied to username  
**Solution**: Working as designed - each user has separate preferences

### Dark Mode Not Applied
**Issue**: Page stays light after selecting dark  
**Cause**: Missing `data-theme` attribute  
**Solution**: Check SettingsContext is wrapped around App

### System Theme Not Detected
**Issue**: Auto mode doesn't work  
**Cause**: Browser doesn't support `prefers-color-scheme`  
**Solution**: Fallback to light mode (handled automatically)

---

## Development Notes

### Adding New Settings

1. **Update DEFAULT_SETTINGS** in SettingsContext.jsx:
```javascript
const DEFAULT_SETTINGS = {
  // ...existing settings
  myNewSetting: defaultValue,
};
```

2. **Add UI in Settings.jsx**:
```javascript
<div className="settings-group">
  <label className="settings-label">
    <input
      type="checkbox"
      checked={settings.myNewSetting}
      onChange={() => handleToggle("myNewSetting")}
    />
    <span>My New Setting</span>
  </label>
  <p className="settings-description">Description here</p>
</div>
```

3. **Use in components**:
```javascript
const { settings } = useContext(SettingsContext);
if (settings.myNewSetting) {
  // Do something
}
```

### Adding Theme Colors

1. Define in both light (`:root`) and dark (`[data-theme="dark"]`) modes
2. Use descriptive semantic names: `--color-purpose-variant`
3. Always provide fallbacks for older code

---

## Performance Considerations

- Settings load once per user session
- Theme changes apply instantly (no page reload)
- localStorage writes are debounced by React state updates
- No network requests for settings (all client-side)

---

## Accessibility

- ✅ Keyboard navigation works in Settings page
- ✅ Theme buttons have clear active states
- ✅ Range sliders show current values
- ✅ Color contrast meets WCAG AA in both themes
- ⚠️ Screen reader announcements for theme changes (future enhancement)

---

## Migration Notes

**Upgrading from older versions**:
- Old settings are preserved (merged with defaults)
- Missing settings use default values
- Invalid values are reset to defaults
- No migration script needed - handled automatically

---

## Related Documentation

- [Code Cleanup Guide](code-cleanup-guide.md) - Code organization patterns
- [Component Structure](component-structure.md) - Component architecture
- [Theme Usage Examples](../frontend/src/styles/THEME_USAGE_EXAMPLES.css) - CSS variable usage

---

**Implementation Status**: ✅ Complete  
**Phase 1 (Foundation)**: ✅ Complete  
**Phase 2 (Dark Mode)**: ✅ Complete  
**Phase 3 (List Preferences)**: ✅ Complete  
**Phase 4+ (Future)**: ⏳ Planned
