feat(crews): compact focus toggle group + mobile-only Near me
- Replace the eight wrapping filter chips with a single-row ToggleGroup (short labels; full names in tooltip/aria-label). Scrolls horizontally on mobile instead of wrapping to two rows. - Near me is now mobile-only on the Crews page — it was clutter on desktop.
This commit is contained in:
parent
f5ce4002e9
commit
6b925a4fc0
1 changed files with 43 additions and 31 deletions
|
|
@ -5,6 +5,7 @@ import { Layout } from '@/components/Layout';
|
||||||
import { LazyMount } from '@/components/LazyMount';
|
import { LazyMount } from '@/components/LazyMount';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
|
||||||
import { Skeleton } from '@/components/ui/skeleton';
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||||
import { CrewRepBadge, CrewActivityPulse } from '@/components/CrewBadge';
|
import { CrewRepBadge, CrewActivityPulse } from '@/components/CrewBadge';
|
||||||
|
|
@ -18,15 +19,17 @@ import type { CrewActivity } from '@/lib/crewHelpers';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { Users, Plus, Search, MapPin, X, HardHat, Camera, GraduationCap, Sparkles, Navigation, Loader2, Music, Palette, Dumbbell, Film } from 'lucide-react';
|
import { Users, Plus, Search, MapPin, X, HardHat, Camera, GraduationCap, Sparkles, Navigation, Loader2, Music, Palette, Dumbbell, Film } from 'lucide-react';
|
||||||
|
|
||||||
const FOCUS_FILTERS: { key: CrewFocus | 'all'; label: string; icon: typeof Users }[] = [
|
// `label` is the full name (used for the tooltip + screen readers); `short` is
|
||||||
{ key: 'all', label: 'All', icon: Users },
|
// what the compact toggle shows, to keep the filter bar to a single row.
|
||||||
{ key: 'builder', label: CREW_FOCUS_LABELS.builder, icon: HardHat },
|
const FOCUS_FILTERS: { key: CrewFocus | 'all'; label: string; short: string; icon: typeof Users }[] = [
|
||||||
{ key: 'photo', label: CREW_FOCUS_LABELS.photo, icon: Camera },
|
{ key: 'all', label: 'All', short: 'All', icon: Users },
|
||||||
{ key: 'coaching', label: CREW_FOCUS_LABELS.coaching, icon: GraduationCap },
|
{ key: 'builder', label: CREW_FOCUS_LABELS.builder, short: 'DIY', icon: HardHat },
|
||||||
{ key: 'art', label: CREW_FOCUS_LABELS.art, icon: Palette },
|
{ key: 'photo', label: CREW_FOCUS_LABELS.photo, short: 'Photo', icon: Camera },
|
||||||
{ key: 'music', label: CREW_FOCUS_LABELS.music, icon: Music },
|
{ key: 'coaching', label: CREW_FOCUS_LABELS.coaching, short: 'Coaching', icon: GraduationCap },
|
||||||
{ key: 'wellness', label: CREW_FOCUS_LABELS.wellness, icon: Dumbbell },
|
{ key: 'art', label: CREW_FOCUS_LABELS.art, short: 'Art', icon: Palette },
|
||||||
{ key: 'mixed', label: CREW_FOCUS_LABELS.mixed, icon: Sparkles },
|
{ key: 'music', label: CREW_FOCUS_LABELS.music, short: 'Music', icon: Music },
|
||||||
|
{ key: 'wellness', label: CREW_FOCUS_LABELS.wellness, short: 'Physio', icon: Dumbbell },
|
||||||
|
{ key: 'mixed', label: CREW_FOCUS_LABELS.mixed, short: 'Mixed', icon: Sparkles },
|
||||||
];
|
];
|
||||||
|
|
||||||
const FOCUS_BADGE_ICONS: Record<CrewFocus, typeof Users> = {
|
const FOCUS_BADGE_ICONS: Record<CrewFocus, typeof Users> = {
|
||||||
|
|
@ -272,33 +275,42 @@ export default function CrewsPage() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Filters row: focus chips + Near me */}
|
{/* Filters: one compact focus toggle group (scrolls on mobile) */}
|
||||||
<div className="mb-5 flex flex-wrap items-center gap-2">
|
<div className="mb-5 flex items-center gap-2">
|
||||||
{FOCUS_FILTERS.map(({ key, label, icon: Icon }) => {
|
<div className="scroll-container min-w-0 flex-1 overflow-x-auto">
|
||||||
const active = focusFilter === key;
|
<ToggleGroup
|
||||||
return (
|
type="single"
|
||||||
<button
|
value={focusFilter}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
if (v) setFocusFilter(v as CrewFocus | 'all');
|
||||||
|
}}
|
||||||
|
className="inline-flex w-max items-center gap-0.5 rounded-xl border border-white/10 bg-white/[0.04] p-1"
|
||||||
|
>
|
||||||
|
{FOCUS_FILTERS.map(({ key, label, short, icon: Icon }) => (
|
||||||
|
<ToggleGroupItem
|
||||||
key={key}
|
key={key}
|
||||||
type="button"
|
value={key}
|
||||||
onClick={() => setFocusFilter(key)}
|
title={label}
|
||||||
|
aria-label={label}
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-flex items-center gap-1.5 rounded-full border px-3 py-1.5 text-xs font-bold transition-all active:scale-95',
|
'h-7 shrink-0 gap-1 rounded-lg px-2 text-xs font-bold text-gray-300 transition-colors',
|
||||||
active
|
'hover:bg-white/5 hover:text-teal-300',
|
||||||
? 'border-teal-500 bg-teal-500 text-black'
|
'data-[state=on]:bg-teal-500 data-[state=on]:text-black data-[state=on]:hover:bg-teal-500 data-[state=on]:hover:text-black',
|
||||||
: 'border-white/10 bg-white/5 text-gray-300 hover:border-teal-500/40 hover:text-teal-300',
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Icon className="h-3.5 w-3.5" />
|
<Icon className="h-3.5 w-3.5" />
|
||||||
{label}
|
{short}
|
||||||
</button>
|
</ToggleGroupItem>
|
||||||
);
|
))}
|
||||||
})}
|
</ToggleGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Near me — mobile only; on desktop it was just clutter in this bar. */}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleNearMe}
|
onClick={handleNearMe}
|
||||||
className={cn(
|
className={cn(
|
||||||
'ml-auto inline-flex items-center gap-1.5 rounded-full border px-3 py-1.5 text-xs font-bold transition-all active:scale-95',
|
'inline-flex shrink-0 items-center gap-1.5 rounded-full border px-3 py-1.5 text-xs font-bold transition-all active:scale-95 sm:hidden',
|
||||||
nearMe
|
nearMe
|
||||||
? 'border-orange-500 bg-orange-500 text-black'
|
? 'border-orange-500 bg-orange-500 text-black'
|
||||||
: 'border-white/10 bg-white/5 text-gray-300 hover:border-orange-500/40 hover:text-orange-300',
|
: 'border-white/10 bg-white/5 text-gray-300 hover:border-orange-500/40 hover:text-orange-300',
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue