📱 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! 📱✨
86 lines
No EOL
2.5 KiB
TypeScript
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;
|