mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 14:15:23 +02:00
feat: full mobile responsive optimization for Android/iPhone
- Add bottom navigation bar (6 tabs) for mobile, hidden on desktop - Compact header with smaller logo and reduced padding on mobile - Collapsible filter bar with active filter count badge on mobile - Bottom-sheet style dropdowns with overlay and larger touch targets - Fullscreen AI chat on mobile, floating window on desktop - Responsive dashboard cards with always-visible expand button - Smaller table text and touch-friendly scroll on all data grids - iPhone safe-area support and thinner scrollbars on mobile Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
fecc7264c8
commit
9895545910
@@ -38,6 +38,14 @@ const MultiSelectDropdown: React.FC<MultiSelectDropdownProps> = ({ label, select
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
// Prevent body scroll when dropdown is open on mobile
|
||||
useEffect(() => {
|
||||
if (isOpen && window.innerWidth < 768) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
return () => { document.body.style.overflow = ''; };
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const filteredOptions = useMemo(() => {
|
||||
if (!searchTerm) return options;
|
||||
return options.filter(opt => opt.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
@@ -139,8 +147,23 @@ const MultiSelectDropdown: React.FC<MultiSelectDropdownProps> = ({ label, select
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{/* Mobile overlay backdrop */}
|
||||
{isOpen && (
|
||||
<div className="absolute top-[calc(100%+4px)] left-0 w-64 max-h-96 overflow-hidden bg-slate-900 border border-slate-700 rounded-xl shadow-2xl z-[100] animate-fade-in flex flex-col">
|
||||
<div className="fixed inset-0 bg-black/50 z-[99] md:hidden" onClick={() => setIsOpen(false)} />
|
||||
)}
|
||||
|
||||
{isOpen && (
|
||||
<div className="fixed inset-x-3 bottom-3 max-h-[75vh] md:absolute md:inset-auto md:top-[calc(100%+4px)] md:left-0 md:bottom-auto md:w-64 md:max-h-96 overflow-hidden bg-slate-900 border border-slate-700 rounded-xl shadow-2xl z-[100] animate-fade-in flex flex-col">
|
||||
|
||||
{/* Mobile header with close */}
|
||||
<div className="flex items-center justify-between p-3 border-b border-slate-800 md:hidden">
|
||||
<h3 className="text-sm font-bold text-white">{label}</h3>
|
||||
<button onClick={() => setIsOpen(false)} className="text-slate-400 active:text-white p-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-5 h-5">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Search Bar */}
|
||||
<div className="p-2 border-b border-slate-800 sticky top-0 bg-slate-900 z-10">
|
||||
@@ -209,14 +232,14 @@ const MultiSelectDropdown: React.FC<MultiSelectDropdownProps> = ({ label, select
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1 overflow-y-auto custom-scrollbar p-2 max-h-60">
|
||||
<div className="space-y-1 overflow-y-auto custom-scrollbar scroll-touch p-2 max-h-60 md:max-h-60">
|
||||
{filteredOptions.map((opt) => (
|
||||
<label key={opt} className="flex items-center space-x-3 p-2 rounded hover:bg-slate-800 cursor-pointer group">
|
||||
<label key={opt} className="flex items-center space-x-3 p-2.5 md:p-2 rounded hover:bg-slate-800 active:bg-slate-700 cursor-pointer group">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selected.includes(opt)}
|
||||
onChange={() => toggleOption(opt)}
|
||||
className="form-checkbox h-4 w-4 text-primary rounded border-slate-600 bg-slate-800 focus:ring-primary focus:ring-offset-slate-900 transition duration-150 ease-in-out"
|
||||
className="form-checkbox h-5 w-5 md:h-4 md:w-4 text-primary rounded border-slate-600 bg-slate-800 focus:ring-primary focus:ring-offset-slate-900 transition duration-150 ease-in-out"
|
||||
/>
|
||||
<span className={`text-sm break-all group-hover:text-white ${selected.includes(opt) ? 'text-white' : 'text-slate-400'}`}>
|
||||
{opt}
|
||||
|
||||
Reference in New Issue
Block a user