Mobile optimization pass for responsive layouts

- TabsList: Add responsive grid columns (grid-cols-2/3 on mobile)
- Headers: Stack vertically on mobile with responsive text sizes
- Dialogs: Use viewport-relative heights (70-80vh on mobile)
- Grids: Add sm: breakpoints for single-column mobile layouts
- Tables: Add overflow-x-auto for horizontal scrolling
- Buttons: Full-width on mobile with flex-1 sm:flex-none
- Select triggers: Full-width on mobile

Files updated: 21 component and page files across admin,
staff, dashboards, and hub sections.
This commit is contained in:
Claude 2026-01-26 22:46:26 +00:00
parent 88e364f4c5
commit b640b0d2ad
No known key found for this signature in database
21 changed files with 44 additions and 44 deletions

View file

@ -196,7 +196,7 @@ export function ProfileEditor({
return (
<Tabs defaultValue="basic" className="w-full">
<TabsList className="grid w-full grid-cols-5">
<TabsList className="grid w-full grid-cols-2 sm:grid-cols-3 md:grid-cols-5">
<TabsTrigger value="basic">Basic</TabsTrigger>
<TabsTrigger value="social">Social</TabsTrigger>
<TabsTrigger value="skills">Skills</TabsTrigger>

View file

@ -80,7 +80,7 @@ export default function AdminStaffAdmin() {
</div>
<Tabs value={adminTab} onValueChange={setAdminTab} className="space-y-4">
<TabsList className="grid w-full grid-cols-3 lg:grid-cols-6">
<TabsList className="grid w-full grid-cols-2 sm:grid-cols-3 lg:grid-cols-6">
<TabsTrigger value="users" className="flex items-center gap-2">
<Users className="w-4 h-4" />
<span className="hidden sm:inline">Users</span>

View file

@ -209,7 +209,7 @@ export const AIChat: React.FC<AIChatProps> = ({
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: 20, scale: 0.95 }}
transition={{ type: 'spring', damping: 25, stiffness: 300 }}
className="fixed bottom-4 right-4 md:bottom-6 md:right-6 w-[calc(100vw-2rem)] md:w-[450px] h-[600px] max-h-[80vh] bg-background border border-border rounded-2xl shadow-2xl z-50 flex flex-col overflow-hidden"
className="fixed bottom-4 right-4 md:bottom-6 md:right-6 w-[calc(100vw-2rem)] md:w-[450px] h-[70vh] sm:h-[600px] max-h-[80vh] bg-background border border-border rounded-2xl shadow-2xl z-50 flex flex-col overflow-hidden"
>
<div className={`flex items-center justify-between p-4 border-b border-border bg-gradient-to-r ${currentPersona.theme.gradient} bg-opacity-10`}>
<PersonaSelector

View file

@ -205,7 +205,7 @@ export default function CommentsModal({
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[500px] flex flex-col h-[600px]">
<DialogContent className="sm:max-w-[500px] flex flex-col h-[80vh] sm:h-[600px] max-h-[600px]">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<MessageCircle className="h-5 w-5" />

View file

@ -347,7 +347,7 @@ export default function BotPanel() {
</div>
)}
<Separator className="bg-gray-700" />
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<p className="text-sm text-gray-400">Commands</p>
<p className="text-lg font-semibold text-white">
@ -379,7 +379,7 @@ export default function BotPanel() {
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-3 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div className="text-center p-4 bg-gray-700/30 rounded-lg">
<p className="text-2xl font-bold text-white">{feedStats?.totalPosts || 0}</p>
<p className="text-sm text-gray-400">Total Posts</p>

View file

@ -393,7 +393,7 @@ export default function Dashboard() {
onValueChange={setActiveTab}
className="w-full"
>
<TabsList className="grid w-full grid-cols-4 lg:grid-cols-4 bg-purple-950/30 border border-purple-500/20 p-1">
<TabsList className="grid w-full grid-cols-2 sm:grid-cols-4 bg-purple-950/30 border border-purple-500/20 p-1">
<TabsTrigger value="realms" className="text-sm md:text-base">
<span className="hidden sm:inline">Realms</span>
<span className="sm:hidden">Arms</span>

View file

@ -108,7 +108,7 @@ export default function MaintenancePage() {
<div className="h-px bg-border" />
<div className="grid grid-cols-3 gap-4 text-center text-xs">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4 text-center text-xs">
<div className="space-y-1">
<div className="text-muted-foreground">STATUS</div>
<div className="text-blue-400 font-semibold flex items-center justify-center gap-1">

View file

@ -158,7 +158,7 @@ export default function ProjectsAdmin() {
value={draft.title}
onChange={(e) => setDraft({ ...draft, title: e.target.value })}
/>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
<select
className="rounded border border-border/40 bg-background/70 px-3 py-2"
value={draft.org_unit}

View file

@ -74,7 +74,7 @@ export default function StaffAdmin() {
<Card className="bg-slate-900/50 border-purple-500/20">
<CardContent className="pt-6">
<Tabs value={activeTab} onValueChange={setActiveTab}>
<TabsList className="grid w-full grid-cols-5 bg-slate-800/50">
<TabsList className="grid w-full grid-cols-2 sm:grid-cols-3 md:grid-cols-5 bg-slate-800/50">
<TabsTrigger value="users" className="gap-2">
<Users className="w-4 h-4" />
<span className="hidden sm:inline">Users</span>

View file

@ -71,7 +71,7 @@ export default function StaffChat() {
</Button>
</div>
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6 h-[600px]">
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6 h-[calc(100vh-200px)] sm:h-[600px] min-h-[400px]">
{/* Channels Sidebar */}
<Card className="bg-slate-900/50 border-purple-500/20 lg:col-span-1">
<CardHeader>

View file

@ -155,7 +155,7 @@ export default function StaffDashboard() {
</CardHeader>
<CardContent>
<Tabs value={activeTab} onValueChange={setActiveTab}>
<TabsList className="grid w-full grid-cols-4 bg-slate-800/50">
<TabsList className="grid w-full grid-cols-2 sm:grid-cols-4 bg-slate-800/50">
<TabsTrigger value="overview" className="gap-2">
<BarChart3 className="w-4 h-4" />
<span className="hidden sm:inline">Overview</span>

View file

@ -27,7 +27,7 @@ export default function WixCaseStudies() {
<CardDescription>{c.summary}</CardDescription>
</CardHeader>
<CardContent>
<div className="grid grid-cols-3 gap-3 text-sm">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm">
{c.metrics.map((m, i) => (
<div
key={i}

View file

@ -132,18 +132,18 @@ export default function AdminAnalytics() {
<div className="relative z-10">
<div className="container mx-auto max-w-7xl px-4 py-16">
{/* Header */}
<div className="flex items-center justify-between mb-8">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-8">
<div className="flex items-center gap-3">
<div className="p-3 rounded-lg bg-cyan-500/20 border border-cyan-500/30">
<BarChart3 className="h-6 w-6 text-cyan-400" />
</div>
<div>
<h1 className="text-4xl font-bold text-cyan-100">Analytics</h1>
<p className="text-cyan-200/70">Platform insights and metrics</p>
<h1 className="text-2xl sm:text-4xl font-bold text-cyan-100">Analytics</h1>
<p className="text-cyan-200/70 text-sm sm:text-base">Platform insights and metrics</p>
</div>
</div>
<Select value={period} onValueChange={setPeriod}>
<SelectTrigger className="w-40 bg-slate-800 border-slate-700 text-slate-100">
<SelectTrigger className="w-full sm:w-40 bg-slate-800 border-slate-700 text-slate-100">
<SelectValue placeholder="Period" />
</SelectTrigger>
<SelectContent>

View file

@ -264,18 +264,18 @@ export default function AdminModeration() {
<div className="relative z-10">
<div className="container mx-auto max-w-7xl px-4 py-16">
{/* Header */}
<div className="flex items-center justify-between mb-6">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
<div className="flex items-center gap-3">
<div className="p-3 rounded-lg bg-red-500/20 border border-red-500/30">
<Shield className="h-6 w-6 text-red-400" />
</div>
<div>
<h1 className="text-4xl font-bold text-red-100">Moderation</h1>
<p className="text-red-200/70">Content moderation and user management</p>
<h1 className="text-2xl sm:text-4xl font-bold text-red-100">Moderation</h1>
<p className="text-red-200/70 text-sm sm:text-base">Content moderation and user management</p>
</div>
</div>
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="w-40 bg-slate-800 border-slate-700 text-slate-100">
<SelectTrigger className="w-full sm:w-40 bg-slate-800 border-slate-700 text-slate-100">
<SelectValue placeholder="Status" />
</SelectTrigger>
<SelectContent>

View file

@ -238,7 +238,7 @@ export default function GameForgeDashboard() {
className="w-full"
>
<TabsList
className="grid w-full grid-cols-5 bg-green-950/30 border border-green-500/20 p-1"
className="grid w-full grid-cols-2 sm:grid-cols-3 md:grid-cols-5 bg-green-950/30 border border-green-500/20 p-1"
style={{ fontFamily: theme.fontFamily }}
>
<TabsTrigger value="overview">Overview</TabsTrigger>

View file

@ -306,7 +306,7 @@ export default function LabsDashboard() {
className="w-full"
>
<TabsList
className="grid w-full grid-cols-4 bg-amber-950/30 border border-amber-500/20 p-1"
className="grid w-full grid-cols-2 sm:grid-cols-4 bg-amber-950/30 border border-amber-500/20 p-1"
style={{ fontFamily: "Monaco, Courier New, monospace" }}
>
<TabsTrigger value="overview">Overview</TabsTrigger>

View file

@ -421,7 +421,7 @@ export default function NexusDashboard() {
onValueChange={setActiveTab}
className="w-full"
>
<TabsList className="grid w-full grid-cols-4 bg-purple-950/30 border border-purple-500/20 p-1">
<TabsList className="grid w-full grid-cols-2 sm:grid-cols-4 bg-purple-950/30 border border-purple-500/20 p-1">
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="applications">Applications</TabsTrigger>
<TabsTrigger value="contracts">Contracts</TabsTrigger>
@ -876,7 +876,7 @@ export default function NexusDashboard() {
onValueChange={setActiveTab}
className="w-full"
>
<TabsList className="grid w-full grid-cols-4 bg-blue-950/30 border border-blue-500/20 p-1">
<TabsList className="grid w-full grid-cols-2 sm:grid-cols-4 bg-blue-950/30 border border-blue-500/20 p-1">
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="opportunities">Opportunities</TabsTrigger>
<TabsTrigger value="applicants">Applicants</TabsTrigger>

View file

@ -284,8 +284,8 @@ export default function ClientInvoices() {
{selectedInvoice.line_items?.length > 0 && (
<div className="space-y-3">
<h3 className="text-lg font-semibold text-white">Line Items</h3>
<div className="bg-black/30 rounded-lg border border-cyan-500/20 overflow-hidden">
<table className="w-full">
<div className="bg-black/30 rounded-lg border border-cyan-500/20 overflow-x-auto">
<table className="w-full min-w-[500px]">
<thead className="bg-cyan-500/10">
<tr className="text-left text-xs text-gray-400 uppercase">
<th className="p-4">Description</th>

View file

@ -138,7 +138,7 @@ export default function MyApplications() {
}
className="mb-8"
>
<TabsList className="grid w-full grid-cols-5 bg-slate-800/50 border-slate-700">
<TabsList className="grid w-full grid-cols-2 sm:grid-cols-3 md:grid-cols-5 bg-slate-800/50 border-slate-700">
<TabsTrigger value="all">
All ({applications.length})
</TabsTrigger>

View file

@ -266,18 +266,18 @@ export default function StaffOKRs() {
<div className="relative z-10">
<div className="container mx-auto max-w-6xl px-4 py-16">
{/* Header */}
<div className="flex items-center justify-between mb-6">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
<div className="flex items-center gap-3">
<div className="p-3 rounded-lg bg-emerald-500/20 border border-emerald-500/30">
<Target className="h-6 w-6 text-emerald-400" />
</div>
<div>
<h1 className="text-4xl font-bold text-emerald-100">OKRs</h1>
<p className="text-emerald-200/70">Objectives and Key Results</p>
<h1 className="text-2xl sm:text-4xl font-bold text-emerald-100">OKRs</h1>
<p className="text-emerald-200/70 text-sm sm:text-base">Objectives and Key Results</p>
</div>
</div>
<Button
className="bg-emerald-600 hover:bg-emerald-700"
className="bg-emerald-600 hover:bg-emerald-700 w-full sm:w-auto"
onClick={() => setCreateOkrDialog(true)}
>
<Plus className="h-4 w-4 mr-2" />
@ -334,9 +334,9 @@ export default function StaffOKRs() {
</div>
{/* Filters */}
<div className="flex gap-4 mb-8">
<div className="flex flex-wrap gap-4 mb-8">
<Select value={selectedQuarter} onValueChange={setSelectedQuarter}>
<SelectTrigger className="w-32 bg-slate-800 border-slate-700 text-slate-100">
<SelectTrigger className="w-full sm:w-32 bg-slate-800 border-slate-700 text-slate-100">
<SelectValue placeholder="Quarter" />
</SelectTrigger>
<SelectContent>
@ -348,7 +348,7 @@ export default function StaffOKRs() {
</SelectContent>
</Select>
<Select value={selectedYear} onValueChange={setSelectedYear}>
<SelectTrigger className="w-32 bg-slate-800 border-slate-700 text-slate-100">
<SelectTrigger className="w-full sm:w-32 bg-slate-800 border-slate-700 text-slate-100">
<SelectValue placeholder="Year" />
</SelectTrigger>
<SelectContent>
@ -510,7 +510,7 @@ export default function StaffOKRs() {
onChange={(e) => setNewOkr({ ...newOkr, description: e.target.value })}
className="bg-slate-700 border-slate-600 text-slate-100"
/>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<Select
value={newOkr.quarter.toString()}
onValueChange={(v) => setNewOkr({ ...newOkr, quarter: parseInt(v) })}
@ -570,7 +570,7 @@ export default function StaffOKRs() {
onChange={(e) => setNewKr({ ...newKr, description: e.target.value })}
className="bg-slate-700 border-slate-600 text-slate-100"
/>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="text-sm text-slate-400 mb-1 block">Target Value</label>
<Input

View file

@ -276,20 +276,20 @@ export default function StaffTimeTracking() {
<div className="relative z-10">
<div className="container mx-auto max-w-6xl px-4 py-16">
{/* Header */}
<div className="flex items-center justify-between mb-6">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
<div className="flex items-center gap-3">
<div className="p-3 rounded-lg bg-blue-500/20 border border-blue-500/30">
<Clock className="h-6 w-6 text-blue-400" />
</div>
<div>
<h1 className="text-4xl font-bold text-blue-100">Time Tracking</h1>
<p className="text-blue-200/70">Track your work hours and projects</p>
<h1 className="text-2xl sm:text-4xl font-bold text-blue-100">Time Tracking</h1>
<p className="text-blue-200/70 text-sm sm:text-base">Track your work hours and projects</p>
</div>
</div>
<div className="flex gap-2">
<div className="flex flex-wrap gap-2">
{activeTimer ? (
<Button
className="bg-red-600 hover:bg-red-700"
className="bg-red-600 hover:bg-red-700 flex-1 sm:flex-none"
onClick={stopTimer}
>
<Square className="h-4 w-4 mr-2" />
@ -297,7 +297,7 @@ export default function StaffTimeTracking() {
</Button>
) : (
<Button
className="bg-green-600 hover:bg-green-700"
className="bg-green-600 hover:bg-green-700 flex-1 sm:flex-none"
onClick={startTimer}
>
<Play className="h-4 w-4 mr-2" />
@ -305,7 +305,7 @@ export default function StaffTimeTracking() {
</Button>
)}
<Button
className="bg-blue-600 hover:bg-blue-700"
className="bg-blue-600 hover:bg-blue-700 flex-1 sm:flex-none"
onClick={() => setCreateDialog(true)}
>
<Plus className="h-4 w-4 mr-2" />