theme selecter moved
This commit is contained in:
@@ -3,4 +3,7 @@
|
|||||||
## Version v0.1.1
|
## Version v0.1.1
|
||||||
### Features
|
### Features
|
||||||
* Ability to add new logs through the web interface
|
* 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
|
## Version v0.1.0 Initial release
|
||||||
|
|||||||
@@ -1250,3 +1250,9 @@ Put the new entry button left of the hamburger menu
|
|||||||
|
|
||||||
### Assistant outcome
|
### 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.
|
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.
|
||||||
|
|||||||
@@ -220,6 +220,7 @@
|
|||||||
210. After an entry is saved move to the /<user>/ page
|
210. After an entry is saved move to the /<user>/ page
|
||||||
211. Don't put new entry in the hamburger menu but present it as a seperate button next to the style selector
|
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
|
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
|
## Future entries
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,10 @@
|
|||||||
const menuToggle = document.querySelector('.menu-toggle');
|
const menuToggle = document.querySelector('.menu-toggle');
|
||||||
const logoutButton = document.querySelector('#logout-button');
|
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;
|
if (!loginButton || !profileLink || !labelsLink || !adminLink || !session || !username || !menu || !menuToggle || !logoutButton) return;
|
||||||
|
|
||||||
menuToggle.addEventListener('click', () => {
|
menuToggle.addEventListener('click', () => {
|
||||||
@@ -23,6 +27,16 @@
|
|||||||
menuToggle.setAttribute('aria-expanded', String(!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() {
|
function showSignedOut() {
|
||||||
loginButton.classList.remove('hidden');
|
loginButton.classList.remove('hidden');
|
||||||
if (newEntryButton) newEntryButton.classList.add('hidden');
|
if (newEntryButton) newEntryButton.classList.add('hidden');
|
||||||
|
|||||||
+80
-11
@@ -223,17 +223,6 @@ body::selection {
|
|||||||
position: relative;
|
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 {
|
.menu-toggle {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 10px 13px;
|
padding: 10px 13px;
|
||||||
@@ -339,6 +328,86 @@ body::selection {
|
|||||||
color: var(--red);
|
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 {
|
main.container {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|||||||
+32
-11
@@ -11,18 +11,39 @@ async function loadAvailableThemes() {
|
|||||||
? localStorage.getItem(themePreference)
|
? localStorage.getItem(themePreference)
|
||||||
: themes[0]?.id;
|
: themes[0]?.id;
|
||||||
if (selected) document.documentElement.dataset.theme = selected;
|
if (selected) document.documentElement.dataset.theme = selected;
|
||||||
const headerActions = document.querySelector('.header-actions');
|
|
||||||
if (!headerActions || !themes.length) return;
|
const submenuContainer = document.querySelector('#theme-submenu-container');
|
||||||
const picker = document.createElement('select');
|
const themeOptions = document.querySelector('#theme-options');
|
||||||
picker.className = 'theme-picker';
|
const submenuTitle = document.querySelector('.submenu-title');
|
||||||
picker.setAttribute('aria-label', 'Theme');
|
|
||||||
picker.replaceChildren(...themes.map((theme) => new Option(theme.label, theme.id)));
|
if (!submenuContainer || !themeOptions || !themes.length) return;
|
||||||
picker.value = selected || themes[0].id;
|
|
||||||
picker.addEventListener('change', () => {
|
// Show the submenu container
|
||||||
localStorage.setItem(themePreference, picker.value);
|
submenuContainer.classList.remove('hidden');
|
||||||
document.documentElement.dataset.theme = picker.value;
|
|
||||||
|
// 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();
|
loadAvailableThemes();
|
||||||
@@ -29,6 +29,10 @@
|
|||||||
<a id="auth-admin-link" class="hidden" href="/admin">Admin</a>
|
<a id="auth-admin-link" class="hidden" href="/admin">Admin</a>
|
||||||
<div id="auth-session" class="auth-session hidden"><a id="auth-username" class="user-name" href="/"></a></div>
|
<div id="auth-session" class="auth-session hidden"><a id="auth-username" class="user-name" href="/"></a></div>
|
||||||
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
||||||
|
<div id="theme-submenu-container" class="theme-submenu-container hidden">
|
||||||
|
<button type="button" class="submenu-title" aria-expanded="false" aria-controls="theme-options">Themes</button>
|
||||||
|
<div id="theme-options" class="submenu-options hidden"></div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -31,6 +31,10 @@
|
|||||||
<a id="auth-username" class="user-name" href="/"></a>
|
<a id="auth-username" class="user-name" href="/"></a>
|
||||||
</div>
|
</div>
|
||||||
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
||||||
|
<div id="theme-submenu-container" class="theme-submenu-container hidden">
|
||||||
|
<button type="button" class="submenu-title" aria-expanded="false" aria-controls="theme-options">Themes</button>
|
||||||
|
<div id="theme-options" class="submenu-options hidden"></div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -31,6 +31,10 @@
|
|||||||
<a id="auth-username" class="user-name" href="/"></a>
|
<a id="auth-username" class="user-name" href="/"></a>
|
||||||
</div>
|
</div>
|
||||||
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
||||||
|
<div id="theme-submenu-container" class="theme-submenu-container hidden">
|
||||||
|
<button type="button" class="submenu-title" aria-expanded="false" aria-controls="theme-options">Themes</button>
|
||||||
|
<div id="theme-options" class="submenu-options hidden"></div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
<section class="toolbar">
|
<section class="toolbar">
|
||||||
|
|||||||
@@ -29,6 +29,10 @@
|
|||||||
<a id="auth-admin-link" class="hidden" href="/admin">Admin</a>
|
<a id="auth-admin-link" class="hidden" href="/admin">Admin</a>
|
||||||
<div id="auth-session" class="auth-session hidden"><a id="auth-username" class="user-name" href="/"></a></div>
|
<div id="auth-session" class="auth-session hidden"><a id="auth-username" class="user-name" href="/"></a></div>
|
||||||
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
||||||
|
<div id="theme-submenu-container" class="theme-submenu-container hidden">
|
||||||
|
<button type="button" class="submenu-title" aria-expanded="false" aria-controls="theme-options">Themes</button>
|
||||||
|
<div id="theme-options" class="submenu-options hidden"></div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -30,6 +30,10 @@
|
|||||||
<a id="auth-username" class="user-name" href="/"></a>
|
<a id="auth-username" class="user-name" href="/"></a>
|
||||||
</div>
|
</div>
|
||||||
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
||||||
|
<div id="theme-submenu-container" class="theme-submenu-container hidden">
|
||||||
|
<button type="button" class="submenu-title" aria-expanded="false" aria-controls="theme-options">Themes</button>
|
||||||
|
<div id="theme-options" class="submenu-options hidden"></div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -31,6 +31,10 @@
|
|||||||
<a id="auth-username" class="user-name" href="/"></a>
|
<a id="auth-username" class="user-name" href="/"></a>
|
||||||
</div>
|
</div>
|
||||||
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
||||||
|
<div id="theme-submenu-container" class="theme-submenu-container hidden">
|
||||||
|
<button type="button" class="submenu-title" aria-expanded="false" aria-controls="theme-options">Themes</button>
|
||||||
|
<div id="theme-options" class="submenu-options hidden"></div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
<a id="auth-username" class="user-name" href="/"></a>
|
<a id="auth-username" class="user-name" href="/"></a>
|
||||||
</div>
|
</div>
|
||||||
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
<button id="logout-button" class="logout-button hidden" type="button">Sign out</button>
|
||||||
|
<div id="theme-submenu-container" class="theme-submenu-container hidden">
|
||||||
|
<button type="button" class="submenu-title" aria-expanded="false" aria-controls="theme-options">Themes</button>
|
||||||
|
<div id="theme-options" class="submenu-options hidden"></div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"version": "0.1.0"
|
"version": "0.1.1"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user