fix(mobile): stop detail-page grids from overflowing horizontally
The spot page (and the other detail pages) used `grid lg:grid-cols-3` with
no explicit mobile column. Below the `lg` breakpoint the grid falls back to
a single implicit `auto` track, whose minimum is the min-content of its
items. A long mapper name ("Tip the Mapper" card) gave the sidebar a
~559px min-content, so the whole grid widened past the viewport and was
clipped by the global `html, body { overflow-x: hidden }` — content cut off
on the right with no way to scroll to it.
Fixes:
- Add `grid-cols-1` to detail-page grids so the mobile track is
`minmax(0, 1fr)` and can never exceed the container. Applied to Spot,
Shop, Event, NIP-19, Crew and Coach detail pages.
- Add `min-w-0` to their sidebar/main columns so long content can shrink
and truncate instead of forcing the track wider.
- Make the Spot Chat header wrap (`flex-wrap` + `gap-y`) so the trust
filter and channel badge no longer get clipped on narrow phones.
This commit is contained in:
parent
07e844e0fb
commit
571257e5c3
7 changed files with 30 additions and 30 deletions
|
|
@ -206,8 +206,8 @@ export function SpotChat({
|
|||
return (
|
||||
<Card className={cn('flex flex-col overflow-hidden', className)}>
|
||||
<CardHeader className="pb-3 border-b">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<CardTitle className="text-lg flex items-center gap-2">
|
||||
<div className="flex flex-wrap items-center justify-between gap-x-3 gap-y-2">
|
||||
<CardTitle className="text-lg flex flex-wrap items-center gap-2 min-w-0">
|
||||
<MessageCircle className="h-5 w-5 text-orange-500" />
|
||||
Spot Chat
|
||||
<Badge
|
||||
|
|
@ -219,7 +219,7 @@ export function SpotChat({
|
|||
Public
|
||||
</Badge>
|
||||
</CardTitle>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<TrustFilter value={trustLevel} onChange={setTrustLevel} compact />
|
||||
<Badge variant="secondary" className="font-mono text-[10px] gap-1">
|
||||
<Radio className="h-3 w-3" />#{channel}
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ function CoachDetailSkeleton() {
|
|||
<Layout>
|
||||
<div className="container px-4 py-8 max-w-4xl">
|
||||
<Skeleton className="h-6 w-32 mb-6" />
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="md:col-span-2 space-y-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="md:col-span-2 space-y-6 min-w-0">
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<div className="flex items-start gap-4">
|
||||
|
|
@ -220,9 +220,9 @@ export default function CoachDetailPage() {
|
|||
Back to The Lab
|
||||
</Link>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* Main Content */}
|
||||
<div className="md:col-span-2 space-y-6">
|
||||
<div className="md:col-span-2 space-y-6 min-w-0">
|
||||
{/* Confirm-membership prompt (only for listed pending members) */}
|
||||
{isCollective && (
|
||||
<ConfirmMembershipCard
|
||||
|
|
@ -477,7 +477,7 @@ export default function CoachDetailPage() {
|
|||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-6 min-w-0">
|
||||
{/* Contact Card */}
|
||||
<Card className="bg-black/90 border-2 border-[#ccff00]/50">
|
||||
<CardHeader>
|
||||
|
|
|
|||
|
|
@ -230,8 +230,8 @@ export default function CrewDetailPage() {
|
|||
<Layout>
|
||||
<div className="container px-4 py-8 max-w-4xl">
|
||||
<Skeleton className="h-6 w-32 mb-6" />
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="md:col-span-2 space-y-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="md:col-span-2 space-y-6 min-w-0">
|
||||
<Skeleton className="h-48 w-full" />
|
||||
<Skeleton className="h-64 w-full" />
|
||||
</div>
|
||||
|
|
@ -256,9 +256,9 @@ export default function CrewDetailPage() {
|
|||
Back to Crews
|
||||
</Link>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* Main */}
|
||||
<div className="md:col-span-2 space-y-6">
|
||||
<div className="md:col-span-2 space-y-6 min-w-0">
|
||||
{/* Confirm membership prompt (listed pending members only) */}
|
||||
{hasMembers && (
|
||||
<ConfirmMembershipCard
|
||||
|
|
@ -416,7 +416,7 @@ export default function CrewDetailPage() {
|
|||
</div>
|
||||
|
||||
{/* Sidebar — ordered: leadership → who → support → band → connections → founder */}
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-6 min-w-0">
|
||||
{/* Leadership — team leader (founder) + captains (admins) */}
|
||||
<CrewLeadership crew={crew} confirmedAdmins={confirmedAdmins} rolesByPubkey={rolesByPubkey} />
|
||||
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ function EventDetailSkeleton() {
|
|||
return (
|
||||
<Layout>
|
||||
<div className="container px-4 py-8">
|
||||
<div className="grid lg:grid-cols-3 gap-8">
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
<div className="lg:col-span-2 space-y-6 min-w-0">
|
||||
<Skeleton className="aspect-video w-full rounded-xl" />
|
||||
<div className="space-y-4">
|
||||
<Skeleton className="h-10 w-3/4" />
|
||||
|
|
@ -69,7 +69,7 @@ function EventDetailSkeleton() {
|
|||
<Skeleton className="h-24 w-full" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-6 min-w-0">
|
||||
<Skeleton className="h-48 w-full rounded-xl" />
|
||||
<Skeleton className="h-32 w-full rounded-xl" />
|
||||
</div>
|
||||
|
|
@ -321,9 +321,9 @@ export default function EventDetailPage() {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className="grid lg:grid-cols-3 gap-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Main Content */}
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
<div className="lg:col-span-2 space-y-6 min-w-0">
|
||||
{/* ── Immersive hero ── */}
|
||||
<div className="relative overflow-hidden rounded-2xl border border-white/10">
|
||||
{/* Cover */}
|
||||
|
|
@ -504,7 +504,7 @@ export default function EventDetailPage() {
|
|||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-6 min-w-0">
|
||||
{/* Date Card */}
|
||||
<Card className="bg-gradient-to-br from-primary/5 to-accent/5">
|
||||
<CardContent className="pt-6">
|
||||
|
|
|
|||
|
|
@ -399,7 +399,7 @@ function ProfilePage({ pubkey }: { pubkey: string }) {
|
|||
)}
|
||||
|
||||
{/* Profile Info */}
|
||||
<div className="grid lg:grid-cols-3 gap-6">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* Main Content */}
|
||||
<div className="lg:col-span-2 space-y-6 min-w-0">
|
||||
{/* About */}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ function ShopDetailSkeleton() {
|
|||
return (
|
||||
<Layout>
|
||||
<div className="container px-4 py-8">
|
||||
<div className="grid lg:grid-cols-3 gap-8">
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
<div className="lg:col-span-2 space-y-6 min-w-0">
|
||||
<Skeleton className="aspect-video w-full rounded-xl" />
|
||||
<div className="space-y-4">
|
||||
<Skeleton className="h-10 w-3/4" />
|
||||
|
|
@ -67,7 +67,7 @@ function ShopDetailSkeleton() {
|
|||
<Skeleton className="h-24 w-full" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-6 min-w-0">
|
||||
<Skeleton className="h-64 w-full rounded-xl" />
|
||||
<Skeleton className="h-32 w-full rounded-xl" />
|
||||
</div>
|
||||
|
|
@ -210,9 +210,9 @@ export default function ShopDetailPage() {
|
|||
Back to Map
|
||||
</Link>
|
||||
|
||||
<div className="grid lg:grid-cols-3 gap-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Main Content */}
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
<div className="lg:col-span-2 space-y-6 min-w-0">
|
||||
{/* Image Gallery */}
|
||||
{shop.images.length > 0 ? (
|
||||
<div className="aspect-video rounded-xl overflow-hidden bg-muted">
|
||||
|
|
@ -364,7 +364,7 @@ export default function ShopDetailPage() {
|
|||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-6 min-w-0">
|
||||
{/* Contact Card */}
|
||||
{(shop.phone || shop.email || shop.website || shop.instagram) && (
|
||||
<Card className="bg-[#ccff00]/10 border-2 border-[#ccff00]/50">
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ function SpotDetailSkeleton() {
|
|||
return (
|
||||
<Layout>
|
||||
<div className="container px-4 py-8">
|
||||
<div className="grid lg:grid-cols-3 gap-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
<Skeleton className="aspect-video w-full rounded-xl" />
|
||||
<div className="space-y-4">
|
||||
|
|
@ -245,7 +245,7 @@ export default function SpotDetailPage() {
|
|||
Back to Map
|
||||
</Link>
|
||||
|
||||
<div className="grid lg:grid-cols-3 gap-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Main Content */}
|
||||
<div className="lg:col-span-2 space-y-6 min-w-0">
|
||||
{/* Image Gallery - Combines owner photos + community photos */}
|
||||
|
|
@ -756,7 +756,7 @@ export default function SpotDetailPage() {
|
|||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-6 min-w-0">
|
||||
{/* Who's Skating - Only show for regular spots, not shops */}
|
||||
{!isShop && (
|
||||
<WhosSkating
|
||||
|
|
@ -935,7 +935,7 @@ export default function SpotDetailPage() {
|
|||
<CardContent>
|
||||
<Link
|
||||
to={`/${mapperNpub}`}
|
||||
className="flex items-center gap-3 mb-4 group rounded-xl -m-1 p-1 hover:bg-white/5 transition-colors"
|
||||
className="flex items-center gap-3 mb-4 group rounded-xl -m-1 p-1 hover:bg-white/5 transition-colors min-w-0"
|
||||
>
|
||||
<Avatar className="h-12 w-12 border-2 border-[#ccff00]/30">
|
||||
<AvatarImage src={metadata?.picture} alt={displayName} />
|
||||
|
|
|
|||
Loading…
Reference in a new issue