deckhearth/src/components/scanner/ScanningToast.tsx
Randall Stillwell 8fe34cc10f Implement mobile-first responsive design for scanner wizard
📱 Mobile-First Design Overhaul:
- Complete responsive redesign prioritizing mobile experience
- Touch-friendly interface with larger tap targets (48px minimum)
- Optimized layouts that work seamlessly from mobile to desktop

🎨 ScanModeSelector Mobile Updates:
- Full-screen mobile layout with proper spacing
- Touch-friendly mode selection cards with active states
- Responsive grid (1 column mobile, 2 columns tablet+)
- Enhanced pro tips section with better mobile typography

📷 AutoScanningCamera Mobile Optimizations:
- Mobile-optimized camera preview with proper aspect ratios
- Touch-friendly manual scan button (full-width on mobile)
- Better positioned queue counter and scanning indicators
- Mobile-specific camera controls overlay with live indicators
- Improved error messaging and OCR configuration warnings

🗂️ CardQueue Mobile Experience:
- Responsive card grid (1 col mobile → 4 cols desktop)
- Larger touch targets for selection and removal
- Mobile-optimized card thumbnails with better info layout
- Touch-friendly bulk selection controls
- Improved empty state with better mobile spacing

 BulkOperations Mobile Interface:
- Responsive 3-column layout (stacked on mobile)
- Touch-optimized form controls and buttons
- Better mobile typography and spacing
- Enhanced tag suggestions with touch-friendly buttons
- Mobile-optimized creation workflows

🎯 ScanningToast Mobile Positioning:
- Full-width on mobile, centered on desktop
- Better mobile positioning (top-left-right)
- Responsive text sizing and icon scaling
- Improved progress bar visibility on mobile

🚀 Mobile UX Enhancements:
- Active states for all interactive elements
- Proper focus rings for accessibility
- Mobile-optimized border radius (rounded-xl)
- Better visual hierarchy with responsive typography
- Consistent spacing system across all components

Perfect for mobile card scanning experience! 📱
2025-07-22 12:37:31 -05:00

86 lines
No EOL
2.5 KiB
TypeScript

import React from 'react';
interface ScanningToastProps {
isVisible: boolean;
message: string;
progress?: number; // 0-100 for progress bar
type?: 'scanning' | 'processing' | 'success' | 'error';
}
const ScanningToast: React.FC<ScanningToastProps> = ({
isVisible,
message,
progress,
type = 'scanning'
}) => {
if (!isVisible) return null;
const getTypeStyles = () => {
switch (type) {
case 'scanning':
return 'bg-blue-600 text-white';
case 'processing':
return 'bg-purple-600 text-white';
case 'success':
return 'bg-green-600 text-white';
case 'error':
return 'bg-red-600 text-white';
default:
return 'bg-blue-600 text-white';
}
};
const getIcon = () => {
switch (type) {
case 'scanning':
return '📷';
case 'processing':
return '🤖';
case 'success':
return '✅';
case 'error':
return '❌';
default:
return '📷';
}
};
return (
<div className="fixed top-4 left-4 right-4 z-50 animate-slide-down sm:left-1/2 sm:right-auto sm:transform sm:-translate-x-1/2 sm:w-auto sm:min-w-80 sm:max-w-md">
<div className={`${getTypeStyles()} rounded-xl shadow-lg px-4 py-3 sm:px-5 sm:py-4`}>
<div className="flex items-center space-x-3">
{/* Icon */}
<div className="text-lg sm:text-xl flex-shrink-0" role="img" aria-label={type}>
{getIcon()}
</div>
{/* Content */}
<div className="flex-1 min-w-0">
<div className="font-medium text-sm sm:text-base leading-tight">{message}</div>
{/* Progress bar */}
{progress !== undefined && (
<div className="mt-2">
<div className="w-full bg-white/20 rounded-full h-1.5 sm:h-2">
<div
className="bg-white h-1.5 sm:h-2 rounded-full transition-all duration-300 ease-out"
style={{ width: `${Math.min(100, Math.max(0, progress))}%` }}
/>
</div>
</div>
)}
</div>
{/* Spinner for scanning/processing */}
{(type === 'scanning' || type === 'processing') && (
<div className="w-5 h-5 sm:w-6 sm:h-6 flex-shrink-0">
<div className="animate-spin rounded-full h-5 w-5 sm:h-6 sm:w-6 border-2 border-white border-t-transparent"></div>
</div>
)}
</div>
</div>
</div>
);
};
export default ScanningToast;