feat: Standardize table UI across Orders and Products modules
**Issue:** - Orders and Products had inconsistent table styling - Orders: px-3 py-2, no hover, no header bg - Products: p-3, hover effect, header bg **Solution:** 1. Added comprehensive Table/List UI Standards to PROJECT_SOP.md 2. Updated Orders table to match Products standard **Changes to PROJECT_SOP.md:** - Added "Table/List UI Standards" section - Defined required classes for all table elements - Specified padding: p-3 (NOT px-3 py-2) - Specified header: bg-muted/50 + font-medium - Specified rows: hover:bg-muted/30 - Added empty state and mobile card patterns **Changes to Orders/index.tsx:** - Container: border-border bg-card → border (match Products) - Header: border-b → bg-muted/50 + border-b - Header cells: px-3 py-2 → p-3 font-medium text-left - Body rows: Added hover:bg-muted/30 - Body cells: px-3 py-2 → p-3 - Empty state: px-3 py-12 → p-8 text-muted-foreground **Result:** ✅ Consistent padding across all modules (p-3) ✅ Consistent header styling (bg-muted/50 + font-medium) ✅ Consistent hover effects (hover:bg-muted/30) ✅ Consistent container styling (overflow-hidden) ✅ Documented standard for future modules
This commit is contained in:
@@ -392,11 +392,11 @@ export default function Orders() {
|
||||
</div>
|
||||
|
||||
{/* Desktop: Table */}
|
||||
<div className="hidden md:block rounded-lg border border-border bg-card overflow-auto">
|
||||
<div className="hidden md:block rounded-lg border overflow-hidden">
|
||||
<table className="min-w-[800px] w-full text-sm">
|
||||
<thead className="border-b">
|
||||
<tr className="text-left">
|
||||
<th className="px-3 py-2 w-12">
|
||||
<thead className="bg-muted/50">
|
||||
<tr className="border-b">
|
||||
<th className="w-12 p-3">
|
||||
<Checkbox
|
||||
checked={allSelected}
|
||||
onCheckedChange={toggleAll}
|
||||
@@ -404,39 +404,39 @@ export default function Orders() {
|
||||
className={someSelected ? 'data-[state=checked]:bg-gray-400' : ''}
|
||||
/>
|
||||
</th>
|
||||
<th className="px-3 py-2">{__('Order')}</th>
|
||||
<th className="px-3 py-2">{__('Date')}</th>
|
||||
<th className="px-3 py-2">{__('Customer')}</th>
|
||||
<th className="px-3 py-2">{__('Items')}</th>
|
||||
<th className="px-3 py-2">{__('Status')}</th>
|
||||
<th className="px-3 py-2 text-right">{__('Total')}</th>
|
||||
<th className="px-3 py-2 text-center">{__('Actions')}</th>
|
||||
<th className="text-left p-3 font-medium">{__('Order')}</th>
|
||||
<th className="text-left p-3 font-medium">{__('Date')}</th>
|
||||
<th className="text-left p-3 font-medium">{__('Customer')}</th>
|
||||
<th className="text-left p-3 font-medium">{__('Items')}</th>
|
||||
<th className="text-left p-3 font-medium">{__('Status')}</th>
|
||||
<th className="text-right p-3 font-medium">{__('Total')}</th>
|
||||
<th className="text-center p-3 font-medium">{__('Actions')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filteredOrders.map((row) => (
|
||||
<tr key={row.id} className="border-b last:border-0">
|
||||
<td className="px-3 py-2">
|
||||
<tr key={row.id} className="border-b hover:bg-muted/30 last:border-0">
|
||||
<td className="p-3">
|
||||
<Checkbox
|
||||
checked={selectedIds.includes(row.id)}
|
||||
onCheckedChange={() => toggleRow(row.id)}
|
||||
aria-label={__('Select order')}
|
||||
/>
|
||||
</td>
|
||||
<td className="px-3 py-2">
|
||||
<td className="p-3">
|
||||
<Link className="underline underline-offset-2" to={`/orders/${row.id}`}>#{row.number}</Link>
|
||||
</td>
|
||||
<td className="px-3 py-2 min-w-32">
|
||||
<td className="p-3 min-w-32">
|
||||
<span title={row.date ?? ""}>
|
||||
{formatRelativeOrDate(row.date_ts)}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-3 py-2">{row.customer || '—'}</td>
|
||||
<td className="px-3 py-2">
|
||||
<td className="p-3">{row.customer || '—'}</td>
|
||||
<td className="p-3">
|
||||
<ItemsCell row={row} />
|
||||
</td>
|
||||
<td className="px-3 py-2"><StatusBadge value={row.status} /></td>
|
||||
<td className="px-3 py-2 text-right tabular-nums font-mono">
|
||||
<td className="p-3"><StatusBadge value={row.status} /></td>
|
||||
<td className="p-3 text-right tabular-nums font-mono">
|
||||
{formatMoney(row.total, {
|
||||
currency: row.currency || store.currency,
|
||||
symbol: row.currency_symbol || store.symbol,
|
||||
@@ -446,7 +446,7 @@ export default function Orders() {
|
||||
decimals: store.decimals,
|
||||
})}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-center space-x-2">
|
||||
<td className="p-3 text-center space-x-2">
|
||||
<Link className="btn text-sm underline underline-offset-2" to={`/orders/${row.id}`}>{__('Open')}</Link>
|
||||
<Link className="btn text-sm underline underline-offset-2" to={`/orders/${row.id}/edit`}>{__('Edit')}</Link>
|
||||
</td>
|
||||
@@ -455,7 +455,7 @@ export default function Orders() {
|
||||
|
||||
{filteredOrders.length === 0 && (
|
||||
<tr>
|
||||
<td className="px-3 py-12 text-center" colSpan={8}>
|
||||
<td className="p-8 text-center text-muted-foreground" colSpan={8}>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<PackageOpen className="w-8 h-8 opacity-40" />
|
||||
<div className="font-medium">{__('No orders found')}</div>
|
||||
|
||||
Reference in New Issue
Block a user