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:
Christian Vidal Wolf
2026-02-16 09:27:46 +01:00
co-authored by Claude Opus 4.6
parent fecc7264c8
commit 9895545910
11 changed files with 172 additions and 72 deletions
+14 -14
View File
@@ -34,12 +34,12 @@ const ExpandableCard: React.FC<{ title: string; children: React.ReactNode; class
if (isExpanded) {
return (
<div className="fixed inset-0 z-50 bg-slate-950 px-6 pb-6 pt-32 flex flex-col animate-fade-in overflow-hidden">
<div className="fixed inset-0 z-50 bg-slate-950 px-3 pb-16 pt-16 md:px-6 md:pb-6 md:pt-32 flex flex-col animate-fade-in overflow-hidden">
{/* Fixed Close Button - Positioned TOP RIGHT ON TOP OF FILTER BAR with z-[100] */}
{/* Fixed Close Button */}
<button
onClick={toggleExpand}
className="fixed top-3 right-3 z-[100] p-2 bg-red-600/90 hover:bg-red-500 border border-red-400 rounded-full text-white transition-all shadow-2xl hover:scale-110 flex items-center gap-2 group"
className="fixed top-3 right-3 z-[100] p-2 bg-red-600/90 hover:bg-red-500 active:bg-red-500 border border-red-400 rounded-full text-white transition-all shadow-2xl hover:scale-110 flex items-center gap-2 group"
title="Exit Fullscreen"
>
<span className="text-xs font-bold hidden group-hover:inline pr-1">CLOSE</span>
@@ -48,10 +48,10 @@ const ExpandableCard: React.FC<{ title: string; children: React.ReactNode; class
</svg>
</button>
<div className="flex justify-between items-center mb-4 border-b border-slate-800 pb-4 shrink-0">
<h3 className="text-xl font-bold text-slate-100 uppercase tracking-wide">{title}</h3>
<div className="flex justify-between items-center mb-3 md:mb-4 border-b border-slate-800 pb-3 md:pb-4 shrink-0">
<h3 className="text-base md:text-xl font-bold text-slate-100 uppercase tracking-wide">{title}</h3>
</div>
<div className="flex-1 overflow-auto bg-slate-900 rounded-xl p-6 border border-border custom-scrollbar">
<div className="flex-1 overflow-auto bg-slate-900 rounded-xl p-3 md:p-6 border border-border custom-scrollbar scroll-touch">
{children}
</div>
</div>
@@ -60,13 +60,13 @@ const ExpandableCard: React.FC<{ title: string; children: React.ReactNode; class
return (
<div
className={`bg-surface border border-border rounded-xl p-6 shadow-sm flex flex-col group relative transition-all duration-300 hover:shadow-primary/5 ${className}`}
className={`bg-surface border border-border rounded-xl p-3 md:p-6 shadow-sm flex flex-col group relative transition-all duration-300 hover:shadow-primary/5 ${className}`}
>
<div className="flex justify-between items-start mb-4">
<h3 className="text-sm font-semibold text-slate-400 uppercase tracking-wide">{title}</h3>
<div className="flex justify-between items-start mb-3 md:mb-4">
<h3 className="text-xs md:text-sm font-semibold text-slate-400 uppercase tracking-wide">{title}</h3>
<button
onClick={toggleExpand}
className="opacity-0 group-hover:opacity-100 text-slate-500 hover:text-primary transition-opacity"
className="opacity-100 md:opacity-0 md:group-hover:opacity-100 text-slate-500 hover:text-primary active:text-primary transition-opacity"
title="Expand to Fullscreen"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-5 h-5">
@@ -74,7 +74,7 @@ const ExpandableCard: React.FC<{ title: string; children: React.ReactNode; class
</svg>
</button>
</div>
<div className="flex-1 min-h-[250px] cursor-pointer" onClick={toggleExpand}>{children}</div>
<div className="flex-1 min-h-[200px] md:min-h-[250px] cursor-pointer" onClick={toggleExpand}>{children}</div>
</div>
);
};
@@ -102,8 +102,8 @@ const MultiYearKPICard: React.FC<{
const displayTitle = contextData ? `${title} (Selected Item)` : title;
return (
<div className="bg-gradient-to-br from-surface to-slate-900 border border-border rounded-xl p-6 flex flex-col justify-center">
<h3 className="text-sm font-medium text-slate-400 mb-3">{displayTitle}</h3>
<div className="bg-gradient-to-br from-surface to-slate-900 border border-border rounded-xl p-3 md:p-6 flex flex-col justify-center">
<h3 className="text-xs md:text-sm font-medium text-slate-400 mb-2 md:mb-3">{displayTitle}</h3>
{sortedYears.length === 0 && <p className="text-3xl font-bold text-white">0</p>}
@@ -508,7 +508,7 @@ const Dashboard: React.FC<DashboardProps> = ({ data, contextData, adsData = [] }
const chartHeight = Math.max(displayData.topLinesSplit.length * 60, 300);
return (
<div className="p-6 space-y-6 max-w-7xl mx-auto animate-fade-in pb-24">
<div className="p-3 md:p-6 space-y-4 md:space-y-6 max-w-7xl mx-auto animate-fade-in pb-24">
{/* Ads Performance Section - Condensed Layout */}
{adsKPIsByYear && availableAdsYears.length > 0 && (