feat(ui): mobile card view for issues list (PinPoint-5g0)#1060
feat(ui): mobile card view for issues list (PinPoint-5g0)#1060timothyfroehlich wants to merge 5 commits intomainfrom
Conversation
Adds a responsive card-based layout for the issues list page on mobile (< md breakpoint). Desktop table remains unchanged and is now wrapped in hidden md:block. The mobile layout renders in md:hidden. New components: - MobileIssueCard: tappable card with ID chip, machine name, age, title (line-clamp-2), status badge, severity dot + label, assignee avatar. Unplayable (urgent) issues get red-tinted border + background. - MobileIssueFilterBar: search input with clear button, filter icon, horizontally scrollable chip row (Sort, Status, Machine, Assigned). Chips show active state when filters are applied. - MobileIssueList: composes header with total count badge, filter bar, top/bottom pagination (count + prev/next), card list, empty state. Key decisions: - Uses existing IssueBadge, useSearchFilters, getSmartBadgeLabel utilities - Server Component page unchanged; only client leaf components added - Severity dots use a static Tailwind class map (not string manipulation) - data-testid: mobile-issue-card, mobile-issues-search, mobile-filter-chips Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
There was a problem hiding this comment.
Pull request overview
Adds a mobile-first issues list experience (< md) by introducing a card-based list with a lightweight filter/search bar, while keeping the existing desktop table + filters for md and above.
Changes:
- Add new mobile components:
MobileIssueList,MobileIssueCard, andMobileIssueFilterBar. - Update
/issuespage to render mobile cards undermdand the existing desktop table atmd+. - Add mobile pagination controls and an empty state consistent with the desktop list.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| src/app/(app)/issues/page.tsx | Splits rendering into md:hidden (mobile cards) and hidden md:block (desktop table). |
| src/components/issues/MobileIssueList.tsx | Composes mobile header, filter bar, pagination, card list, and empty state. |
| src/components/issues/MobileIssueFilterBar.tsx | Implements mobile search + chip row (sort/status/machine/assignee). |
| src/components/issues/MobileIssueCard.tsx | Renders the tappable mobile issue card layout (ID, machine, age, status, severity, assignee). |
Comments suppressed due to low confidence (1)
src/components/issues/MobileIssueList.tsx:146
hasActiveIssueFilters(searchParams)is computed three times in this render path. Consider computing it once (e.g.,const hasActive = ...) to avoid repeated work and to keep the empty-state logic easier to read/maintain.
<p className="text-sm font-semibold text-foreground">
{hasActiveIssueFilters(searchParams)
? "No issues found"
: "No issues yet"}
</p>
<p className="text-xs text-muted-foreground mt-1 max-w-[200px]">
{hasActiveIssueFilters(searchParams)
? "Adjust your filters to see more issues."
: "Issues will appear here once they are reported."}
</p>
{!hasActiveIssueFilters(searchParams) && (
<Button variant="outline" size="sm" className="mt-3" asChild>
<Link href="/report">Report an Issue</Link>
</Button>
…terBar - Fix status chip label: empty status array (All) now shows "All" via ALL_STATUS_OPTIONS - Replace hardcoded closed-status list with shared CLOSED_STATUSES constant - Remove non-functional SlidersHorizontal filter button (deferred to PinPoint-eddl) - Machine/Assignee chips now only render when filter is active, acting as clear chips Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mobile redesign added a second search input (mobile-issues-search) alongside
the desktop one (issue-search). Playwright strict mode rejected
getByPlaceholder("Search issues...") since it matched both. Added
getIssueSearchInput() helper that selects by testid based on viewport.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
e2e/smoke/issue-list.spec.ts:38
- This test still uses desktop-only UI/ARIA assumptions (e.g. "Showing 1 of 1 issues", table
role=row, and the "Clear" button). With the newmd:hiddenmobile layout, those elements aren’t visible in Mobile Chrome/Safari projects and the test will fail. Either skip this test on mobile (as done for the inline-edit test) or branch assertions/interactions to use the mobile card UI (data-testid="mobile-issue-card",aria-label="Clear search", and the mobile pagination text).
test("should filter and search issues", async ({ page }, testInfo) => {
// 1. Setup: Use seeded issues
// Issue 1: "Thing flips the bird" (TAF-01)
// Issue 2: "Bookcase not registering" (TAF-02)
const title1 = seededIssues.TAF[0].title;
| const start = totalCount === 0 ? 0 : (page - 1) * pageSize + 1; | ||
| const end = Math.min(totalCount, page * pageSize); | ||
| const isFirstPage = page <= 1; | ||
| const isLastPage = end >= totalCount; | ||
|
|
There was a problem hiding this comment.
start/end are derived from page and totalCount only. If the user lands on an out-of-range page (common after changing filters), issues can be empty while totalCount > 0, producing a backwards range like “31–30 of 30”. Consider deriving end from issues.length (or clamping page to the last page) and showing 0 issues when issues.length === 0.
| @@ -326,7 +328,7 @@ test.describe("Issue List Features", () => { | |||
| await page.waitForURL(/severity=major/); | |||
|
|
|||
There was a problem hiding this comment.
This test applies severity filters via filter-severity, which is part of the desktop IssueFilters UI. Since the page now hides desktop filters on < md, this flow won’t work on the Mobile projects in Playwright and will fail. Either skip this test on mobile viewports or add a mobile-specific equivalent once the mobile filter sheet is implemented.
…list # Conflicts: # e2e/smoke/issue-list.spec.ts
|
Claude Code Review: No issues found. |
Summary
MobileIssueCardcomponent renders ID chip, machine name, age, title (line-clamp-2), status badge, severity dot + label, and assignee avatar; urgent (unplayable) cards get red-tinted borderMobileIssueFilterBarprovides a search input with clear button and a horizontally scrollable chip row (Sort, Status, Machine, Assigned) with active state on filtered chipsMobileIssueListcomposes the header with total count badge, filter bar, top/bottom pagination, and the card listDesign Reference
Based on
docs/design-inspiration:docs/inspiration/mobile-redesign/mockup-issues-list.html.Files Changed
src/app/(app)/issues/page.tsx— Wraps desktop inhidden md:block, addsmd:hiddenmobile sectionsrc/components/issues/MobileIssueCard.tsx— New: tappable issue cardsrc/components/issues/MobileIssueFilterBar.tsx— New: mobile search + filter chipssrc/components/issues/MobileIssueList.tsx— New: mobile layout orchestratorTest plan
/issueson mobile viewport (< 768px): cards appear, table hidden/issueson desktop viewport (>= 768px): table appears, cards hiddendata-testid="mobile-issue-card"present on each carddata-testid="mobile-issues-search"on search inputdata-testid="mobile-filter-chips"on filter chip rowpnpm run checkpassesCloses PinPoint-5g0
Generated with Claude Code