UI Lab

    Kanban & Board Variants

    16 production-ready boards — pick one, see the live preview, copy the code

    Personal Tasks

    Simple to-do board with three lanes.

    Personal Tasks
    To Do
    2

    Buy groceries

    low
    Apr 25

    Renew gym membership

    medium
    Doing
    1

    Read TanStack docs

    medium
    Done
    1

    Pay electricity bill

    high
    Source Code

    Install & set up

    Everything this board needs: 7 generated files to copy and 14 shared engine files the CLI can install for you.

    1

    Choose how data is fetched

    Two independent choices. The default adds no dependency at all — the command below and the code both follow whatever you pick.

    HTTP client used by services.ts

    Where results live used by hooks.ts

    Adds no extra packages.

    2

    Install it with the CLI

    recommended

    Installs every file below and its packages in one command. The steps after this are only for doing it by hand.

    npx afnoui add kanban/kanban-personal-tasks
    Writes to 4 places
    3

    Or install the packages yourself

    Only needed if you copied the files by hand instead of running the command above.

    Runtime dependencies

    npm install react react-dom lucide-react clsx tailwind-merge class-variance-authority

    Dev dependencies

    None — nothing extra is needed at build time.

    • Requires AfnoUI components: button, badge, input, label, textarea, select, dialog, scroll-area, avatar, progress, use-toast.
    • Bring `cn` from your `@/lib/utils` (clsx + tailwind-merge).
    • DnD library is bundled — no @dnd-kit dependency.
    • Import components/dnd/dnd.css once at app entry (e.g. in your global stylesheet).

    Generated files

    Generated files are yours to copy and edit; shared engine files are installed once and reused.

    Generated per board(7)

    Shared engine — copy once(14)

    Generated per board

    Your generated board component — wires the engine to your config + data + onChange hook.

    src/boards/MyTasks/MyTasks.tsx
    src/boards/MyTasks/MyTasks.tsx
    import { useState } from "react";
    import { KanbanBoard } from "@/components/kanban/KanbanBoard";
    import { boardConfig } from "./config";
    import { initialCards } from "./data";
    import { useMyTasksCardChange, useMyTasksLoadMore } from "./hooks";
    import type { KanbanCardData } from "./types";
    
    /**
     * My Tasks
     * Personal productivity board
     *
     * Drag-and-drop is powered by the project's custom Pointer DnD library
     * (no @dnd-kit dependency). Cards persist locally — wire `services.ts`
     * to your backend to make moves stick across reloads.
     */
    export default function MyTasks() {
      const [cards, setCards] = useState<KanbanCardData[]>(initialCards);
      const handleCardChange = useMyTasksCardChange();
      const handleLoadMore = useMyTasksLoadMore();
      return (
        <div className="space-y-4">
          <div>
            <h2 className="text-xl font-bold">{boardConfig.title}</h2>
            {boardConfig.subtitle && (
              <p className="text-sm text-muted-foreground">{boardConfig.subtitle}</p>
            )}
          </div>
          <KanbanBoard
            config={boardConfig}
            cards={cards}
            onCardsChange={setCards}
            onCardChange={handleCardChange}
            onLoadMore={handleLoadMore}
          />
        </div>
      );
    }