From 5ca3f503eef86c0ea624eb0824ecc189854ff744 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Sun, 8 Mar 2026 17:32:27 -0500 Subject: [PATCH] Pond Updates --- .../components/tools/device_settings.css | 38 +++++++++++- .../components/tools/device_settings.js | 61 ++++++++++++++----- .../tools/device_settings_layout.json | 46 +++++++++++++- frogpilot/system/the_pond/the_pond.py | 20 +++++- system/manager/process_config.py | 7 ++- 5 files changed, 150 insertions(+), 22 deletions(-) diff --git a/frogpilot/system/the_pond/assets/components/tools/device_settings.css b/frogpilot/system/the_pond/assets/components/tools/device_settings.css index be8226326..10660b7ad 100644 --- a/frogpilot/system/the_pond/assets/components/tools/device_settings.css +++ b/frogpilot/system/the_pond/assets/components/tools/device_settings.css @@ -43,6 +43,13 @@ } /* ――― Search / Filter ――― */ +.ds-search-row { + align-items: center; + display: flex; + gap: 0.5rem; + margin-bottom: var(--margin-lg); +} + .ds-search { background-color: var(--input-bg); border: var(--border-style-input); @@ -51,17 +58,37 @@ color: var(--text-color); font-family: var(--font-body); font-size: var(--font-size-base); - margin-bottom: var(--margin-lg); + margin-bottom: 0; outline: none; padding: var(--padding-sm) var(--padding-base); transition: box-shadow var(--transition-fast); width: 100%; + flex: 1; } .ds-search:focus { box-shadow: 0 0 0 2px var(--main-fg); } +.ds-search-clear { + background: var(--input-bg); + border: var(--border-style-main); + border-radius: var(--border-radius-base); + color: var(--text-color); + cursor: pointer; + font-family: var(--font-body); + font-size: var(--font-size-sm); + min-width: 4.75rem; + padding: 0.6rem 0.8rem; + transition: background-color var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast); +} + +.ds-search-clear:hover { + background: var(--main-fg); + border-color: var(--main-fg); + color: var(--color-black); +} + /* ――― Section Cards ――― */ .ds-section { background-color: var(--secondary-bg); @@ -397,6 +424,15 @@ padding: var(--padding-sm) var(--padding-base) var(--padding-xl); } + .ds-search-row { + align-items: stretch; + flex-direction: column; + } + + .ds-search-clear { + width: 100%; + } + .ds-tabs { flex-wrap: nowrap; overflow-x: auto; diff --git a/frogpilot/system/the_pond/assets/components/tools/device_settings.js b/frogpilot/system/the_pond/assets/components/tools/device_settings.js index 34f023b69..802ab15f5 100644 --- a/frogpilot/system/the_pond/assets/components/tools/device_settings.js +++ b/frogpilot/system/the_pond/assets/components/tools/device_settings.js @@ -1,5 +1,4 @@ import { html, reactive } from "https://esm.sh/@arrow-js/core" -import { Navigate } from "/assets/components/router.js" const endpointOptionsCache = {} const endpointOptionsInflight = {} @@ -501,6 +500,29 @@ function matchesFilter(p) { return p.label.toLowerCase().includes(q) || p.key.toLowerCase().includes(q) } +function clearSearchFilter() { + if (!state.filter) return + state.filter = "" + scheduleSyncInputs() +} + +function handleSectionTabClick(sectionSlug, event) { + if (!sectionSlug || sectionSlug === state.activeSectionSlug) return + + // Preserve horizontal tab strip position on mobile when switching sections. + const tabsEl = event?.currentTarget?.closest(".ds-tabs") + const preservedScrollLeft = tabsEl ? tabsEl.scrollLeft : null + + state.activeSectionSlug = sectionSlug + + if (preservedScrollLeft !== null) { + requestAnimationFrame(() => { + const nextTabsEl = document.getElementById("ds-tabs") + if (nextTabsEl) nextTabsEl.scrollLeft = preservedScrollLeft + }) + } +} + function renderSettingRow(p) { if (p.parent_key && !state.filter) { if (!state.values[p.parent_key]) return "" @@ -619,14 +641,27 @@ export function DeviceSettings({ params }) {

Toggles

- +
+ + ${() => state.filter ? html` + + ` : ""} +
${() => { if (state.loadingLayout || state.loadingValues) { @@ -678,14 +713,12 @@ export function DeviceSettings({ params }) { const visibleParams = activeSection.params.filter(p => matchesFilter(p)) return html` -
+
${sections.map(section => html`