diff --git a/.planning/phases/04-tickets-restyle/04-UI-SPEC.md b/.planning/phases/04-tickets-restyle/04-UI-SPEC.md index 14619a4..3fc6475 100644 --- a/.planning/phases/04-tickets-restyle/04-UI-SPEC.md +++ b/.planning/phases/04-tickets-restyle/04-UI-SPEC.md @@ -50,7 +50,8 @@ Declared values (multiples of 4). Pulled from existing mobile page patterns and |-------|-------|---------------------| | xs | 4px | Icon gaps (`gap-1`), badge padding (`px-1.5 py-0.5`) | | sm | 8px | Row internal gaps (`gap-2`), filter chip gaps (`gap-2`) | -| md | 16px | Horizontal page padding (`px-4`), filter panel `px-4` | +| sm+ | 12px (3 × 4) | Secondary stacking, filter strip `pb-3` | +| md | 16px | Horizontal page padding (`px-4`), filter panel `px-4`, list row vertical padding (`py-4`) | | lg | 24px | Vertical section breaks between filter header and list | | xl | 32px | Empty-state vertical padding (`py-8`) | | 2xl | 48px | Empty-state with no-results full-screen centering (`py-12`) | @@ -65,13 +66,15 @@ Exceptions: 4px-wide priority stripe is a visual mark, not an interactive target All sizes are Tailwind defaults read from `DESIGN.md §2` and matched to the existing `app/mobile/tickets/page.tsx` patterns. +Two weights only: `font-normal` (400) and `font-semibold` (600). `font-medium` (500) is not used in this phase. + | Role | Size class | Weight | Line Height | Font | Usage | |------|-----------|--------|-------------|------|-------| | Row title | `text-sm` (14px) | `font-semibold` (600) | `leading-snug` (1.375) | IBM Plex Sans | Ticket title in list row — 1-line truncate | | Body / secondary | `text-xs` (12px) | `font-normal` (400) | `leading-normal` (1.5) | IBM Plex Sans | Company name, age, assignee in row | | Ticket number / ID | `text-[10px]` (10px) | `font-mono` / `font-normal` (400) | `leading-normal` | IBM Plex Mono | Ticket # badge in row (`font-mono`) | -| Detail breadcrumb | `text-sm` (14px) | `font-medium` (500) | `leading-normal` | IBM Plex Sans | "Tickets / #T20250001" in detail header | -| Filter label | `text-xs` (12px) | `font-medium` (500) | `leading-none` | IBM Plex Sans | Chip labels (Open, High, etc.) | +| Detail breadcrumb | `text-sm` (14px) | `font-semibold` (600) | `leading-normal` | IBM Plex Sans | "Tickets / #T20250001" in detail header | +| Filter label | `text-xs` (12px) | `font-semibold` (600) | `leading-none` | IBM Plex Sans | Chip labels (Open, High, etc.) | | Count / status line | `text-xs` (12px) | `font-normal` (400) | `leading-normal` | IBM Plex Sans | "N open tickets" beneath filter strip | Heading note: No `text-2xl` page title is rendered by the list page — the shell HeaderBar owns the brand mark; the list page opens directly with the filter strip. The detail page retains its existing `text-base font-bold` ticket title (body is out of scope). @@ -85,7 +88,7 @@ All colors use CSS variable tokens from `app/globals.css` + `app/styles/brand.cs | Role | Token / Class | Usage | |------|--------------|-------| | Dominant surface (60%) | `bg-background` | Page background, filter strip background, row background | -| Secondary surface (30%) | `bg-muted` / `bg-muted/50` | Ticket number badge, filter chip hover, row hover (`hover:bg-accent`) | +| Secondary surface (30%) | `bg-muted` / `bg-muted/50` | Ticket number badge, filter chip hover, row hover (`hover:bg-muted/50`) | | Primary accent (10%) | `text-primary` / `bg-primary` / `bg-primary/15` | Active filter chip selected state (`bg-primary text-primary-foreground`) | | Muted text | `text-muted-foreground` | Company, age, assignee — all secondary row fields | | Border | `border-border` | Row dividers, filter strip border-b, filter chip borders | @@ -108,6 +111,10 @@ These are direct Tailwind palette references (not CSS variable tokens) per the D ## Component Inventory +### Primary Visual Anchor + +The primary focal point on the list page is the ticket title row. The `text-sm font-semibold` title creates a clear hierarchy against the `text-xs font-normal` secondary metadata (company, age, queue) beneath it. Every row is visually anchored to this title line — readers land there first, then scan down to context. + ### Filter Strip [D-01 through D-04] — Collapsible **Container:** `sticky top-0 bg-background z-10 border-b px-4 pt-4 pb-3 space-y-2` @@ -131,13 +138,13 @@ These are direct Tailwind palette references (not CSS variable tokens) per the D | Queue | `Select` (shadcn) | Sourced from existing `/api/mobile/tickets` queue list | `queue` (int) | | Assigned to me | `Switch` or `Toggle` (shadcn) | on/off | `mine` (`1`/absent) | -Filter chips: `shrink-0 px-3 py-1 rounded-full text-xs font-medium border transition-colors` — active: `bg-primary text-primary-foreground border-primary`; inactive: `border-border hover:bg-accent` +Filter chips: `shrink-0 px-3 py-1 rounded-full text-xs font-semibold border transition-colors` — active: `bg-primary text-primary-foreground border-primary`; inactive: `border-border hover:bg-muted/50` "Clear all" button: `text-xs text-muted-foreground underline`, appears only when ≥1 filter is active [D-04] ### Ticket List Row [D-15 through D-17] -Outer wrapper: `` — `flex items-start border-l-4 {priority-border-class} px-4 py-3.5 hover:bg-accent transition-colors active:bg-accent` +Outer wrapper: `` — `flex items-start border-l-4 {priority-border-class} px-4 py-4 hover:bg-muted/50 transition-colors active:bg-muted/50` Row interior structure: ``` @@ -157,7 +164,7 @@ Row dividers: `divide-y` on the list container — matches existing pattern. - Sentinel: `
` at list end - `IntersectionObserver` with `rootMargin: '200px'` fires `fetchNextPage()` when sentinel enters viewport - Guard: no-op if `loadingMore || !hasMore` -- Load more button: `w-full py-3 rounded-xl border text-sm font-medium hover:bg-accent transition-colors disabled:opacity-50` — always rendered when `hasMore`, focusable, triggers same fetch path +- Load more button: `w-full py-3 rounded-xl border text-sm font-semibold hover:bg-muted/50 transition-colors disabled:opacity-50` — always rendered when `hasMore`, focusable, triggers same fetch path - Loading more indicator: small `Loader2` icon (`w-4 h-4 animate-spin text-muted-foreground`) centered above the Load more button during in-flight requests ### Detail Page In-Page Header [D-18] @@ -168,7 +175,7 @@ New header bar: `flex items-center justify-between px-4 py-3 border-b` Left slot: `