fix: Make compact list readable on mobile by replacing wide bag select with compact 4-char tag pill and allowing full item text

This commit is contained in:
airent106 committed 2026-10-15 22:40:21 -06:00
1 parent 946a7780f6
commit be586ea386
2 files changed
+82 -52

No files matched your search

+13 -13
View File
@@ -95,7 +95,7 @@ export const BagOverview: React.FC<BagOverviewProps> = ({
</button>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-2 sm:gap-3">
{visibleBags.map((b) => {
const bagItems = items.filter((i) => i.bag === b.id);
const bagPacked = bagItems.filter((i) => i.packed).length;
@@ -112,43 +112,43 @@ export const BagOverview: React.FC<BagOverviewProps> = ({
sound.playClick();
onSelectBag(isSelected ? 'all' : b.id);
}}
className={`relative text-left p-3.5 border-2 border-ink transition-all flex flex-col justify-between ${
className={`relative text-left p-2.5 sm:p-3.5 border-2 border-ink transition-all flex flex-col justify-between ${
isSelected
? 'bg-canary-light shadow-card-hard border-ink translate-x-0.5 translate-y-0.5'
: 'bg-ticket-50 hover:bg-ticket-100 shadow-card-hard-sm'
}`}
>
{/* Perforation holes on card edges */}
<div className="ticket-notch-left" />
<div className="ticket-notch-right" />
<div className="ticket-notch-left hidden sm:block" />
<div className="ticket-notch-right hidden sm:block" />
<div>
{/* Top Barcode Header */}
<div className="flex items-center justify-between border-b border-ink/20 pb-2 mb-2 font-mono text-[10px]">
<span className="bg-ink text-ticket-100 px-1 py-0.5 font-bold uppercase">
<div className="flex items-center justify-between border-b border-ink/20 pb-1.5 sm:pb-2 mb-1.5 sm:mb-2 font-mono text-[10px] gap-1">
<span className="bg-ink text-ticket-100 px-1 py-0.5 font-bold uppercase shrink-0">
{b.tagCode}
</span>
<span className="text-ink-muted tracking-tight truncate max-w-[130px]">
<span className="text-ink-muted tracking-tight truncate">
{b.sub}
</span>
</div>
{/* Title & Icon */}
<div className="flex items-center justify-between gap-2 mb-1">
<div className="flex items-center gap-2 text-ink min-w-0">
<span className="text-ink shrink-0">{getBagIcon(b.iconKey)}</span>
<span className="font-display text-xl tracking-wide uppercase leading-tight truncate">
<div className="flex items-center justify-between gap-1.5 mb-1">
<div className="flex items-center gap-1.5 sm:gap-2 text-ink min-w-0">
<span className="text-ink shrink-0 hidden sm:inline">{getBagIcon(b.iconKey)}</span>
<span className="font-display text-base sm:text-xl tracking-wide uppercase leading-tight truncate">
{b.label}
</span>
</div>
{isFull && (
<CheckCircle2 size={18} className="text-stamp-green shrink-0" />
<CheckCircle2 size={16} className="text-stamp-green shrink-0" />
)}
</div>
{/* TSA / Bag Advisory Tip */}
{b.tsaTip && (
<p className="font-sans text-[11px] text-ink-muted leading-tight mb-3 line-clamp-2">
<p className="font-sans text-[11px] text-ink-muted leading-tight mb-3 line-clamp-2 hidden sm:block">
{b.tsaTip}
</p>
)}
+69 -39
View File
@@ -53,42 +53,51 @@ export const ItemRow: React.FC<ItemRowProps> = ({
if (compact) {
return (
<div
className={`group relative flex items-center justify-between border-2 py-1.5 px-3 mb-1.5 transition-all shadow-xs ${
className={`group relative flex items-center justify-between gap-2 border-2 py-2 px-2.5 sm:px-3 mb-1.5 transition-all shadow-xs ${
item.packed
? 'bg-[#ECE8DC]/70 border-ink/40 text-ink/60'
: 'bg-ticket-50 hover:bg-ticket-100 border-ink'
? 'bg-[#ECE8DC]/80 border-ink/40 text-ink/60'
: 'bg-white hover:bg-ticket-50 border-ink text-ink'
}`}
>
{/* Left: Checkbox & Name */}
<div className="flex items-center gap-2.5 min-w-0 flex-1">
{/* Left: Tap anywhere here to toggle packed */}
<div
onClick={() => {
sound.playTear();
onTogglePacked(item.id);
}}
className="flex items-center gap-2 sm:gap-2.5 min-w-0 flex-1 cursor-pointer select-none"
>
<button
type="button"
onClick={() => {
onClick={(e) => {
e.stopPropagation();
sound.playTear();
onTogglePacked(item.id);
}}
className={`w-5 h-5 rounded border-2 flex items-center justify-center font-mono font-bold shrink-0 transition-transform ${
item.packed
? 'border-stamp-green bg-stamp-green text-white rotate-[-3deg]'
: 'border-ink/60 bg-white hover:border-ink'
: 'border-ink bg-white hover:border-ink'
}`}
title={item.packed ? 'Mark as unpacked' : 'Check off'}
>
{item.packed ? <Check size={12} strokeWidth={3} /> : null}
{item.packed ? <Check size={13} strokeWidth={3} /> : null}
</button>
{/* Qty indicator */}
<span className="font-mono text-xs font-bold text-ink shrink-0 bg-ticket-200 border border-ink/20 px-1.5 py-0.2 rounded-xs">
<span
className={`font-mono text-xs font-bold shrink-0 px-1.5 py-0.5 rounded-xs border ${
item.packed
? 'bg-ticket-200/60 border-ink/20 text-ink/50'
: 'bg-canary/40 border-ink/40 text-ink'
}`}
>
{item.quantity}×
</span>
{/* Name */}
{/* Item Name — full readability on mobile */}
<span
onClick={() => {
sound.playTear();
onTogglePacked(item.id);
}}
className={`font-grotesk font-bold text-xs sm:text-sm truncate cursor-pointer select-none ${
className={`font-grotesk font-bold text-sm sm:text-base leading-snug break-words min-w-0 flex-1 ${
item.packed ? 'line-through text-ink/50' : 'text-ink'
}`}
>
@@ -96,34 +105,55 @@ export const ItemRow: React.FC<ItemRowProps> = ({
</span>
{item.essential && (
<span className="font-mono text-[9px] font-bold bg-gate-orange text-white px-1 py-0.2 uppercase shrink-0 hidden sm:inline">
ESSENTIAL
</span>
<>
<span
className="w-2 h-2 rounded-full bg-gate-orange shrink-0 sm:hidden"
title="Essential item"
/>
<span className="font-mono text-[9px] font-bold bg-gate-orange text-white px-1.5 py-0.5 uppercase shrink-0 hidden sm:inline">
ESSENTIAL
</span>
</>
)}
</div>
{/* Right: Bag Selector & Category Pill & Actions */}
<div className="flex items-center gap-2 shrink-0 ml-2">
{/* Bag Selector Dropdown Pill */}
<select
value={item.bag}
onChange={(e) => {
sound.playClick();
onUpdateBag(item.id, e.target.value);
}}
className="bg-white border border-ink font-mono text-[10px] font-bold px-1.5 py-0.5 cursor-pointer hover:bg-canary-light"
title="Assigned Bag"
{/* Right: Compact Bag Tag Pill & Desktop Actions */}
<div className="flex items-center gap-1.5 sm:gap-2 shrink-0">
{/* Compact Bag Tag Pill with invisible native select overlay so it never stretches mobile width */}
<div
className="relative inline-flex items-center"
title={`Assigned to: ${currentBag.label}`}
>
{availableBags.map((b) => (
<option key={b.id} value={b.id}>
{b.tagCode} ({b.label})
</option>
))}
</select>
<span
className={`font-mono text-[11px] font-bold px-2 py-0.5 border border-ink pointer-events-none flex items-center gap-1 ${
item.packed
? 'bg-ticket-100 text-ink/60 border-ink/40'
: 'bg-ticket-100 text-ink shadow-2xs'
}`}
>
<span>{currentBag.tagCode}</span>
<span className="text-[8px] opacity-60">▾</span>
</span>
<select
value={item.bag}
onChange={(e) => {
sound.playClick();
onUpdateBag(item.id, e.target.value);
}}
aria-label={`Assign ${item.name} to bag`}
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
>
{availableBags.map((b) => (
<option key={b.id} value={b.id}>
{b.tagCode} — {b.label}
</option>
))}
</select>
</div>
{/* Category Pill */}
{/* Category Pill (Desktop only) */}
<span
className={`font-mono text-[9px] font-bold px-1.5 py-0.2 border border-ink/20 hidden md:inline ${catStyle.bg} ${catStyle.text}`}
className={`font-mono text-[9px] font-bold px-1.5 py-0.5 border border-ink/20 hidden md:inline ${catStyle.bg} ${catStyle.text}`}
>
{catStyle.label}
</span>
@@ -135,10 +165,10 @@ export const ItemRow: React.FC<ItemRowProps> = ({
sound.playClick();
onDelete(item.id);
}}
className="p-1 text-ink/30 hover:text-stamp-red transition-colors"
className="p-1 text-ink/35 hover:text-stamp-red transition-colors"
title="Delete item"
>
<Trash2 size={13} />
<Trash2 size={14} />
</button>
</div>
</div>