From 8328e75f11b385195090aaeacfe9d5d53cef87eb Mon Sep 17 00:00:00 2001
From: bkennedy
Date: Sat, 4 Jul 2026 15:30:11 +0000
Subject: [PATCH 1/4] feat(board): PROG-81 collapse board filters behind a
disclosure on mobile
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
A rendered phone audit (WebKit @360/390/430, touch emulation) found the
board's six filter dropdowns + New-issue button + two toggles filled the
entire first viewport, pushing the cards — the point of the page — below
the fold. On a 844px phone you saw zero board content before scrolling.
On phones (< sm) the filter row now collapses behind a "Filters" disclosure,
collapsed by default with a badge counting active filters/toggles, so three
cards sit above the fold. At sm+ the row stays inline and desktop is
byte-identical (verified: toggle hidden, six selects inline at 1440px).
Also bump the board's own New-issue and Show-backlog/Show-sub-issues buttons
to a >=44px row on mobile (min-h-11, reverting at sm) — they were ~31px,
under the touch floor.
---
docs/REFERENCE.md | 6 +++++-
src/client/pages/Home.tsx | 41 ++++++++++++++++++++++++++++++++++-----
2 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/docs/REFERENCE.md b/docs/REFERENCE.md
index 68a0a49..38b4f2e 100644
--- a/docs/REFERENCE.md
+++ b/docs/REFERENCE.md
@@ -450,7 +450,11 @@ canonical key — entirely client-side from the loaded workspace (D22).
Agenda filters sort the same way. The current filter selection is also
mirrored to `localStorage` (`progress:board-filters`) and re-applied when the
board is reopened with a bare URL, so a choice sticks across navigation;
- "Clear filters" clears the memory too (PROG-58). Drag-and-drop reorders cards
+ "Clear filters" clears the memory too (PROG-58). On phones (`< sm`) the whole
+ filter row collapses behind a **"Filters"** disclosure — collapsed by default,
+ with a badge counting the active filters/toggles — so the board itself sits
+ above the fold instead of a screenful of dropdowns; at `sm` and up the row is
+ always inline (PROG-81). Drag-and-drop reorders cards
vertically
within a column (a manual work order) and moves them between columns to set
status; both persist as one optimistic write via the card's `rank` (D44).
diff --git a/src/client/pages/Home.tsx b/src/client/pages/Home.tsx
index 55e3ea2..34c012f 100644
--- a/src/client/pages/Home.tsx
+++ b/src/client/pages/Home.tsx
@@ -203,6 +203,10 @@ export default function Home({ workspace }: { workspace: WorkspacePayload }) {
const [columns, setColumns] = useState(sourceColumns);
const [activeId, setActiveId] = useState(null);
+ // Mobile only: the filter dropdowns collapse behind a "Filters" disclosure so
+ // the board itself sits above the fold instead of a screenful of chrome
+ // (PROG-81). Desktop ignores this — the block is always `sm:flex`.
+ const [filtersOpen, setFiltersOpen] = useState(false);
// Mirror of activeId for effects/handlers that must read it without depending
// on it (a ref updates synchronously and doesn't re-trigger effects).
const activeIdRef = useRef(null);
@@ -367,6 +371,12 @@ export default function Home({ workspace }: { workspace: WorkspacePayload }) {
);
const shownCount = visibleColumns.reduce((n, s) => n + columns[s].length, 0);
const filtersActive = FILTER_KEYS.some((k) => filters[k]);
+ // Badge on the mobile "Filters" toggle: how many filters/toggles are narrowing
+ // the board right now, so a collapsed panel still signals it's doing something.
+ const activeFilterCount =
+ FILTER_KEYS.filter((k) => filters[k]).length +
+ (filters.backlog ? 1 : 0) +
+ (filters.subissues ? 1 : 0);
return (
<>
@@ -379,13 +389,34 @@ export default function Home({ workspace }: { workspace: WorkspacePayload }) {
-
+ {/* Mobile: a "Filters" disclosure keeps the six dropdowns + two toggles
+ out of the default view so the board is above the fold (PROG-81). The
+ badge shows how many are active while collapsed. Hidden at sm+, where
+ the filter row is always inline. */}
+
+
+
{/* Archived containers stay out of the dropdowns (D26); their issues
still render, so nothing silently disappears from the board. */}