Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
926edd5
Do not use font-extrabold anywhere
fulopkovacs Dec 21, 2025
b363f23
Load the theme from tweakcn
fulopkovacs Dec 21, 2025
d50828a
Refactor drop indicator into ShowDropIndicator component in TodoBoards
fulopkovacs Dec 21, 2025
b29063a
Remove sidebar background from Board and update muted foreground color
fulopkovacs Dec 21, 2025
bce117c
Update the drop indicator everywhere
fulopkovacs Dec 21, 2025
79b6101
Rename ShowDropIndicator to DropIndicator in TodoBoards
fulopkovacs Dec 21, 2025
0ffb07e
Start redesigning the board
fulopkovacs Dec 21, 2025
5fac4fd
Add scroll shadow effect to TodoBoards with useScrollShadow hook
fulopkovacs Dec 21, 2025
6389798
Update TodoBoards UI with icons, badges, and improved layout
fulopkovacs Dec 21, 2025
ec18aa4
Design updates
fulopkovacs Dec 22, 2025
d102e02
Replace CircleIcon with SkullIcon and update priority icons and butto…
fulopkovacs Dec 22, 2025
20b14f5
Apply a wiggle animation to the dragged task element
fulopkovacs Dec 22, 2025
5f53154
Update the AGENTS.md config
fulopkovacs Dec 22, 2025
4cce443
Fix the styles.css file
fulopkovacs Dec 22, 2025
4f38069
Adjust the loading skeleton's colors
fulopkovacs Dec 22, 2025
707e8b1
Refactor Board component to remove unused projectId prop and improve …
fulopkovacs Dec 22, 2025
ac19cc5
Update badge styles with outline and muted variants and add success c…
fulopkovacs Dec 22, 2025
81a524c
Update the author attribution
fulopkovacs Dec 22, 2025
612ff66
Update the colors of the NetworkLatencyConfigurator
fulopkovacs Dec 22, 2025
1316293
Update the loading skeleton of the project details
fulopkovacs Dec 23, 2025
fa7865f
Fix the loading skeleton of the project details
fulopkovacs Dec 23, 2025
77fb5a4
Add loading skeleton for the boards
fulopkovacs Dec 23, 2025
f35b964
Fix the dark mode theme
fulopkovacs Dec 23, 2025
2bc9950
Fix the bg of the database loader progress bar
fulopkovacs Dec 23, 2025
a8a8e58
Use light theme by default
fulopkovacs Dec 23, 2025
e576fe4
Center the DropIndicator line
fulopkovacs Dec 23, 2025
543b163
Update the selection colors for the input fields
fulopkovacs Dec 23, 2025
63714e9
Fix the DropIndicator to show up before the first card if needed
fulopkovacs Dec 23, 2025
ac140e2
Remove an unused component
fulopkovacs Dec 24, 2025
869fbdd
Run knip in the CI
fulopkovacs Dec 24, 2025
b2d8b2a
Remove unused export
fulopkovacs Dec 24, 2025
a28e35d
Remove a redundant console.log
fulopkovacs Dec 24, 2025
e7fe40a
Replace VList with Virtualizer from virtua and simplify scroll contai…
fulopkovacs Dec 24, 2025
6f49b18
Fix a formatting issue
fulopkovacs Dec 24, 2025
e84ec5f
Fix the virtualization of todo items
fulopkovacs Dec 24, 2025
3af3e08
Fix: Show the drop indicator for empty columns too
fulopkovacs Dec 24, 2025
6ef9504
Make sure the skeleton in place of the dragged element has the correc…
fulopkovacs Dec 24, 2025
40d91ad
Fix the position of the sidebar trigger on small screens
fulopkovacs Dec 24, 2025
03942e7
Add a comment to explain why we cannot use a dependency array when we…
fulopkovacs Dec 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ jobs:
- name: Type check
run: pnpm typecheck

- name: Knip
run: pnpm knip

- name: Test
run: pnpm test

Expand All @@ -73,12 +76,12 @@ jobs:
owner: context.repo.owner,
repo: context.repo.repo,
});

const botComment = comments.data.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('🚀 Preview Deployment')
);

if (botComment) {
console.log(`Found existing comment: ${botComment.id}`);
return botComment.id;
Expand All @@ -93,11 +96,11 @@ jobs:
const commentBody = `## 🚀 Preview Deployment

**Status:** ⏳ Loading...

**Commit:** \`${{ github.event.pull_request.head.sha }}\`

_Deployment in progress..._`;

if (commentId && commentId !== 'null') {
await github.rest.issues.updateComment({
comment_id: commentId,
Expand Down Expand Up @@ -162,17 +165,17 @@ jobs:
script: |
const deploymentUrl = '${{ steps.deploy.outputs.deployment-url }}';
const commentId = '${{ steps.find-comment.outputs.result }}';

const commentBody = `## 🚀 Preview Deployment

**Status:** ✅ Ready!

**Preview URL:** [Open Preview](${deploymentUrl})

**Commit:** \`${{ github.event.pull_request.head.sha }}\`

_Built and deployed successfully_`;

if (commentId && commentId !== 'null') {
await github.rest.issues.updateComment({
comment_id: commentId,
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Here's the tech stack:
- framework: TanStack Start (`@tanstack/start`) with `react`
- router: TanStack Router (`@tanstack/router`)
- ui: `shadcn/ui`
- css: `tailwindcss`
- css: `tailwindcss` (v4)

# Tests

Expand Down
6 changes: 1 addition & 5 deletions src/collections/todoItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,7 @@ export async function batchUpdateTodoItem({
await res.json();
}

export async function insertTodoItem({
data,
}: {
data: TodoItemCreateDataType;
}) {
async function insertTodoItem({ data }: { data: TodoItemCreateDataType }) {
const res = await fetch("/api/todo-items", {
method: "POST",
headers: {
Expand Down
4 changes: 2 additions & 2 deletions src/components/ConfigureDB.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ export function ConfigureDB() {
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
>
<Badge className="gap-2" variant={"secondary"}>
<Badge className="gap-2 bg-muted" variant="outline">
<div
className={cn(
"grow-0 h-2 w-2 rounded-full",
"grow-0 h-2 w-2 rounded-full border",
isConnected
? "bg-green-300"
: "animate-pulse bg-yellow-400",
Expand Down
62 changes: 29 additions & 33 deletions src/components/EditableProjectDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ function EditProjectNamePopover({ name, id }: { name: string; id: string }) {
name: name,
},
onSubmit: ({ value }) => {
console.log("New project name:", value.name);
projectsCollection.update(id, (project) => {
project.name = value.name;
});
Expand Down Expand Up @@ -91,17 +90,6 @@ function ProjectsNotFoundFromAPIErrorMessage() {
);
}

function LoadingEditableProjects() {
return (
<div className="flex flex-col gap-4">
<div className="flex items-center gap-2">
<Skeleton className="size-9 scroll-m-40 text-2xl font-extrabold w-20" />
</div>
<Skeleton className="h-(--text-xl) w-80" />
</div>
);
}

export function EditableProjectDetails({ projectId }: { projectId: string }) {
const {
data: [project],
Expand Down Expand Up @@ -140,32 +128,40 @@ export function EditableProjectDetails({ projectId }: { projectId: string }) {
}
}, [project, isReady]);

return isLoading ? (
<LoadingEditableProjects />
) : project ? (
<HighlightWrapper highlightId="project_projectPage">
<div className="flex flex-col gap-4">
<div className="flex items-center gap-2">
<h1 className="scroll-m-20 text-2xl font-extrabold">
{project.name}
</h1>
<EditProjectNamePopover name={project.name} id={project.id} />
</div>
<p>{project.description}</p>
</div>
</HighlightWrapper>
) : /*
The API returned a 404 error when trying to sync the
projects collection.
*/
notFoundErrorMessageVisible ? (
return notFoundErrorMessageVisible ? (
/*
The API returned a 404 error when trying to sync the
projects collection.
*/
<ProjectsNotFoundFromAPIErrorMessage />
) : isReady ? (
) : isReady && !project ? (
// The collection is ready, but no project was found
// with this particular live query
<div className="text-muted-foreground">
<p>No project was found with this id.</p>
<p>Please select a project from the sidebar!</p>
</div>
) : null;
) : (
<HighlightWrapper highlightId="project_projectPage">
<div className="flex flex-col mb-6 gap-1">
<div className="flex items-center gap-2">
{isLoading ? (
<div className="flex items-center h-9">
<Skeleton className="h-8 w-40" />
</div>
) : (
<>
<h1 className="scroll-m-20 text-2xl font-bold">{project.name}</h1>
<EditProjectNamePopover name={project.name} id={project.id} />
</>
)}
</div>
{isLoading ? (
<Skeleton className="h-6 block w-80" />
) : (
<p className="text-muted-foreground">{project.description}</p>
)}
</div>
</HighlightWrapper>
);
}
2 changes: 1 addition & 1 deletion src/components/FakeProgressIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function FakeProgressIndicator() {
Setting up the database...
</span>
<div className="w-[60%] max-w-md">
<div className="h-2 bg-secondary rounded-full overflow-hidden">
<div className="h-2 bg-skeleton rounded-full overflow-hidden">
<div
ref={progressRef}
className="h-full bg-primary progress-animated"
Expand Down
54 changes: 27 additions & 27 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ClientOnly } from "@tanstack/react-router";
import { BugIcon, DatabaseZap, GithubIcon } from "lucide-react";
import { BugIcon, GithubIcon } from "lucide-react";
import { ConfigureDB } from "./ConfigureDB";
import { ModeToggle } from "./mode-toggle";
import { NetworkLatencyConfigurator } from "./NetworkLatencyConfigurator";
Expand All @@ -11,32 +11,32 @@ export function Header() {
return (
<header className="flex gap-2 items-center justify-between px-4 py-2 border-b bg-background sticky top-0">
<SidebarTrigger className="md:hidden" />
<a
target="_blank"
href="https://tanstack.com/db/latest/docs/overview"
className="flex items-center text-sm cursor-pointer"
rel="noopener"
>
<DatabaseZap className="h-4 text-orange-500" />
<span className="cursor-pointer bg-linear-to-r bg-clip-text from-orange-500 to-orange-700 text-transparent">
TanStack DB Tutorial{" "}
</span>
</a>
<span className="text-sm">ALPHA</span>
<span className="text-muted-foreground text-sm">by</span>
<a
href="https://fulop.dev"
target="_blank"
rel="noreferrer"
className="cursor-pointer text-muted-foreground hover:text-foreground transition-colors flex items-center gap-2 text-sm"
>
<img
alt="fuko"
src="https://avatars.githubusercontent.com/u/43729152?s=96&v=4"
className="inline h-6 w-6 rounded-full"
/>
fuko
</a>
<div className="flex items-center gap-1 text-sm font-medium">
<a
href="https://fulop.dev"
target="_blank"
rel="noreferrer"
className="group/fuko-link cursor-pointer transition-colors flex items-center gap-2"
>
<img
alt="fuko"
src="https://avatars.githubusercontent.com/u/43729152?s=96&v=4"
className="inline h-6 w-6 rounded-full border"
/>
<span className="underline decoration-wavy group-hover/fuko-link:opacity-80 transition-opacity">
fuko's
</span>
</a>
guide to
<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"
>
@tanstack/db
</a>
</div>
<ClientOnly fallback={null}>
<div className="ml-auto">
<ConfigureDB />
Expand Down
6 changes: 3 additions & 3 deletions src/components/NetworkLatencyConfigurator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ export function NetworkLatencyConfigurator() {
<GlobeIcon
className={cn(
selectedLatency === 0
? "text-green-300"
? "text-green-500 dark:text-green-300"
: selectedLatency === 2000
? "text-orange-300"
? "text-orange-400 dark:text-orange-300"
: selectedLatency === 5000
? "text-destructive-foreground"
? "text-destructive dark:text-destructive"
: "text-foreground",
)}
/>
Expand Down
39 changes: 30 additions & 9 deletions src/components/PriorityRating.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CircleIcon } from "lucide-react";
import { SkullIcon } from "lucide-react";
import { useCallback } from "react";
import { todoItemsCollection } from "@/collections/todoItems";
import { Button } from "./ui/button";
Expand All @@ -10,16 +10,16 @@ import {
} from "./ui/dropdown-menu";

const icons = [
<CircleIcon key="0" className="text-muted-foreground h-4 w-4" />,
<span key="1" className="block text-red-500 font-bold text-sm">
<span key="0" className="block text-muted-foreground font-bold text-sm">
!
</span>,
<span key="2" className="block text-red-500 font-bold text-sm">
<span key="1" className="block font-bold text-current text-sm">
!!
</span>,
<span key="3" className="block text-red-500 font-bold text-sm">
<span key="2" className="block text-destructive font-bold text-sm">
!!!
</span>,
<SkullIcon key="3" className="text-destructive h-4 w-4" />,
];

export function PriorityRatingPopup({
Expand All @@ -38,19 +38,40 @@ export function PriorityRatingPopup({
[todoItemId],
);

const handlePointerDown = (e: React.PointerEvent) => {
e.stopPropagation();
};

const handleClick = (e: React.MouseEvent) => {
e.stopPropagation();
};

return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<Button
variant="empty"
size="icon"
onPointerDown={handlePointerDown}
className="bg-muted hover:bg-muted/80 rounded-full"
>
{icons[priority || 0]}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="min-w-0 flex flex-col items-center">
<DropdownMenuContent
className="min-w-0 flex flex-col items-center"
onPointerDown={handlePointerDown}
onClick={handleClick}
>
{icons.map((icon, index) => (
<DropdownMenuItem
key={index}
onClick={() => handleUpdate(index)}
className="w-fit"
onClick={(e) => {
e.stopPropagation();
handleUpdate(index);
}}
onPointerDown={handlePointerDown}
className="w-8 h-8 flex items-center justify-center p-0"
>
{icon}
</DropdownMenuItem>
Expand Down
Loading