feat: add view mode toggle with compact/cozy/comfortable options

Implemented message density control with three view modes:
- Compact: Tight spacing (10px gaps), smaller text (13px), small avatars (24px)
- Cozy: Balanced spacing (16px gaps), default text (14px) - default mode
- Comfortable: Spacious layout (24px gaps), larger text (15px), larger avatars (32px)

Features:
- View mode selector in Appearance tab
- Persistent preference saved to localStorage
- Dynamic CSS classes applied to body element
- Adjusts message padding, gaps, font sizes, avatar sizes
- Scales headings, code blocks, and all UI elements proportionally

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-14 12:32:07 -07:00
parent 32fc57fab0
commit 30e6af61ca
3 changed files with 166 additions and 1 deletions

View File

@@ -146,6 +146,30 @@ function loadSavedTheme() {
applyTheme(savedTheme);
}
// Apply view mode
function applyViewMode(mode) {
const body = document.body;
// Remove all view mode classes
body.classList.remove('view-compact', 'view-cozy', 'view-comfortable');
// Add the selected mode
body.classList.add(`view-${mode}`);
// Store preference
localStorage.setItem('claudia-view-mode', mode);
}
// Load saved view mode
function loadSavedViewMode() {
const savedMode = localStorage.getItem('claudia-view-mode') || 'cozy';
const viewModeSelect = document.getElementById('view-mode-select');
if (viewModeSelect) {
viewModeSelect.value = savedMode;
}
applyViewMode(savedMode);
}
// Helper function to get avatar URL
async function getAvatarUrl(avatarFilename) {
if (!avatarFilename) return null;
@@ -1179,6 +1203,14 @@ function setupAppControls() {
applyTheme(e.target.value);
});
}
// Setup view mode selector
const viewModeSelect = document.getElementById('view-mode-select');
if (viewModeSelect) {
viewModeSelect.addEventListener('change', (e) => {
applyViewMode(e.target.value);
});
}
}
// Keyboard shortcuts
@@ -1573,8 +1605,9 @@ window.addEventListener('DOMContentLoaded', () => {
messageInput.focus();
setStatus('Ready');
// Load saved theme before anything else
// Load saved preferences before anything else
loadSavedTheme();
loadSavedViewMode();
loadExistingConfig();
});