Fix Grid Line Layout And Studio Project Page State Bugs In Supabase Apps
Resolves three UI and state issues: incorrect last-child CSS selector causing visible extra grid line in learn app, stale project name input due to React defaultValue without key, and potential memory leak from uncleared timeout in lite-studio project page.
Three independent root causes: (1) misuse of Tailwind's last:hidden on grid lines but content div becomes last child; (2) React defaultValue only applies on initial mount without key forcing remount; (3) setTimeout not stored or cleared, causing state update after unmount.
1. Open learn app home page and observe 13th vertical grid line remains visible instead of hidden. 2. Open lite-studio project page, note project name, switch to another project, input value stays old. 3. Click Refresh Status button then navigate away within 2 seconds, observe memory leak warning or state update on unmounted component.
Fixing Code Block
// apps/learn/app/(app)/page.tsx
// In the Home component, replace the grid line map loop with:
{Array.from({ length: 13 }).map((_, i) => (
<div
key={i}
className={`absolute top-0 bottom-0 w-px bg-border/30 z-10 ${i === 0 || i === 12 ? 'hidden' : ''}`}
/>
))}
// apps/lite-studio/app/routes/projects.$ref.tsx
// Add key to the Input:
<Input key={ref} id="project-name" placeholder="my-project" defaultValue={ref} />
// Manage setTimeout with useRef and clear on unmount:
import { useEffect, useRef } from 'react';
export default function ProjectPage() {
// ... existing state and logic
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);
const handleRefresh = () => {
setLoading(true);
if (timeoutRef.current) clearTimeout(timeoutRef.current);
timeoutRef.current = setTimeout(() => setLoading(false), 2000);
};
// ... rest of component with updated button onClick={handleRefresh}
}
The grid line fix replaces fragile CSS :last-child with explicit index-based hiding, ensuring the 13th line is hidden regardless of DOM order. Adding key={ref} to the input forces React to remount the element with the new defaultValue when the route parameter changes. The timeout is now stored in a useRef and cleared both on unmount via useEffect cleanup and before setting a new timeout to prevent stale updates.
Edge Case Audit
Hardcoding index 12 in the grid line fix may break if the number of lines changes; consider deriving from a constant. Adding key to Input forces remount and will discard any unsaved user input if the project changes mid-edit; ensure this is acceptable or add confirmation. The timeout fix resets the timer on repeated clicks; verify this matches intended behavior (debounce vs. throttle). Rollback recommendation: if any fix introduces regressions, revert the specific file changes individually; they are isolated and can be rolled back without affecting other functionality.