Fix mobile league settings: prevent sports scroll and remove completion checkmarks

- Add overflow-hidden to sport label text span so flex truncation is properly contained
- Add min-w-0 to SettingsSection header inner flex item to prevent title/description overflow
- Remove completion check marks from mobile grid nav buttons (league settings has no completion concept)
- Remove "X of Y set" counter from mobile nav header
- Remove isComplete field from SettingsGridSection type and all data

https://claude.ai/code/session_01T7iTb9YZLuWJFtKV753tdB
This commit is contained in:
Claude 2026-05-07 03:55:13 +00:00
parent d342f1ad25
commit c50386ed4c
No known key found for this signature in database
4 changed files with 13 additions and 26 deletions

View file

@ -1,6 +1,6 @@
import type { ComponentType } from "react";
import type { LucideProps } from "lucide-react";
import { ArrowLeft, Check } from "lucide-react";
import { ArrowLeft } from "lucide-react";
import { cn } from "~/lib/utils";
type SettingsNavSection = {
@ -11,28 +11,22 @@ type SettingsNavSection = {
export type SettingsGridSection = SettingsNavSection & {
icon: ComponentType<LucideProps>;
subtitle: string;
isComplete: boolean;
isDanger?: boolean;
};
export function SettingsMobileGridNav({
sections,
completedCount,
onSectionChange,
}: {
sections: readonly SettingsGridSection[];
completedCount: number;
onSectionChange: (sectionId: string) => void;
}) {
return (
<div className="mb-5 lg:hidden">
<div className="mb-3 flex items-center justify-between">
<div className="mb-3">
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Manage
</p>
<p className="text-xs text-muted-foreground">
{completedCount} of {sections.length} set
</p>
</div>
<div className="grid grid-cols-2 gap-3">
{sections.map((section) => (
@ -41,15 +35,10 @@ export function SettingsMobileGridNav({
type="button"
onClick={() => onSectionChange(section.id)}
className={cn(
"relative flex cursor-pointer flex-col gap-3 rounded-xl border bg-card p-4 text-left transition-colors hover:border-primary/40 active:scale-[0.98]",
"flex cursor-pointer flex-col gap-3 rounded-xl border bg-card p-4 text-left transition-colors hover:border-primary/40 active:scale-[0.98]",
section.isDanger && "border-destructive/40"
)}
>
{section.isComplete && (
<div className="absolute right-3 top-3 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-primary-foreground">
<Check className="h-3 w-3" strokeWidth={3} />
</div>
)}
<div
className={cn(
"flex h-10 w-10 items-center justify-center rounded-lg",

View file

@ -50,7 +50,7 @@ export function SettingsSection({
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
<div className="flex items-start gap-3">
<GradientIcon icon={icon} className="mt-1 h-6 w-6 shrink-0" />
<div>
<div className="min-w-0">
<h2 className="text-2xl font-bold tracking-tight sm:text-3xl">{title}</h2>
<p className="mt-2 max-w-2xl text-sm text-muted-foreground">{description}</p>
</div>

View file

@ -72,7 +72,7 @@ export function SportsSection({
disabled={!canEditSports}
/>
<SportIcon sport={ss.sport} />
<span className="min-w-0 flex-1">
<span className="min-w-0 flex-1 overflow-hidden">
<span className="block truncate font-medium">
{ss.sport.slug === BRACKT_SLUG ? "Brackt" : `${ss.sport.name} - ${ss.name} (${ss.year})`}
</span>

View file

@ -307,16 +307,15 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone
};
const sectionGridData: SettingsGridSection[] = [
{ id: "league-basics", label: "League Basics", icon: Shield, subtitle: "Name, teams, join", isComplete: true },
{ id: "draft-setup", label: "Draft Settings", icon: Swords, subtitle: "Format, timing, rounds", isComplete: !!(draftDate && draftTime) },
{ id: "draft-order", label: "Draft Order", icon: ListOrdered, subtitle: "Pick order, randomize", isComplete: draftOrderSet },
{ id: "sports", label: "Sports", icon: Trophy, subtitle: `${selectedSports.size} season${selectedSports.size !== 1 ? "s" : ""} selected`, isComplete: selectedSports.size > 0 },
{ id: "scoring", label: "Scoring", icon: TrendingUp, subtitle: "Place values, ties", isComplete: true },
{ id: "notifications", label: "Notifications", icon: Bell, subtitle: "Discord alerts", isComplete: !!league.discordWebhookUrl },
{ id: "people", label: "People", icon: Users, subtitle: `${teamsWithOwners} of ${teamCountValue} teams`, isComplete: false },
{ id: "history-danger", label: "History & Danger", icon: AlertTriangle, subtitle: "Audit log, dissolve", isComplete: false, isDanger: true },
{ id: "league-basics", label: "League Basics", icon: Shield, subtitle: "Name, teams, join" },
{ id: "draft-setup", label: "Draft Settings", icon: Swords, subtitle: "Format, timing, rounds" },
{ id: "draft-order", label: "Draft Order", icon: ListOrdered, subtitle: "Pick order, randomize" },
{ id: "sports", label: "Sports", icon: Trophy, subtitle: `${selectedSports.size} season${selectedSports.size !== 1 ? "s" : ""} selected` },
{ id: "scoring", label: "Scoring", icon: TrendingUp, subtitle: "Place values, ties" },
{ id: "notifications", label: "Notifications", icon: Bell, subtitle: "Discord alerts" },
{ id: "people", label: "People", icon: Users, subtitle: `${teamsWithOwners} of ${teamCountValue} teams` },
{ id: "history-danger", label: "History & Danger", icon: AlertTriangle, subtitle: "Audit log, dissolve", isDanger: true },
];
const completedSectionCount = sectionGridData.filter((s) => s.isComplete).length;
return (
<div className="container mx-auto max-w-5xl px-4 py-6 sm:py-8">
@ -328,7 +327,6 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone
<div className="lg:hidden">
<SettingsMobileGridNav
sections={sectionGridData}
completedCount={completedSectionCount}
onSectionChange={(id) => handleSectionChange(id as SettingsSectionId, { mobile: true })}
/>
</div>