Interactive Kanban Board in React with TypeScript
Build a functional and interactive Kanban board application using React and TypeScript. This challenge will test your ability to manage component state, handle user interactions, and implement drag-and-drop functionality, all while ensuring type safety. A Kanban board is a visual project management tool that helps teams organize and track work, making it a fundamental component for many productivity applications.
Problem Description
Your task is to create a Kanban board where users can:
- Display Columns: Render multiple columns (e.g., "To Do", "In Progress", "Done"). Each column should have a title.
- Display Cards: Within each column, display cards representing individual tasks. Each card should have a title and potentially a description.
- Add New Cards: Allow users to add new cards to a specific column. This could be via a button or an input field.
- Edit Card Details: Enable users to edit the title and/or description of an existing card.
- Delete Cards: Provide a mechanism to delete cards from the board.
- Drag and Drop Cards: Implement drag-and-drop functionality allowing users to move cards between columns and reorder cards within the same column.
- Persistence (Optional but Recommended): If time permits, explore ways to persist the board state (e.g., using local storage or a simple API).
Key Requirements:
- All components should be implemented using React function components and TypeScript.
- State management should be handled efficiently, considering the dynamic nature of the Kanban board.
- The drag-and-drop mechanism should be intuitive and responsive.
- The application should be well-structured and maintainable.
Expected Behavior:
- Users can see predefined columns with cards.
- Clicking an "Add Card" button or similar UI element within a column should allow a new card to be created in that column.
- Clicking on a card should reveal an editing interface (e.g., a modal or inline editing).
- A "Delete" button or icon should be present on each card, allowing its removal.
- Users can click and hold a card, drag it to a different column or reorder it within its current column, and drop it to update its position.
Edge Cases to Consider:
- Empty columns: How does the UI behave when a column has no cards?
- Long card titles/descriptions: How should text be handled to prevent UI overflow?
- Concurrent drag operations (though less critical for a single-user client-side app).
- User canceling a drag operation.
Examples
Example 1: Initial State
Input Data (Conceptual):
{
columns: [
{ id: 'col-1', title: 'To Do', cards: [{ id: 'card-1', title: 'Design UI', description: 'Create mockups for the homepage.' }] },
{ id: 'col-2', title: 'In Progress', cards: [] },
{ id: 'col-3', title: 'Done', cards: [{ id: 'card-2', title: 'Setup project', description: 'Initialize React project with TypeScript.' }] }
]
}
Output (Conceptual UI Representation):
--------------------------------------------------------------------
| To Do | In Progress | Done |
--------------------------------------------------------------------
| [Card: Design UI | | [Card: Setup |
| Description: | | project |
| Create mockups...] | | Description: |
| | | Initialize React..|
--------------------------------------------------------------------
| [+ Add Card] | [+ Add Card] | [+ Add Card] |
--------------------------------------------------------------------
Example 2: Dragging a Card
- User Action: Drags "Design UI" card from "To Do" to "In Progress".
- Expected State Change: The
columnsdata structure updates to reflect the card's new position.
Updated Data (Conceptual):
{
columns: [
{ id: 'col-1', title: 'To Do', cards: [] },
{ id: 'col-2', title: 'In Progress', cards: [{ id: 'card-1', title: 'Design UI', description: 'Create mockups for the homepage.' }] },
{ id: 'col-3', title: 'Done', cards: [{ id: 'card-2', title: 'Setup project', description: 'Initialize React project with TypeScript.' }] }
]
}
Example 3: Adding a Card
- User Action: Clicks "+ Add Card" in the "To Do" column and enters "Write tests" for the title.
- Expected State Change: A new card is added to the "To Do" column.
Updated Data (Conceptual):
{
columns: [
{ id: 'col-1', title: 'To Do', cards: [{ id: 'card-1', title: 'Design UI', description: 'Create mockups for the homepage.' }, { id: 'card-3', title: 'Write tests', description: '' }] },
{ id: 'col-2', title: 'In Progress', cards: [] },
{ id: 'col-3', title: 'Done', cards: [{ id: 'card-2', title: 'Setup project', description: 'Initialize React project with TypeScript.' }] }
]
}
Constraints
- The application must be built using React and TypeScript.
- Avoid using external libraries for the core Kanban board logic (e.g., pre-built Kanban component libraries) unless specifically allowed for drag-and-drop. You are encouraged to use a popular drag-and-drop library like
react-beautiful-dndor explore native HTML5 drag-and-drop API. - Initial data structure for columns and cards should be managed within the React component's state (e.g., using
useStateoruseReducer). - The solution should be client-side only.
Notes
- Consider how you will manage unique IDs for columns and cards.
- Think about the data flow and how state updates will propagate through your components.
- For drag-and-drop, focus on a smooth user experience.
- Break down the problem into smaller, manageable components (e.g.,
KanbanBoard,Column,Card,AddCardForm). - Hint: You might want to define interfaces for
CardandColumnto leverage TypeScript's type checking. For drag-and-drop, consider libraries that provide good accessibility and performance.