diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 6795526..ded7067 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -3,4 +3,7 @@ ## Version v0.1.1 ### Features * Ability to add new logs through the web interface +### Modification + * Moved the style selection into the hamburger menu + * Toot formatting changed a wee bit ## Version v0.1.0 Initial release diff --git a/VIBE/CHAT_LOG.md b/VIBE/CHAT_LOG.md index 32fb5ff..51740e3 100644 --- a/VIBE/CHAT_LOG.md +++ b/VIBE/CHAT_LOG.md @@ -1250,3 +1250,9 @@ Put the new entry button left of the hamburger menu ### Assistant outcome Restructured all template headers to position the new-entry button inside the header-actions container, left of the menu-toggle button. Updated feed.html, about.html, admin.html, labels.html, user_profile.html, login.html, and new-entry.html. The button now appears in visual order: new-entry button, then hamburger menu toggle, with proper flexbox alignment and 8px spacing. All 54 backend tests pass. + +### User +The style selection should move into the hamburger menu - but in such a way that it becomes a submenu so that it doesn't clutter the menu structure + +### Assistant outcome +Moved the theme selector into the hamburger menu as a collapsible submenu. Added theme-submenu-container with a submenu-title button and submenu-options to all templates (feed.html, about.html, admin.html, labels.html, user_profile.html, login.html, new-entry.html). Updated theme.js to populate the submenu with theme buttons instead of adding a picker to header-actions. Updated auth-header.js to handle submenu toggle with aria-expanded for accessibility. Added comprehensive CSS styling for .theme-submenu-container, .submenu-title, .submenu-options, and .theme-option (including .active state). Theme selection now works cleanly within the menu without cluttering the header. All 54 backend tests pass. diff --git a/VIBE/PROMPTS.md b/VIBE/PROMPTS.md index 1de2237..7e29aaa 100644 --- a/VIBE/PROMPTS.md +++ b/VIBE/PROMPTS.md @@ -220,6 +220,7 @@ 210. After an entry is saved move to the // page 211. Don't put new entry in the hamburger menu but present it as a seperate button next to the style selector 212. Put the new entry button left of the hamburger menu +213. The style selection should move into the hamburger menu - but in such a way that it becomes a submenu so that it doesn't clutter the menu structure ## Future entries diff --git a/frontend/static/auth-header.js b/frontend/static/auth-header.js index 5f2d634..352dd08 100644 --- a/frontend/static/auth-header.js +++ b/frontend/static/auth-header.js @@ -14,6 +14,10 @@ const menu = document.querySelector('#auth-menu'); const menuToggle = document.querySelector('.menu-toggle'); const logoutButton = document.querySelector('#logout-button'); + + const themeSubmenuContainer = document.querySelector('#theme-submenu-container'); + const themeSubmenuTitle = document.querySelector('.submenu-title'); + const themeOptions = document.querySelector('#theme-options'); if (!loginButton || !profileLink || !labelsLink || !adminLink || !session || !username || !menu || !menuToggle || !logoutButton) return; @@ -22,6 +26,16 @@ menu.classList.toggle('hidden', isOpen); menuToggle.setAttribute('aria-expanded', String(!isOpen)); }); + + // Handle theme submenu toggle + if (themeSubmenuTitle && themeOptions) { + themeSubmenuTitle.addEventListener('click', (e) => { + e.preventDefault(); + const isOpen = !themeOptions.classList.contains('hidden'); + themeOptions.classList.toggle('hidden', isOpen); + themeSubmenuTitle.setAttribute('aria-expanded', String(!isOpen)); + }); + } function showSignedOut() { loginButton.classList.remove('hidden'); diff --git a/frontend/static/style.css b/frontend/static/style.css index 19d9481..a501435 100644 --- a/frontend/static/style.css +++ b/frontend/static/style.css @@ -223,17 +223,6 @@ body::selection { position: relative; } -.theme-picker { - width: auto; - min-width: 132px; - padding: 8px 10px; - border: 1px solid var(--surface-2); - border-radius: 7px; - background: var(--surface-0); - color: var(--text); - font: inherit; -} - .menu-toggle { min-width: 0; padding: 10px 13px; @@ -339,6 +328,86 @@ body::selection { color: var(--red); } +.theme-submenu-container { + border-top: 1px solid var(--border); + margin-top: 6px; + padding-top: 6px; +} + +.theme-submenu-container.hidden { + display: none; +} + +.submenu-title { + display: block; + width: 100%; + min-width: 0; + padding: 9px 10px; + border: 0; + border-radius: 6px; + background: transparent; + color: var(--text); + text-align: left; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; +} + +.submenu-title:hover { + background: var(--surface-1); + color: var(--lavender); +} + +.submenu-title::after { + content: ' ▼'; + font-size: 0.7em; + opacity: 0.7; +} + +.submenu-title[aria-expanded='true']::after { + transform: rotate(-180deg); + display: inline-block; +} + +.submenu-options { + display: flex; + flex-direction: column; + gap: 4px; + padding: 4px 8px; + margin-top: 4px; + border-radius: 6px; + background: var(--surface-1); +} + +.submenu-options.hidden { + display: none; +} + +.theme-option { + padding: 8px 10px; + border: 1px solid var(--border); + border-radius: 5px; + background: transparent; + color: var(--text); + text-align: left; + cursor: pointer; + transition: all 0.2s ease; + font-size: 0.9rem; +} + +.theme-option:hover { + background: var(--surface-0); + border-color: var(--lavender); + color: var(--lavender); +} + +.theme-option.active { + background: var(--mauve); + border-color: var(--mauve); + color: var(--crust); + font-weight: 600; +} + main.container { position: relative; z-index: 1; diff --git a/frontend/static/theme.js b/frontend/static/theme.js index d5bc5bd..7249384 100644 --- a/frontend/static/theme.js +++ b/frontend/static/theme.js @@ -11,18 +11,39 @@ async function loadAvailableThemes() { ? localStorage.getItem(themePreference) : themes[0]?.id; if (selected) document.documentElement.dataset.theme = selected; - const headerActions = document.querySelector('.header-actions'); - if (!headerActions || !themes.length) return; - const picker = document.createElement('select'); - picker.className = 'theme-picker'; - picker.setAttribute('aria-label', 'Theme'); - picker.replaceChildren(...themes.map((theme) => new Option(theme.label, theme.id))); - picker.value = selected || themes[0].id; - picker.addEventListener('change', () => { - localStorage.setItem(themePreference, picker.value); - document.documentElement.dataset.theme = picker.value; + + const submenuContainer = document.querySelector('#theme-submenu-container'); + const themeOptions = document.querySelector('#theme-options'); + const submenuTitle = document.querySelector('.submenu-title'); + + if (!submenuContainer || !themeOptions || !themes.length) return; + + // Show the submenu container + submenuContainer.classList.remove('hidden'); + + // Create theme buttons + const buttons = themes.map((theme) => { + const button = document.createElement('button'); + button.type = 'button'; + button.className = 'theme-option'; + button.dataset.themeId = theme.id; + button.textContent = theme.label; + if (theme.id === selected) { + button.classList.add('active'); + } + button.addEventListener('click', () => { + localStorage.setItem(themePreference, theme.id); + document.documentElement.dataset.theme = theme.id; + // Update active state + document.querySelectorAll('.theme-option').forEach((btn) => { + btn.classList.remove('active'); + }); + button.classList.add('active'); + }); + return button; }); - headerActions.prepend(picker); + + themeOptions.replaceChildren(...buttons); } loadAvailableThemes(); \ No newline at end of file diff --git a/frontend/templates/about.html b/frontend/templates/about.html index 8afdcaf..aca169e 100644 --- a/frontend/templates/about.html +++ b/frontend/templates/about.html @@ -29,6 +29,10 @@ + diff --git a/frontend/templates/admin.html b/frontend/templates/admin.html index b41429d..32232cd 100644 --- a/frontend/templates/admin.html +++ b/frontend/templates/admin.html @@ -31,6 +31,10 @@ + diff --git a/frontend/templates/feed.html b/frontend/templates/feed.html index f82b6ba..0fe2722 100644 --- a/frontend/templates/feed.html +++ b/frontend/templates/feed.html @@ -31,6 +31,10 @@ +
diff --git a/frontend/templates/labels.html b/frontend/templates/labels.html index 81efa43..e897f73 100644 --- a/frontend/templates/labels.html +++ b/frontend/templates/labels.html @@ -29,6 +29,10 @@ + diff --git a/frontend/templates/login.html b/frontend/templates/login.html index 23b94ce..a6597be 100644 --- a/frontend/templates/login.html +++ b/frontend/templates/login.html @@ -30,6 +30,10 @@ + diff --git a/frontend/templates/new-entry.html b/frontend/templates/new-entry.html index cee675c..d61cbeb 100644 --- a/frontend/templates/new-entry.html +++ b/frontend/templates/new-entry.html @@ -31,6 +31,10 @@ + diff --git a/frontend/templates/user_profile.html b/frontend/templates/user_profile.html index a284f7d..cace3de 100644 --- a/frontend/templates/user_profile.html +++ b/frontend/templates/user_profile.html @@ -32,6 +32,10 @@ + diff --git a/frontend/version.json b/frontend/version.json index 6793ca7..cf0d650 100644 --- a/frontend/version.json +++ b/frontend/version.json @@ -1,3 +1,3 @@ { - "version": "0.1.0" + "version": "0.1.1" } \ No newline at end of file