Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-172Done

3.2.8 Board column polish — auto scroll-to-load (drop the button + loaded-count); uniform column height

Estimate: 16m · Depends on: 3.2.5, 3.2.6

A board-column UX refinement (user-requested, 2026-06-07). Two changes to the shipped BoardColumn (3.2.3 + 3.2.5 scale + 3.2.6 completeness), both within the EXISTING scale vocabulary — no new component, no new behaviour the design did not already contemplate, so this folds the design-asset update into the one subtask rather than a separate design pass (justified deviation from design-before-code: the owner specified the exact intent and scroll-to-load is already documented in design/boards/design-notes.md).

1. Pure auto scroll-to-load — drop the explicit "Load more" button AND the "{n} loaded · rows virtualized" note. 3.2.5 shipped BOTH an IntersectionObserver scroll-sentinel (auto-load on scroll-to-bottom) AND a redundant .col-foot "Load more" button + a virtNote showing how many cards are loaded. Keep ONLY the scroll-to-load: remove the button and the loaded-count note. When a scroll-triggered page is in flight, show a small bottom Spinner (the loadingMore state) so there is still feedback; on a failed page keep a minimal inline error + retry affordance (a drop of the whole button is fine, but a scroll-load that errors must still be recoverable without a reload — a small "Couldn’t load — retry" link, NOT the big button). The per-column total-count badge in the header STAYS — that is the column’s issue count (the Jira-standard denominator), distinct from the removed "how many loaded" note. a11y: loading more must remain reachable without a mouse — the column body is focusable/scrollable so keyboard scroll still trips the sentinel; verify a keyboard user can reach later pages (if the sentinel alone can’t guarantee it, keep a visually-minimal but focusable load affordance rather than a pointer-only one).

2. Uniform column height — every column the same height, even with one card. Today the column <section> uses max-h-[calc(100dvh-12rem)], so a column with one card shrinks to its content and columns are ragged. Switch to a CONSISTENT height (h-[calc(100dvh-12rem)] — a viewport-relative LAYOUT height, not a shaped-control size, so a raw calc is correct, not a --height-* token) so all columns are the same height; the card body (flex-1, internal scroll) fills it and a sparse column shows empty space below its cards. The empty-column placeholder (3.2.6) sits inside the same full-height column. Keep it usable on mobile (the 3.2.6 pager / short viewports) — the height stays viewport-relative.

Design asset + i18n upkeep. Update design/boards/board.mock.html (the scale panel + the states panel’s column) and the design-notes.md scale section to match: scroll-to-load only (no button, no loaded-count note), uniform column height. Remove the now-unused boards i18n keys (loadMore, virtNote) from messages/en.json + zh.json (keep loadingMore / loadMoreError / loadMoreRetry for the in-flight spinner + the inline error-retry); catalog parity (tests/i18n-catalog.test.ts) must stay green.

Out of scope: the virtualization/windowing itself (3.2.5 — kept, just no visible note), the load paging contract (unchanged — still the 3.1.6 cursor route appended in place), and WIP/swimlanes (3.3).

Acceptance criteria

  • The .col-foot "Load more" button and the "{n} loaded · rows virtualized" note are gone; a column pages in the next slice purely on scroll-to-bottom (the IntersectionObserver sentinel), with a bottom Spinner while a page is in flight.
  • A scroll-load that fails still shows a minimal, focusable retry affordance (no full reload needed); loading more is reachable by keyboard, not pointer-only.
  • The per-column header total-count badge is unchanged (it is the column issue count, not the removed loaded-count).
  • Every board column renders at the same height regardless of card count (one-card and full columns line up); the card body scrolls internally and a sparse column shows empty space; the empty-column + empty-board states still render correctly; mobile/pager layout (3.2.6) still works.
  • design/boards/board.mock.html + design-notes.md updated to the new scale affordance + uniform height (render-checklist clean); unused i18n keys removed with en/zh parity green; colours via --el-*, shape via element tokens.
  • Component tests updated: the column auto-loads on sentinel intersection (no button), renders the in-flight spinner + the error-retry, and the uniform-height/empty branches; no test asserts the removed button/note.

Context refs

  • app/(authed)/boards/_components/BoardColumn.tsx — the .col-foot button + virtNote to remove, the sentinel to keep, the max-h-[calc(100dvh-12rem)]h-… change; boardPaging.ts / useRowWindow (3.2.5) — unchanged
  • app/(authed)/boards/_components/BoardContainer.tsx — the loadMore/paging wiring (unchanged contract)
  • design/boards/board.mock.html (scale + states panels) + design/boards/design-notes.md (scale section) — the asset to update
  • messages/en.json + zh.json boards.* (loadMore/virtNote to remove); tests/i18n-catalog.test.ts — parity gate
  • tests/components/board-column.test.tsx / board-completeness.test.tsx — the component tests to update; motir-core/CLAUDE.md--el-* + element-shape rules