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. */} {menuOpen && ( <> @@ -82,7 +82,7 @@ export default function Header() { setMenuOpen(false); item.run(); }} - className="block w-full px-3 py-1.5 text-left text-sm text-ink-soft hover:bg-line" + className="flex min-h-11 w-full items-center px-3 py-1.5 text-left text-sm text-ink-soft hover:bg-line sm:min-h-0" > New {item.label.toLowerCase()} @@ -98,7 +98,7 @@ export default function Header() { @@ -116,14 +116,14 @@ export default function Header() { setAcctOpen(false)} - className="block w-full px-3 py-1.5 text-left text-sm text-ink-soft hover:bg-line" + className="flex min-h-11 w-full items-center px-3 py-1.5 text-left text-sm text-ink-soft hover:bg-line sm:min-h-0" > Admin )} From 3d7406c0aab7c2e77c5c0f004ad1544bab9001d5 Mon Sep 17 00:00:00 2001 From: bkennedy Date: Sat, 4 Jul 2026 15:30:28 +0000 Subject: [PATCH 3/4] fix(issue): PROG-81 give issue field-edit links a 44px touch row on mobile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Move… / Change… / Edit… / Copy-as-prompt / Copy-CLI links in the issue aside rendered ~19px tall. They carry keyboard shortcuts (M/A/T/W) on desktop, but on a phone tapping the link is the ONLY way to fire them — so a 19px target is a real miss. Factor the shared styling into FIELD_ACTION_CLS: a >=44px flex row on mobile (flex is block-level, so each link keeps its own line as block did), reverting to the compact block layout at sm+. Add ml-1 to the (M)/(A)/(T)/(W) shortcut hints so the flex row keeps the space. --- src/client/pages/IssuePage.tsx | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/client/pages/IssuePage.tsx b/src/client/pages/IssuePage.tsx index c738f5e..4b88dbe 100644 --- a/src/client/pages/IssuePage.tsx +++ b/src/client/pages/IssuePage.tsx @@ -38,6 +38,14 @@ import { toastAction } from "../toast"; const fmtTime = (iso: string) => new Date(iso).toLocaleString(undefined, { dateStyle: "medium", timeStyle: "short" }); +// The field-edit triggers in the aside (Move… / Change… / Edit… / Copy…). They +// carry keyboard shortcuts on desktop, but on a phone tapping the link is the +// ONLY way to fire them — so give each a 44px-tall touch row on mobile while +// keeping the compact one-line-each layout on desktop (PROG-81). `flex` is +// block-level, so each still sits on its own line as `block` did. +const FIELD_ACTION_CLS = + "flex min-h-11 items-center text-xs text-adobe hover:underline sm:block sm:min-h-0"; + export default function IssuePage({ workspace, keyParam, @@ -196,9 +204,9 @@ export default function IssuePage({

@@ -211,9 +219,9 @@ export default function IssuePage({ )} @@ -234,21 +242,21 @@ export default function IssuePage({ )} From 544f7ff6ece849208b30a021e747de806e5896ca Mon Sep 17 00:00:00 2001 From: bkennedy Date: Sat, 4 Jul 2026 15:30:35 +0000 Subject: [PATCH 4/4] docs: PROG-81 record the mobile audit findings and decisions Append the PROG-81 decision entry summarizing the rendered phone audit: the three fixes made (board filter collapse, header targets, issue field links) and the two low-severity items deliberately deferred (tablet-range select font-size, tab-bar translucency bleed). --- docs/DECISIONS.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index 30a33cf..fea0863 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -1309,3 +1309,34 @@ after each step and stuttering the auto-scroll toward the target column; on drop untouched** — `flex-1` fits every column there, so the row never overflows and snap is inert. Verified in WebKit at 390 px: a partial nudge settled exactly on a column edge (0 px delta), zero page overflow. + +### PROG-81 — mobile audit: filters collapse + 44px touch targets + +An audit of the rendered phone experience (WebKit at 360/390/430/768, touch +emulation, per the `mobile-first-audit` skill) found the app broadly solid — +correct `viewport-fit=cover` meta, zoom enabled, 19 px body, `pb-24` clearing +the bottom tab bar, no page-level horizontal overflow — but three things worth +fixing: + +1. **Board filters buried the board.** The six filter dropdowns + New-issue + + two toggles filled the entire first viewport; the cards (the point of the + page) only appeared after scrolling past all of it. Fixed by collapsing the + filter row behind a **"Filters"** disclosure on phones (`< sm`), collapsed by + default with an active-count badge; at `sm`+ the row stays inline and desktop + is byte-identical. *Hard call:* a phone user now taps once to filter, but + gets three cards above the fold instead of zero — mobile is primary, so the + board wins the default view. +2. **Sub-44 px touch targets.** The header New button (~34), avatar (32) and its + dropdown rows (~31), the board's New-issue and Show-backlog/sub-issues + buttons (~31), and the issue page's field-edit links — Move…/Change…/Edit…/ + Copy… — at ~19 px (on a phone the *only* way to fire those, since the + keyboard shortcuts don't exist there). All bumped to a **≥44 px** row on + mobile via `min-h-11` (and a `flex` row for the issue links so they keep + their own line), reverting to the compact sizing at `sm`+. + +*Deliberately deferred* (noted, not fixed, to keep the PR focused): tablet-range +(640–767 px) filter `