summaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
authorTyler Hoang <tyler@tylerhoang.xyz>2026-06-08 15:14:20 -0700
committerTyler Hoang <tyler@tylerhoang.xyz>2026-06-08 15:14:20 -0700
commit9d46475d4ef94abebf844d2442085a50a57e5e34 (patch)
tree97028b1d0862b5088f0c265d3bb80352f9c7edef /static
parent629ee5d4e1ca637b6c654b220d9458c36e04ceb5 (diff)
Replace sticky search bar with icon-toggle toolbar on mobileHEADmaster
On mobile, the sticky feed toolbar consumed most of the viewport. Replaced it with a compact icon bar (search + sort) that expands into mutually exclusive panels. Sort options render as radio-style buttons generated dynamically from the existing select, which remains for desktop unchanged.
Diffstat (limited to 'static')
-rw-r--r--static/app.js55
-rw-r--r--static/styles.css115
2 files changed, 167 insertions, 3 deletions
diff --git a/static/app.js b/static/app.js
index 7a60c52..b38c586 100644
--- a/static/app.js
+++ b/static/app.js
@@ -497,6 +497,61 @@ document.querySelectorAll(".star-control[data-form-stars]").forEach((control) =>
sortSelect.addEventListener("change", () => {
currentSort = sortSelect.value;
resetFeed();
+ syncSortRadios(sortSelect.value);
});
}
+
+ const sortOptions = document.querySelector("#sort-options");
+ if (sortOptions && sortSelect) {
+ Array.from(sortSelect.options).forEach((opt) => {
+ const btn = document.createElement("button");
+ btn.type = "button";
+ btn.className = "sort-option" + (opt.value === "" ? " is-active" : "");
+ btn.dataset.value = opt.value;
+ btn.textContent = opt.textContent;
+ btn.addEventListener("click", () => {
+ sortSelect.value = opt.value;
+ currentSort = opt.value;
+ resetFeed();
+ syncSortRadios(opt.value);
+ closePanels();
+ });
+ sortOptions.appendChild(btn);
+ });
+ }
+
+ function syncSortRadios(value) {
+ if (!sortOptions) return;
+ sortOptions.querySelectorAll(".sort-option").forEach((btn) => {
+ btn.classList.toggle("is-active", btn.dataset.value === value);
+ });
+ }
+
+ const toggles = document.querySelectorAll(".toolbar-toggle");
+ const panels = document.querySelectorAll(".toolbar-panel");
+
+ function closePanels() {
+ panels.forEach((p) => p.classList.remove("is-open"));
+ toggles.forEach((t) => t.classList.remove("is-active"));
+ }
+
+ toggles.forEach((toggle) => {
+ toggle.addEventListener("click", () => {
+ const panelName = toggle.dataset.panel;
+ const panel = document.querySelector(
+ `.toolbar-panel-${panelName}`
+ );
+ const isOpen = toggle.classList.contains("is-active");
+
+ closePanels();
+
+ if (!isOpen && panel) {
+ panel.classList.add("is-open");
+ toggle.classList.add("is-active");
+ if (panelName === "search" && searchInput) {
+ searchInput.focus();
+ }
+ }
+ });
+ });
})();
diff --git a/static/styles.css b/static/styles.css
index 3b3cf0d..172abb0 100644
--- a/static/styles.css
+++ b/static/styles.css
@@ -1904,14 +1904,28 @@ textarea:focus {
gap: 10px;
}
-.search-row input {
+.toolbar-toggles {
+ display: none;
+}
+
+.feed-toolbar {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.toolbar-panel-search {
flex: 1 1 360px;
}
-.search-row select {
+.toolbar-panel-sort {
flex: 0 0 260px;
}
+.sort-options {
+ display: none;
+}
+
.diary-feed {
gap: 24px;
}
@@ -2404,9 +2418,104 @@ textarea:focus {
}
.feed-toolbar {
- top: 10px;
+ position: static;
margin-bottom: 20px;
+ padding: 0;
+ border-radius: 8px;
+ overflow: hidden;
+ }
+
+ .toolbar-toggles {
+ display: flex;
+ border-bottom: 1px solid var(--line);
+ }
+
+ .toolbar-toggle {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 6px;
padding: 12px;
+ border: none;
+ border-radius: 0;
+ background: transparent;
+ color: var(--muted);
+ font-size: 0.8rem;
+ font-weight: 600;
+ letter-spacing: 0.03em;
+ text-transform: uppercase;
+ cursor: pointer;
+ transition: color 0.15s, background 0.15s;
+ }
+
+ .toolbar-toggle + .toolbar-toggle {
+ border-left: 1px solid var(--line);
+ }
+
+ .toolbar-toggle.is-active {
+ color: var(--accent-strong);
+ background: rgba(194, 170, 122, 0.08);
+ }
+
+ .toolbar-panel {
+ display: none;
+ padding: 12px;
+ }
+
+ .toolbar-panel.is-open {
+ display: block;
+ }
+
+ .sort-options {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ margin-bottom: 10px;
+ }
+
+ .sort-option {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 10px 12px;
+ border: none;
+ border-radius: 4px;
+ background: transparent;
+ color: var(--muted);
+ font-family: var(--font-sans);
+ font-size: 0.88rem;
+ cursor: pointer;
+ text-align: left;
+ transition: color 0.15s, background 0.15s;
+ }
+
+ .sort-option:hover {
+ background: rgba(194, 170, 122, 0.06);
+ }
+
+ .sort-option.is-active {
+ color: var(--accent-strong);
+ background: rgba(194, 170, 122, 0.1);
+ }
+
+ .sort-option::before {
+ content: "";
+ width: 14px;
+ height: 14px;
+ border: 2px solid var(--faint);
+ border-radius: 50%;
+ flex-shrink: 0;
+ transition: border-color 0.15s, box-shadow 0.15s;
+ }
+
+ .sort-option.is-active::before {
+ border-color: var(--accent);
+ box-shadow: inset 0 0 0 3px var(--accent);
+ }
+
+ .toolbar-panel-sort .search-row {
+ display: none;
}
.month-rail {