From a7a6f191caa9e6712c9c5d741a8b6d03ed5a29b5 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Fri, 29 May 2026 06:33:20 -0700 Subject: [PATCH] feat(tracker-web): migrate items page controls + create modal to primitives (UX-2.1) Replace the raw search input, the three filter selects, the New Item button, and the hand-rolled create modal with @bytelyst/ui Input/Select/ Field/Button/Modal (via the Primitives adapter). The shared Modal closes the focus-trap/Esc/scroll-lock a11y gap. Swap the inline type/status/ priority cell pills to StatusBadge with token-driven tones. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../src/app/dashboard/items/page.tsx | 263 ++++++++---------- 1 file changed, 123 insertions(+), 140 deletions(-) diff --git a/dashboards/tracker-web/src/app/dashboard/items/page.tsx b/dashboards/tracker-web/src/app/dashboard/items/page.tsx index 045ed4b0..f899d046 100644 --- a/dashboards/tracker-web/src/app/dashboard/items/page.tsx +++ b/dashboards/tracker-web/src/app/dashboard/items/page.tsx @@ -4,28 +4,40 @@ import { useEffect, useState, useCallback, useMemo } from 'react'; import Link from 'next/link'; import { DataTable, type ColumnDef } from '@bytelyst/data-table'; import { PageHeader, LoadingSpinner } from '@bytelyst/dashboard-components'; +import { + Button, + Input, + Select, + Textarea, + Field, + FieldLabel, + Modal, + StatusBadge, + AlertBanner, + type StatusTone, +} from '@/components/ui/Primitives'; import { useAuth } from '@/lib/auth-context'; import { listItems, createItem, deleteItem, type TrackerItem } from '@/lib/tracker-client'; -const TYPE_BADGE: Record = { - bug: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300', - feature: 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300', - task: 'bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-300', +const TYPE_TONE: Record = { + bug: 'danger', + feature: 'info', + task: 'warning', }; -const PRIORITY_BADGE: Record = { - critical: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300', - high: 'bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-300', - medium: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-300', - low: 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300', +const PRIORITY_TONE: Record = { + critical: 'danger', + high: 'warning', + medium: 'neutral', + low: 'success', }; -const STATUS_BADGE: Record = { - open: 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300', - in_progress: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-300', - done: 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-300', - closed: 'bg-gray-100 text-gray-800 dark:bg-gray-800/30 dark:text-gray-300', - wont_fix: 'bg-gray-100 text-gray-600 dark:bg-gray-800/30 dark:text-gray-400', +const STATUS_TONE: Record = { + open: 'success', + in_progress: 'warning', + done: 'success', + closed: 'neutral', + wont_fix: 'neutral', }; export default function ItemsListPage() { @@ -139,11 +151,9 @@ export default function ItemsListPage() { accessorKey: 'type', header: 'Type', cell: ({ row }) => ( - + {row.original.type} - + ), }, { @@ -151,11 +161,9 @@ export default function ItemsListPage() { accessorKey: 'status', header: 'Status', cell: ({ row }) => ( - + {row.original.status.replace(/_/g, ' ')} - + ), }, { @@ -163,11 +171,9 @@ export default function ItemsListPage() { accessorKey: 'priority', header: 'Priority', cell: ({ row }) => ( - + {row.original.priority} - + ), }, { id: 'voteCount', accessorKey: 'voteCount', header: 'Votes' }, @@ -177,12 +183,14 @@ export default function ItemsListPage() { header: 'Actions', enableSorting: false, cell: ({ row }) => ( - + ), }, ], @@ -195,65 +203,61 @@ export default function ItemsListPage() { setShowCreate(true)} - className="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90" - > - + New Item - - } + actions={} />

{total} items total

{error && ( -
+ {error} -
+ )} {/* Filters */}
- setSearch(e.target.value)} - className="rounded-md border border-input bg-background px-3 py-1.5 text-sm outline-none ring-ring focus:ring-2" /> - - setStatusFilter(e.target.value)} - className="rounded-md border border-input bg-background px-3 py-1.5 text-sm" - > - - - - - - - - setPriorityFilter(e.target.value)} - className="rounded-md border border-input bg-background px-3 py-1.5 text-sm" - > - - - - - - + options={[ + { value: '', label: 'All priorities' }, + { value: 'critical', label: 'Critical' }, + { value: 'high', label: 'High' }, + { value: 'medium', label: 'Medium' }, + { value: 'low', label: 'Low' }, + ]} + />
{/* Items table — @bytelyst/data-table (Wave 9.C.9) */} @@ -276,78 +280,57 @@ export default function ItemsListPage() { )} {/* Create modal */} - {showCreate && ( -
-
-

New Item

-
-
- - setNewTitle(e.target.value)} - className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm outline-none ring-ring focus:ring-2" - /> -
-
-
- - -
-
- - -
-
-
- -