Update the theme - #22
Conversation
…n styles in PriorityRating
…DraggableTask skeleton rendering
WalkthroughReworks the boards UI to a virtualized drag/drop surface with scroll shadows and a new loading component; adds useScrollShadow hook; switches default theme to light and font to Space Grotesk; many UI/dark-mode styling tweaks; removes Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Browser as Browser (UI)
participant TodoBoards as TodoBoards component
participant LiveDB as Live Query / DB
participant Virtualizer as Virtualizer
participant Sortable as SortableContext (DragLayer)
Browser->>TodoBoards: mount(projectId)
TodoBoards->>LiveDB: subscribe to boards & items
LiveDB-->>TodoBoards: stream items
TodoBoards->>Virtualizer: provide visible items & layout
Virtualizer-->>Browser: render TaskBase items
Browser->>Sortable: pointer down / start drag
Sortable->>Virtualizer: request overlay render for dragged item
Virtualizer-->>Sortable: provide overlay (TaskBase with wiggle)
Browser->>Sortable: drop at target
Sortable->>LiveDB: commit reorder payload
LiveDB-->>TodoBoards: updated items stream
TodoBoards->>Virtualizer: re-render with new order
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
src/components/TodoBoardsLoading.tsx (1)
28-37: Consider responsive layout for mobile viewports.The
grid-cols-3class creates a fixed 3-column layout. On smaller screens, this may cause content to be cramped or overflow. Consider adding responsive breakpoints (e.g.,grid-cols-1 md:grid-cols-2 lg:grid-cols-3) if the loading skeleton should match the responsive behavior of the actualTodoBoardscomponent.🔎 Suggested responsive fix
export function TodoBoardsLoading() { return ( <div className="flex-1 min-h-0"> - <div className="grid grid-cols-3 gap-4 h-full min-h-0"> + <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 h-full min-h-0"> <BoardSkeleton taskCount={2} /> <BoardSkeleton taskCount={3} /> <BoardSkeleton taskCount={2} /> </div> </div> ); }src/components/Header.tsx (2)
14-37: Consider consistentrelattributes for external links.The external links use different
relvalues:rel="noreferrer"on line 17 vsrel="noopener"on line 34. For consistency and security best practices, consider usingrel="noopener noreferrer"on both links.🔎 Suggested fix
<a href="https://fulop.dev" target="_blank" - rel="noreferrer" + rel="noopener noreferrer" className="group/fuko-link cursor-pointer transition-colors flex items-center gap-2" ><a target="_blank" href="https://tanstack.com/db/latest/docs/overview" className="text-primary flex items-center cursor-pointer underline decoration-wavy hover:opacity-80" - rel="noopener" + rel="noopener noreferrer" >
20-24: External avatar image dependency.The avatar is loaded directly from GitHub's CDN. While GitHub avatars are highly available, consider self-hosting the image or adding a fallback for improved reliability and faster load times.
src/components/TodoBoards.tsx (2)
53-57: Consider deriving board names from schema.The
BoardNameenum hardcodes board names that likely exist in your database schema. If board names change in the schema, this enum will become stale.Alternative approach using schema types
Consider importing board name constants from your schema or using the actual
board.namevalues directly to maintain a single source of truth:-enum BoardName { - Todo = "Todo", - InProgress = "In Progress", - Done = "Done", -} // In Board component -{board.name === BoardName.Done ? ( +{board.name === "Done" ? (Or if you have schema constants:
import { BOARD_NAMES } from "@/db/schema"; {board.name === BOARD_NAMES.Done ? (
163-170: Consider dynamic skeleton height for better drag feedback.The skeleton placeholder uses a hardcoded
h-[180px], which may not match the actual height of tasks with varying content lengths. This could cause visual jumps or inconsistent spacing during drag operations.Alternative approach using ref measurement
Consider measuring the actual task height before drag starts:
function DraggableTask({ task }: { task: TodoItemRecord }) { const taskRef = useRef<HTMLDivElement>(null); const [taskHeight, setTaskHeight] = useState<number | null>(null); const { attributes, listeners, setNodeRef, isDragging } = useSortable({ id: task.id, }); useEffect(() => { if (taskRef.current) { setTaskHeight(taskRef.current.offsetHeight); } }, []); if (isDragging && taskHeight) { return ( <div ref={setNodeRef} className="bg-skeleton rounded-lg mb-2 animate-skeleton-pulse" style={{ height: `${taskHeight}px` }} /> ); } return ( <TaskBase task={task} ref={(node) => { setNodeRef(node); taskRef.current = node; }} {...attributes} {...listeners} className="cursor-grab" /> ); }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (18)
AGENTS.mdsrc/components/ConfigureDB.tsxsrc/components/EditableProjectDetails.tsxsrc/components/FakeProgressIndicator.tsxsrc/components/Header.tsxsrc/components/NetworkLatencyConfigurator.tsxsrc/components/PriorityRating.tsxsrc/components/TodoBoards.tsxsrc/components/TodoBoardsLoading.tsxsrc/components/theme-provider.tsxsrc/components/ui/badge.tsxsrc/components/ui/button.tsxsrc/components/ui/dropdown-menu.tsxsrc/components/ui/input.tsxsrc/components/ui/skeleton.tsxsrc/hooks/use-scroll-shadow.tssrc/routes/__root.tsxsrc/styles.css
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-19T21:20:23.301Z
Learnt from: CR
Repo: fulopkovacs/trytanstackdb.com PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:20:23.301Z
Learning: Applies to src/route/__root.tsx : The root route is located at `src/route/__root.tsx` in a TanStack Start project
Applied to files:
src/routes/__root.tsxAGENTS.md
📚 Learning: 2025-12-19T21:20:23.301Z
Learnt from: CR
Repo: fulopkovacs/trytanstackdb.com PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:20:23.301Z
Learning: The project uses TanStack Start as the framework with React, TanStack Router, shadcn/ui for UI, and Tailwind CSS for styling
Applied to files:
AGENTS.md
🧬 Code graph analysis (9)
src/components/NetworkLatencyConfigurator.tsx (1)
src/components/mode-toggle.tsx (2)
ModeToggle(11-39)setTheme(28-28)
src/hooks/use-scroll-shadow.ts (1)
src/components/ui/scroll-area.tsx (2)
ScrollArea(6-33)ScrollBar(35-60)
src/components/TodoBoardsLoading.tsx (1)
src/components/ui/skeleton.tsx (1)
Skeleton(13-13)
src/components/FakeProgressIndicator.tsx (1)
src/components/ui/progress.tsx (1)
Progress(5-26)
src/components/ui/skeleton.tsx (1)
src/lib/utils.ts (1)
cn(4-6)
src/components/theme-provider.tsx (1)
src/components/mode-toggle.tsx (1)
setTheme(28-28)
src/components/PriorityRating.tsx (2)
src/components/ui/dropdown-menu.tsx (4)
DropdownMenu(240-240)DropdownMenuTrigger(242-242)DropdownMenuContent(243-243)DropdownMenuItem(246-246)src/components/ui/button.tsx (1)
Button(63-63)
src/components/Header.tsx (2)
src/components/ui/sidebar.tsx (2)
SidebarTrigger(718-718)Sidebar(160-260)src/components/tutorial/TutorialWindow.tsx (1)
FloatingWindowHeader(16-32)
src/components/ConfigureDB.tsx (2)
src/components/ui/badge.tsx (1)
Badge(48-48)src/lib/utils.ts (1)
cn(4-6)
🪛 GitHub Actions: CI/CD
src/components/EditableProjectDetails.tsx
[error] 93-93: TS6133: 'LoadingEditableProjects' is declared but its value is never read.
🔇 Additional comments (23)
src/components/ui/dropdown-menu.tsx (1)
75-75: LGTM: Dark mode focus styling enhancement.The addition of
dark:focus:bg-borderanddark:focus:text-currentprovides proper focus state styling for dark mode, aligning with the broader theming updates in this PR.AGENTS.md (1)
47-47: LGTM: Documentation updated to reflect Tailwind CSS v4.The version annotation accurately reflects the Tailwind CSS version in use, helping maintain clear technical documentation.
src/components/ui/input.tsx (1)
11-11: LGTM: Selection styling updated to use accent tokens.The change from
selection:bg-primarytoselection:bg-accentaligns with the new theming system and maintains visual consistency across the UI.src/components/PriorityRating.tsx (2)
1-23: LGTM: Icon set updated with improved visual hierarchy.The replacement of
CircleIconwithSkullIconand the updated icon styling (with muted/destructive colors) provides clearer visual indication of priority levels.
41-80: Event propagation blocking does not affect keyboard navigation or accessibility.The
stopPropagation()calls target pointer and click events only—not keyboard events. Radix UI's DropdownMenu (which shadcn/ui wraps) handles all keyboard navigation (Enter, Space, Arrow keys, Esc, etc.) internally and maintains full WAI-ARIA support independent of pointer/click propagation. Keyboard accessibility is unaffected.Likely an incorrect or invalid review comment.
src/routes/__root.tsx (1)
37-49: LGTM: Font loading with performance optimizations.The Space Grotesk font is loaded with proper
preconnecthints for Google Fonts, which is a performance best practice. The Google Fonts URL includesdisplay=swap, ensuring text remains visible during font load.src/components/FakeProgressIndicator.tsx (1)
26-26: LGTM: Progress indicator background updated to match skeleton theming.The change to
bg-skeletonmaintains visual consistency with other loading states in the application, providing a unified skeleton/loading appearance.src/components/ui/button.tsx (1)
14-23: Button variants are properly implemented and in use.The new
emptyandtutorialvariants are actively used throughout the codebase (inPriorityRating.tsxandTutorialWindow.tsxrespectively). Dark mode styling enhancements are present across multiple variants, and the styling is consistent with the broader theme.src/components/ui/skeleton.tsx (1)
7-7: The Tailwind classesbg-skeletonandanimate-skeleton-pulseare not configured and will not be generated.While the CSS custom properties
--skeletonand--animate-skeleton-pulseare defined insrc/styles.css, they are not wired to Tailwind class names. Tailwind v4 requires explicit configuration in atailwind.config.tsfile to extend the theme and map custom properties to classes. Without this configuration, the classes used in line 7 (bg-skeleton animate-skeleton-pulse) will be undefined and non-functional. Either add atailwind.config.tsfile with the theme extensions, or use the CSS custom properties directly via inline styles or CSS classes.Likely an incorrect or invalid review comment.
src/components/ui/badge.tsx (1)
20-21: LGTM!The new
neutralvariant follows the established pattern of other badge variants and uses consistent design tokens (bg-muted,text-muted-foreground). The hover state is appropriately scoped to anchor elements.src/components/ConfigureDB.tsx (1)
46-53: LGTM!The Badge styling update using
variant="outline"combined withbg-mutedis a clean approach since the outline variant doesn't define a background. The added border on the indicator dot improves visual definition.src/components/theme-provider.tsx (1)
8-8: LGTM!The default theme change from "dark" to "light" aligns with the PR's visual overhaul objectives. The change correctly propagates through
UserThemeSchema,AppThemeSchema, server-side fallbacks, and the theme script.src/components/NetworkLatencyConfigurator.tsx (1)
56-62: LGTM!The updated color scheme improves contrast by using more saturated colors in light mode (green-500, orange-400) while keeping lighter variants for dark mode readability. Using
text-destructivefor both modes correctly relies on the theme's CSS variable system.src/components/EditableProjectDetails.tsx (1)
142-177: LGTM!The conditional rendering logic correctly handles three states: API 404 error, no project found, and the default loading/data state. The inline skeleton approach provides smooth loading transitions.
src/hooks/use-scroll-shadow.ts (1)
15-69: LGTM!Well-implemented scroll shadow hook with:
- Passive scroll listener for performance
- ResizeObserver for container size changes
- MutationObserver for content changes
- Proper cleanup on unmount
- 1px threshold to handle sub-pixel rendering edge cases
The empty dependency array for
updateScrollShadowsis correct since it only references the stablescrollRef.src/styles.css (4)
11-12: Font change looks good.The switch from Clash Grotesk to Space Grotesk aligns with the PR's visual overhaul goals. Ensure the font is properly preloaded in the root route to avoid layout shifts.
23-90: OKLCH color system implementation looks correct.The new OKLCH-based color palette with skeleton and success tokens follows Tailwind v4 conventions and supports the visual overhaul goals.
370-391: Animation definitions are well-structured.The wiggle and skeleton-pulse animations effectively support the drag-and-drop feedback and loading state UI enhancements.
405-406: Letter spacing application looks good.The tracking-normal token properly integrates with the new typography system.
src/components/TodoBoards.tsx (4)
22-42: Import additions support the new UI features.The new icons, hooks, and components properly support the Card-based refactor and loading states.
267-323: Board layout structure is well-organized.The Card-based board layout with icon mapping, scroll shadows, and drop indicators creates a cohesive drag-and-drop experience.
520-528: Loading state implementation is clean.The conditional rendering properly shows the TodoBoardsLoading skeleton during data fetch, improving perceived performance.
530-532: Drag overlay with animation enhances UX.The wiggle animation on the dragged task provides excellent visual feedback during drag operations.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/collections/todoItems.ts (1)
58-63: Fix Prettier formatting to pass CI/CD.The pipeline indicates a formatting mismatch on these lines. Run the formatter to resolve the CI/CD failure.
Run the following command to fix the formatting:
prettier --write src/collections/todoItems.tssrc/components/EditableProjectDetails.tsx (2)
76-76: Fix typo: "APi" should be "API".🔎 Proposed fix
- We use a service worker to simulate the backend APi. Sometimes it's + We use a service worker to simulate the backend API. Sometimes it's
113-113: Fix typo in comment: missing opening parenthesis.🔎 Proposed fix
- Sometimes typically after a hard refresh), the service worker + Sometimes (typically after a hard refresh), the service worker
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.github/workflows/main.ymlsrc/collections/todoItems.tssrc/components/EditableProjectDetails.tsx
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-19T21:20:23.301Z
Learnt from: CR
Repo: fulopkovacs/trytanstackdb.com PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:20:23.301Z
Learning: Use `pnpm run test` for running tests
Applied to files:
.github/workflows/main.yml
📚 Learning: 2025-12-19T21:20:23.301Z
Learnt from: CR
Repo: fulopkovacs/trytanstackdb.com PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:20:23.301Z
Learning: Use `pnpm typecheck` for type checking
Applied to files:
.github/workflows/main.yml
📚 Learning: 2025-12-19T21:20:23.301Z
Learnt from: CR
Repo: fulopkovacs/trytanstackdb.com PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:20:23.301Z
Learning: Use `pnpm lint` for linting code
Applied to files:
.github/workflows/main.yml
🧬 Code graph analysis (2)
src/collections/todoItems.ts (1)
src/components/CreateOrEditTodoItems.tsx (3)
newItemData(45-51)newItemData(32-44)project(39-43)
src/components/EditableProjectDetails.tsx (3)
src/utils/highlight-collection-related-info.tsx (1)
HighlightWrapper(6-28)src/components/ui/skeleton.tsx (1)
Skeleton(13-13)src/local-api/api.projects.ts (1)
updatedData(28-90)
🪛 GitHub Actions: CI/CD
src/collections/todoItems.ts
[error] 58-63: Prettier formatting mismatch detected. The formatter would format this file differently. Run 'prettier --write' to fix code style issues in this file (or run the full formatting check again).
🔇 Additional comments (4)
src/collections/todoItems.ts (1)
58-78: No external imports exist—this change is correct as-is.The
insertTodoItemfunction is appropriately scoped as internal-only. It is not imported by any files, includingCreateOrEditTodoItems.tsx, and is only used internally within thetodoItemsCollection'sonInsertcallback. Removing theexportkeyword is the correct design decision.Likely an incorrect or invalid review comment.
.github/workflows/main.yml (1)
54-55: Good addition of code quality tooling.Adding Knip to catch unused files, dependencies, and exports is a solid practice, especially for a large visual overhaul PR where refactoring may leave unused code behind. The tool is properly configured with well-defined entry points and dependency rules, and its placement in the workflow after type checking and before tests follows a logical sequence.
src/components/EditableProjectDetails.tsx (2)
18-68: LGTM! Clean form handling.The EditProjectNamePopover component correctly handles project name updates with proper validation and popover state management.
131-166: Excellent refactoring! Clean three-branch rendering logic.The reworked rendering flow clearly separates API errors, missing projects, and normal content display. The inline loading skeleton approach is more maintainable than the previous separate loading component. The logic correctly handles all states: API 404 errors, ready-but-no-project cases, and loading-vs-loaded states.
🚀 Preview DeploymentStatus: ✅ Ready! Preview URL: Open Preview Commit: Built and deployed successfully |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/components/TodoBoards.tsx (2)
53-57: Consider using the enum in the type system for better type safety.The
BoardNameenum is defined but not used to constrain theBoardRecord.nametype. This means the string comparisons on lines 242-248 aren't type-safe, and mismatches between database values and enum values will fail silently at runtime.Consider either:
- Updating the schema to use the enum type:
boardsTableshould havename: text('name').$type<BoardName>()- Or adding runtime validation when loading boards to ensure names match expected enum values
157-180: Consider extracting the hardcoded height to a constant.The skeleton height
h-[180px](line 166) is also used asitemSize={180}in the Virtualizer (line 276). If these values get out of sync, virtualization will break. Consider extracting this to a named constant at the module level:const TASK_ITEM_HEIGHT = 180;Then use it in both places for maintainability.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/collections/todoItems.tssrc/components/TodoBoards.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
src/components/TodoBoards.tsx (9)
src/lib/utils.ts (1)
cn(4-6)src/components/ui/card.tsx (5)
Card(85-85)CardHeader(86-86)CardTitle(88-88)CardDescription(90-90)CardFooter(87-87)src/components/PriorityRating.tsx (1)
PriorityRatingPopup(25-82)src/components/CreateOrEditTodoItems.tsx (1)
CreateOrEditTodoItems(19-143)src/components/ui/button.tsx (1)
Button(63-63)src/db/schema.ts (2)
TodoItemRecord(72-72)BoardRecord(52-52)src/hooks/use-scroll-shadow.ts (1)
useScrollShadow(15-70)src/components/ui/badge.tsx (1)
Badge(48-48)src/components/TodoBoardsLoading.tsx (1)
TodoBoardsLoading(28-38)
src/collections/todoItems.ts (1)
src/local-api/api.todo-items.ts (1)
TodoItemCreateDataType(16-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy Preview
🔇 Additional comments (5)
src/collections/todoItems.ts (1)
58-58: No external imports ofinsertTodoItemexist—the export removal is safe.Verification confirms that
insertTodoItemis not imported or used by any other files in the codebase. The function is only used internally within this module (line 85 in theonInserthook). Removing theexportkeyword is not a breaking change.src/components/TodoBoards.tsx (4)
110-155: LGTM!The refactored
TaskBasecomponent properly integrates Card components with a clean header/description/footer layout. The grip indicator, priority rating, and edit functionality are well-implemented. The event handling correctly prevents drag interference with interactive elements.
265-291: LGTM! Virtualizer implementation is correct.The refactored Board component properly addresses the previous review feedback by using
Virtualizerin a custom scroll container with a controlled ref. The callback ref pattern on lines 266-269 correctly manages both the droppable ref and the scroll shadow ref. The virtualization with drop indicators is well-implemented.
276-290: Drop indicator logic is correct.The implementation properly shows drop indicators before items when hovering over them, and after the last item when dropping at the end of a column. The conditional logic ensures indicators only appear once and in the correct position.
493-506: LGTM!The conditional rendering for loading states and the drag overlay implementation are well-executed. The use of
TodoBoardsLoadingas a dedicated loading component and the wiggle animation during drag provide a polished user experience.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/components/TodoBoards.tsx (2)
53-57: Consider strengthening type safety for board names.The
BoardNameenum is compared via string equality withboard.nameat runtime (lines 257-263), but there's no type-level constraint ensuring database values match the enum. Ifboard.namedoesn't match exactly, the code silently falls back toLayoutListIcon.To prevent potential mismatches, consider either:
- Constraining the
BoardRecordtype to use theBoardNameenum, or- Using a mapping object instead of inline conditionals:
const BOARD_ICONS: Record<BoardName, typeof LayoutListIcon> = { [BoardName.Done]: CircleCheckBigIcon, [BoardName.InProgress]: LoaderIcon, [BoardName.Todo]: LayoutListIcon, };Then use:
{React.createElement(BOARD_ICONS[board.name as BoardName] ?? LayoutListIcon)}Also applies to: 257-263
167-171: Consider optimizing the height measurement effect.The
useEffectwithout a dependency array runs after every render, potentially causing unnecessary measurements. While React's state batching prevents infinite loops, this could be optimized to measure only when needed:🔎 Suggested optimization
useEffect(() => { if (taskRef.current) { setMeasuredHeight(taskRef.current.offsetHeight); } - }); + }, []);Alternatively, use a
ResizeObserverto remeasure only when the element's size actually changes.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/components/TodoBoards.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-24T15:25:07.106Z
Learnt from: fulopkovacs
Repo: fulopkovacs/trytanstackdb.com PR: 22
File: src/components/TodoBoards.tsx:63-81
Timestamp: 2025-12-24T15:25:07.106Z
Learning: In Tailwind CSS v4, prefer canonical classes using bg-linear-to-* (e.g., bg-linear-to-b, bg-linear-to-t, bg-linear-to-r) over the older bg-gradient-to-* syntax. This aligns with Tailwind LSP's suggestCanonicalClasses rule. Apply across TSX files (e.g., src/components/*.tsx); replace occurrences of bg-gradient-to-* with the corresponding bg-linear-to-* equivalents and verify gradients visually.
Applied to files:
src/components/TodoBoards.tsx
🧬 Code graph analysis (1)
src/components/TodoBoards.tsx (4)
src/components/CreateOrEditTodoItems.tsx (1)
CreateOrEditTodoItems(19-143)src/db/schema.ts (2)
TodoItemRecord(72-72)BoardRecord(52-52)src/hooks/use-scroll-shadow.ts (1)
useScrollShadow(15-70)src/components/TodoBoardsLoading.tsx (1)
TodoBoardsLoading(28-38)
🔇 Additional comments (5)
src/components/TodoBoards.tsx (5)
65-83: LGTM!The
ScrollShadowcomponent correctly uses Tailwind v4's canonical gradient syntax (bg-linear-to-b,bg-linear-to-t) with smooth opacity transitions for scroll indicators.
112-157: LGTM!The refactored
TaskBasecomponent correctly implementsforwardRef, properly structures the Card with semantic sections (Header/Footer), and includes appropriate event handlers to prevent drag interference when editing.
197-323: LGTM - excellent refactor!The
Boardcomponent successfully integrates:
Virtualizerfor efficient renderinguseScrollShadowfor scroll indicators- Complex drop indicator logic handling edge cases (empty columns, end-of-list)
- Proper ref forwarding using callback refs
The migration from the previous implementation is well-executed and addresses past feedback about VList usage.
519-527: LGTM!The loading state is properly handled with the dedicated
TodoBoardsLoadingcomponent, maintaining the same 3-column grid layout for a smooth visual transition.
529-531: Theanimate-wiggleclass is properly defined insrc/styles.csswith the complete animation keyframes and CSS custom property configuration. No action needed.
… measure the height of a dragabble task
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/components/TodoBoards.tsx (1)
167-177: Consider using ResizeObserver for height measurement.The
useEffectwithout dependencies runs on every render to capture height changes. While the comment explains this is intentional, it could impact performance with many tasks. AResizeObserverwould measure only when the element's size actually changes:Alternative implementation with ResizeObserver
- // Measure height after the element is rendered - useEffect( - () => { - if (taskRef.current) { - setMeasuredHeight(taskRef.current.offsetHeight); - } - }, - /* - No dependency array: remeasures on every render - to capture dynamic content changes (edits, etc.) - */ - ); + // Measure height when element size changes + useEffect(() => { + const element = taskRef.current; + if (!element) return; + + const observer = new ResizeObserver(() => { + setMeasuredHeight(element.offsetHeight); + }); + + observer.observe(element); + return () => observer.disconnect(); + }, []);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/components/TodoBoards.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-24T15:25:07.106Z
Learnt from: fulopkovacs
Repo: fulopkovacs/trytanstackdb.com PR: 22
File: src/components/TodoBoards.tsx:63-81
Timestamp: 2025-12-24T15:25:07.106Z
Learning: In Tailwind CSS v4, prefer canonical classes using bg-linear-to-* (e.g., bg-linear-to-b, bg-linear-to-t, bg-linear-to-r) over the older bg-gradient-to-* syntax. This aligns with Tailwind LSP's suggestCanonicalClasses rule. Apply across TSX files (e.g., src/components/*.tsx); replace occurrences of bg-gradient-to-* with the corresponding bg-linear-to-* equivalents and verify gradients visually.
Applied to files:
src/components/TodoBoards.tsx
🧬 Code graph analysis (1)
src/components/TodoBoards.tsx (5)
src/components/PriorityRating.tsx (1)
PriorityRatingPopup(25-82)src/components/CreateOrEditTodoItems.tsx (1)
CreateOrEditTodoItems(19-143)src/db/schema.ts (2)
TodoItemRecord(72-72)BoardRecord(52-52)src/hooks/use-scroll-shadow.ts (1)
useScrollShadow(15-70)src/components/TodoBoardsLoading.tsx (1)
TodoBoardsLoading(28-38)
🔇 Additional comments (3)
src/components/TodoBoards.tsx (3)
65-83: Correct use of Tailwind v4 gradient classes.The
bg-linear-to-bandbg-linear-to-tclasses are the correct canonical syntax for Tailwind CSS v4, as confirmed by the Tailwind LSP'ssuggestCanonicalClassesrule. The ScrollShadow implementation is clean and uses proper conditional opacity transitions.Based on learnings, Tailwind v4 prefers
bg-linear-to-*over the olderbg-gradient-to-*syntax.
286-292: Excellent implementation of custom scroll container.The Board component now uses the recommended pattern with a custom scroll container (lines 286-292) and Virtualizer, addressing the previous review concern about VList not exposing its internal scroll container. The callback ref correctly sets both the droppable node and scroll ref, giving you explicit control over the scroll element for the
useScrollShadowhook.
522-541: Clean drag-and-drop implementation with good UX.The TodoBoards component orchestrates the drag-and-drop flow well:
- Conditional rendering with
TodoBoardsLoadingprovides good loading state UXDragOverlaywith the wiggle animation gives clear visual feedback- The paced mutations with debouncing (line 335) optimize backend calls while maintaining responsive UI
The overall architecture is solid and the visual overhaul integrates smoothly with the existing functionality.
This is a huge visual overhaul attempting to make the whole app more appealing.
Summary by CodeRabbit
New Features
Style & Visual Improvements
Bug Fixes / UX
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.