shadcn-kanban-board

repository·main·Indexed 42 days ago

https://github.com/janhesters/shadcn-kanban-board

A production-ready, accessible Kanban board designed for Shadcn/UI environments. It is framework-agnostic and compatible with local state, React Router v7 actions, or Next.js Server Actions. Features include mouse and keyboard drag-and-drop support via useDndEvents(), a useJsLoaded() hook to prevent layout shift, and extensible APIs for custom DnD monitors and announcement handlers.

Tokens
3.1K
Snippets
6
Records
10
Agent score
53%

What's inside shadcn-kanban-board

  1. Extend the Kanban Board with custom handlers

    main

    The Kanban board provides extensible APIs for fine-grained control over user interactions. You can register:

    • Custom DnD monitors: To track or intercept drag-and-drop movements.
    • Announcement handlers: To customize how screen-reader announcements are triggered during drag events.
  2. Install the Shadcn/UI Kanban Board

    main

    You can install the Kanban board components using the shadcn CLI. The installation requires two separate components: the main kanban component and the use-js-loaded hook. Choose the command corresponding to your preferred package manager.

    # npm
    npx shadcn@latest add https://shadcn-kanban-board.com/r/kanban.json
    npx shadcn@latest add https://shadcn-kanban-board.com/r/use-js-loaded.json
    
    # yarn
    yarn dlx shadcn@latest add https://shadcn-kanban-board.com/r/kanban.json
    yarn dlx shadcn@latest add https://shadcn-kanban-board.com/r/use-js-loaded.json
    
    # pnpm
    pnpm dlx shadcn@latest add https://shadcn-kanban-board.com/r/kanban.json
    pnpm dlx shadcn@latest add https://shadcn-kanban-board.com/r/use-js-loaded.json
    
    # bun
    bunx shadcn@latest add https://shadcn-kanban-board.com/r/kanban.json
    bunx shadcn@latest add https://shadcn-kanban-board.com/r/use-js-loaded.json
  3. Implement the Kanban Board pattern

    main

    To build a functional Kanban board, follow the pattern demonstrated in the project's example. The implementation involves several key pieces:

    1. Provider & Layout: Wrap your application or page content in KanbanBoardProvider and place the <KanbanBoard> component within your layout.
    2. State Management: Use stable IDs (e.g., via createId() from @paralleldrive/cuid2) for columns and cards to ensure smooth drag-and-drop operations.
    3. Loading State: Use the useJsLoaded() hook to prevent layout shift. While JS is loading, you can render a <KanbanBoardColumnSkeleton> to provide a visual placeholder.
    4. Interactivity:
      • Drag & Drop: The board supports mouse and keyboard DnD (via useDndEvents()). Keyboard controls include Space/Enter to pick up/drop, Arrow keys to move, and Escape to cancel.
      • Editing: Use <Input> and <Textarea> for inline editing of column and card titles.
    5. Theming: The board uses KanbanColorCircle primitives which automatically adapt to your Shadcn/UI CSS variables.
  4. Configure ESLint for the Kanban Board project

    main

    The project uses a flat configuration for ESLint with typescript-eslint, unicorn, simple-import-sort, vitest, testing-library, and playwright.

    Key configuration features include:

    • Type-Checked Linting: Uses tseslint.configs.recommendedTypeChecked and tseslint.configs.stylisticTypeChecked with projectService: true for deep type analysis.
    • Import Sorting: Enforces strict import and export ordering via simple-import-sort.
    • Prettier Integration: Uses eslint-plugin-prettier/recommended to ensure code formatting consistency.
    • Testing Support:
      • Vitest: Configured for files matching app/**/*.{test,spec}.{js,ts,jsx,tsx} with type-checking enabled.
      • Testing Library: React-specific testing rules applied to src/**/*.test.{jsx,tsx}.
      • Playwright: E2E testing rules applied to playwright/**/*.e2e.ts.
    import tseslint from 'typescript-eslint';
    import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
    
    export default tseslint.config(
      // ... configuration blocks
      eslintPluginPrettierRecommended,
    );
  5. Configure Playwright E2E testing

    main

    The project uses Playwright for end-to-end (E2E) testing. Tests are located in the ./playwright directory and must use the .e2e.ts file extension. The configuration is optimized for both local development and CI environments, utilizing environment variables like CI and APP_URL to adjust behavior such as retries, tracing, and the base URL.

    import { defineConfig, devices } from '@playwright/test';
    
    export default defineConfig({
      testDir: './playwright',
      testMatch: '*.e2e.ts',
      fullyParallel: true,
      forbidOnly: !!process.env.CI,
      retries: process.env.CI ? 2 : 0,
      workers: 1,
      reporter: 'html',
      use: {
        baseURL: process.env.APP_URL ?? 'http://localhost:3000',
        trace: process.env.CI ? 'on-first-retry' : 'retain-on-failure',
      },
      projects: [
        { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
        { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
        { name: 'webkit', use: { ...devices['Desktop Safari'] } },
      ],
      webServer: {
        command: process.env.CI ? 'npm run start-with-server-mocks' : 'npm run dev-with-mocks',
        port: 3000,
        reuseExistingServer: process.env.CI ? false : true,
      },
    });
  6. Configure Prettier settings

    main

    The project uses Prettier for code formatting with specific rules to maintain consistency. It also utilizes the prettier-plugin-tailwindcss plugin to handle Tailwind CSS class sorting and formatting. If you are contributing to or building upon this project, ensure your local Prettier configuration aligns with these settings to avoid formatting conflicts.

    export default {
      arrowParens: 'avoid',
      bracketSameLine: false,
      bracketSpacing: true,
      htmlWhitespaceSensitivity: 'css',
      insertPragma: false,
      jsxSingleQuote: false,
      plugins: ['prettier-plugin-tailwindcss'],
      printWidth: 80,
      proseWrap: 'always',
      quoteProps: 'as-needed',
      requirePragma: false,
      semi: true,
      singleQuote: true,
      tabWidth: 2,
      trailingComma: 'all',
      useTabs: false,
    };
  7. Use the cn utility to merge Tailwind CSS classes

    main

    The cn utility is used to conditionally merge Tailwind CSS classes. It combines clsx for handling conditional logic and twMerge to ensure that Tailwind class conflicts are resolved correctly (e.g., ensuring the last class passed takes precedence). This is the standard way to manage dynamic styles in this project.

    import { cn } from '@/lib/utils';
    
    // Example usage with conditional classes
    const className = cn("base-class", isTrue && "conditional-class", "override-class");
  8. Playwright test execution settings

    main

    The following settings control how tests are discovered and executed in this repository:

    • testDir: Set to ./playwright.
    • testMatch: Matches files with the *.e2e.ts extension.
    • fullyParallel: Enabled (true).
    • workers: Set to 1 to opt out of parallel test execution.
    • forbidOnly: If process.env.CI is set, the build will fail if test.only is present in the code.
    • retries: On CI, tests will retry 2 times; otherwise, 0 retries.
    • reporter: Uses the html reporter.
  9. Reference: TypeScript and Unicorn Linting Rules

    main

    The following specific rules are enforced to maintain code quality and consistency across the codebase.

    // TypeScript Rules
    '@typescript-eslint/consistent-type-definitions': ['error', 'type'],
    '@typescript-eslint/no-unused-vars': [
      'error',
      {
        args: 'all',
        argsIgnorePattern: '^_',
        caughtErrors: 'all',
        caughtErrorsIgnorePattern: '^_',
        destructuredArrayIgnorePattern: '^_',
        varsIgnorePattern: '^_',
        ignoreRestSiblings: true,
      },
    ],
    '@typescript-eslint/consistent-type-imports': [
      'error',
      {
        prefer: 'type-imports',
        fixStyle: 'separate-type-imports',
        disallowTypeAnnotations: true,
      },
    ],
    '@typescript-eslint/no-misused-promises': [
      'error',
      { checksVoidReturn: { attributes: false } },
    ],
    '@typescript-eslint/only-throw-error': [
      'error',
      {
        allow: [
          { from: 'file', name: 'DataWithResponseInit' },
          { from: 'file', name: 'ErrorResponse' },
          { from: 'lib', name: 'Response' },
        ],
      },
    ],
    
    // Unicorn Rules
    'unicorn/better-regex': 'warn',
    'unicorn/no-process-exit': 'off',
    'unicorn/no-array-reduce': 'off',
    'unicorn/no-array-callback-reference': 'off',
    'unicorn/prevent-abbreviations': [
      'error',
      {
        replacements: { args: false, params: false, props: false, utils: false },
      },
    ],
    'unicorn/filename-case': [
      'error',
      {
        case: 'kebabCase',
        ignore: [
          /.*\._index\.(tsx|ts)$/,
          /.*\$[A-Za-z]+Slug(\.[A-Za-z]+)*\.(tsx,ts)$/,
          /.*_\.[A-Za-z]+\.(tsx|ts)$/,
        ],
      },
    ],
    
    // Import Sorting
    'simple-import-sort/imports': 'error',
    'simple-import-sort/exports': 'error',
  10. Playwright environment and web server configuration

    main

    The testing environment relies on the following configurations:

    Global use options

    • baseURL: Defaults to http://localhost:3000 unless process.env.APP_URL is provided.
    • trace: On CI, set to on-first-retry. Locally, set to retain-on-failure.

    webServer settings

    Playwright automatically manages the local development server before running tests:

    • command: Uses npm run start-with-server-mocks on CI, or npm run dev-with-mocks locally.
    • port: 3000.
    • reuseExistingServer: Set to false on CI and true locally.