diff options
| author | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-06-08 15:14:20 -0700 |
|---|---|---|
| committer | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-06-08 15:14:20 -0700 |
| commit | 9d46475d4ef94abebf844d2442085a50a57e5e34 (patch) | |
| tree | 97028b1d0862b5088f0c265d3bb80352f9c7edef /static | |
| parent | 629ee5d4e1ca637b6c654b220d9458c36e04ceb5 (diff) | |
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.js | 55 | ||||
| -rw-r--r-- | static/styles.css | 115 |
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 { |
