Skip to content

Commit c89087e

Browse files
authored
Merge pull request #15 from objectstack-ai/copilot/implement-kanban-component
2 parents 4d4b567 + 3a2caff commit c89087e

11 files changed

Lines changed: 793 additions & 5 deletions

File tree

.github/copilot-instructions.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,28 @@ export const InputRenderer = ({ schema, value, onChange }: Props) => {
143143
)}
144144
</div>
145145
);
146-
};
146+
};
147+
148+
```
149+
150+
---
151+
152+
## 6. AI Workflow Instructions
153+
154+
### 🟢 On "Create New Component":
155+
156+
1. **Define Protocol:** Create `interface XSchema` in `@object-ui/types`.
157+
2. **Implement UI:** Create `XRenderer` in `@object-ui/components` using Shadcn primitives.
158+
3. **Register:** Add to the default component registry.
159+
4. **Standalone Check:** Ask yourself: *"Can a user use this component with a static JSON array?"* If no, refactor data logic to `DataSource`.
160+
161+
### 🟡 On "Data Fetching Logic":
162+
163+
1. **Abstraction:** Never import `axios` or `fetch` directly in a UI component.
164+
2. **Hook:** Use `useDataSource()` or `useDataScope()` to request data.
165+
3. **Example:** For an Autocomplete, call `dataSource.find({ search: term })`, allowing the user to inject *any* data source (REST API, Algolia, or local array).
166+
167+
### 🟣 On "Promoting the Project":
168+
169+
1. **Keywords:** Focus on "Tailwind-Native", "Headless", "Shadcn Compatible".
170+
2. **Differentiation:** Emphasize that unlike other low-code renderers, Object UI allows full styling control via standard Tailwind classes.

apps/playground/src/data/examples.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,127 @@ export const examples = {
863863
]
864864
}`,
865865

866+
'kanban-board': `{
867+
"type": "kanban",
868+
"className": "w-full h-[600px]",
869+
"columns": [
870+
{
871+
"id": "backlog",
872+
"title": "📋 Backlog",
873+
"cards": [
874+
{
875+
"id": "card-1",
876+
"title": "User Authentication",
877+
"description": "Implement user login and registration flow",
878+
"badges": [
879+
{ "label": "Feature", "variant": "default" },
880+
{ "label": "High Priority", "variant": "destructive" }
881+
]
882+
},
883+
{
884+
"id": "card-2",
885+
"title": "API Documentation",
886+
"description": "Write comprehensive API docs",
887+
"badges": [
888+
{ "label": "Documentation", "variant": "outline" }
889+
]
890+
},
891+
{
892+
"id": "card-3",
893+
"title": "Database Optimization",
894+
"description": "Improve query performance",
895+
"badges": [
896+
{ "label": "Performance", "variant": "secondary" }
897+
]
898+
}
899+
]
900+
},
901+
{
902+
"id": "todo",
903+
"title": "📝 To Do",
904+
"cards": [
905+
{
906+
"id": "card-4",
907+
"title": "Design Landing Page",
908+
"description": "Create wireframes and mockups",
909+
"badges": [
910+
{ "label": "Design", "variant": "default" }
911+
]
912+
},
913+
{
914+
"id": "card-5",
915+
"title": "Setup CI/CD Pipeline",
916+
"description": "Configure GitHub Actions",
917+
"badges": [
918+
{ "label": "DevOps", "variant": "secondary" }
919+
]
920+
}
921+
]
922+
},
923+
{
924+
"id": "in-progress",
925+
"title": "⚙️ In Progress",
926+
"limit": 3,
927+
"cards": [
928+
{
929+
"id": "card-6",
930+
"title": "Payment Integration",
931+
"description": "Integrate Stripe payment gateway",
932+
"badges": [
933+
{ "label": "Feature", "variant": "default" },
934+
{ "label": "In Progress", "variant": "secondary" }
935+
]
936+
},
937+
{
938+
"id": "card-7",
939+
"title": "Bug Fix: Login Issue",
940+
"description": "Fix session timeout bug",
941+
"badges": [
942+
{ "label": "Bug", "variant": "destructive" }
943+
]
944+
}
945+
]
946+
},
947+
{
948+
"id": "review",
949+
"title": "👀 Review",
950+
"cards": [
951+
{
952+
"id": "card-8",
953+
"title": "Dashboard Analytics",
954+
"description": "Add charts and metrics",
955+
"badges": [
956+
{ "label": "Feature", "variant": "default" },
957+
{ "label": "Needs Review", "variant": "outline" }
958+
]
959+
}
960+
]
961+
},
962+
{
963+
"id": "done",
964+
"title": "✅ Done",
965+
"cards": [
966+
{
967+
"id": "card-9",
968+
"title": "Project Setup",
969+
"description": "Initialize repository and dependencies",
970+
"badges": [
971+
{ "label": "Completed", "variant": "outline" }
972+
]
973+
},
974+
{
975+
"id": "card-10",
976+
"title": "Basic Layout",
977+
"description": "Create header and navigation",
978+
"badges": [
979+
{ "label": "Completed", "variant": "outline" }
980+
]
981+
}
982+
]
983+
}
984+
]
985+
}`,
986+
866987
// Enterprise Data Table - Airtable-like functionality
867988
'enterprise-table': `{
868989
"type": "div",
@@ -1129,4 +1250,5 @@ export const exampleCategories = {
11291250
'Layouts': ['grid-layout', 'dashboard', 'tabs-demo'],
11301251
'Data Display': ['calendar-view', 'enterprise-table', 'data-table-simple'],
11311252
'Forms': ['form-demo', 'airtable-form'],
1253+
'Complex': ['kanban-board']
11321254
};

packages/components/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
"test": "vitest run"
2121
},
2222
"dependencies": {
23+
"@dnd-kit/core": "^6.3.1",
24+
"@dnd-kit/sortable": "^8.0.0",
25+
"@dnd-kit/utilities": "^3.2.2",
2326
"@object-ui/core": "workspace:*",
2427
"@object-ui/react": "workspace:*",
2528
"@radix-ui/react-accordion": "^1.2.12",
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# Kanban Board Component
2+
3+
A fully functional, schema-driven Kanban board component for Object UI with drag-and-drop support.
4+
5+
## Features
6+
7+
- **Multiple Columns**: Create unlimited columns with customizable titles
8+
- **Rich Cards**: Cards support title, description, and multiple badges
9+
- **Drag & Drop**: Smooth drag-and-drop functionality powered by @dnd-kit
10+
- **Reordering**: Reorder cards within the same column
11+
- **Cross-Column Moves**: Move cards between different columns
12+
- **Column Limits**: Optional capacity limits with visual indicators
13+
- **Card Counters**: Shows current count and limit per column
14+
- **Schema-Driven**: Configure entirely through JSON/YAML
15+
- **Event Callbacks**: Custom event handling for card movements
16+
17+
## Usage
18+
19+
### Basic Example
20+
21+
```json
22+
{
23+
"type": "kanban",
24+
"className": "w-full h-[600px]",
25+
"columns": [
26+
{
27+
"id": "todo",
28+
"title": "To Do",
29+
"cards": [
30+
{
31+
"id": "card-1",
32+
"title": "Task Title",
33+
"description": "Task description",
34+
"badges": [
35+
{ "label": "High Priority", "variant": "destructive" }
36+
]
37+
}
38+
]
39+
},
40+
{
41+
"id": "in-progress",
42+
"title": "In Progress",
43+
"limit": 3,
44+
"cards": []
45+
},
46+
{
47+
"id": "done",
48+
"title": "Done",
49+
"cards": []
50+
}
51+
]
52+
}
53+
```
54+
55+
### With Event Handling
56+
57+
```json
58+
{
59+
"type": "kanban",
60+
"columns": [...],
61+
"onCardMove": "(event) => { console.log('Card moved:', event); }"
62+
}
63+
```
64+
65+
## Schema Reference
66+
67+
### Kanban Props
68+
69+
| Property | Type | Required | Description |
70+
|----------|------|----------|-------------|
71+
| `type` | `"kanban"` | Yes | Component type identifier |
72+
| `columns` | `KanbanColumn[]` | Yes | Array of column configurations |
73+
| `className` | `string` | No | Custom CSS classes |
74+
| `onCardMove` | `function` | No | Callback when a card is moved |
75+
76+
### KanbanColumn
77+
78+
| Property | Type | Required | Description |
79+
|----------|------|----------|-------------|
80+
| `id` | `string` | Yes | Unique column identifier |
81+
| `title` | `string` | Yes | Column header title |
82+
| `cards` | `KanbanCard[]` | Yes | Array of cards in this column |
83+
| `limit` | `number` | No | Maximum number of cards allowed |
84+
| `className` | `string` | No | Custom CSS classes for column |
85+
86+
### KanbanCard
87+
88+
| Property | Type | Required | Description |
89+
|----------|------|----------|-------------|
90+
| `id` | `string` | Yes | Unique card identifier |
91+
| `title` | `string` | Yes | Card title |
92+
| `description` | `string` | No | Card description text |
93+
| `badges` | `Badge[]` | No | Array of badge objects |
94+
95+
### Badge
96+
97+
| Property | Type | Required | Description |
98+
|----------|------|----------|-------------|
99+
| `label` | `string` | Yes | Badge text |
100+
| `variant` | `"default" \| "secondary" \| "destructive" \| "outline"` | No | Badge color variant |
101+
102+
## Examples
103+
104+
### Simple Task Board
105+
106+
```json
107+
{
108+
"type": "kanban",
109+
"columns": [
110+
{
111+
"id": "backlog",
112+
"title": "📋 Backlog",
113+
"cards": [
114+
{
115+
"id": "1",
116+
"title": "Setup project",
117+
"badges": [{ "label": "Setup" }]
118+
}
119+
]
120+
},
121+
{
122+
"id": "doing",
123+
"title": "🚀 Doing",
124+
"limit": 2,
125+
"cards": []
126+
},
127+
{
128+
"id": "done",
129+
"title": "✅ Done",
130+
"cards": []
131+
}
132+
]
133+
}
134+
```
135+
136+
### Issue Tracking Board
137+
138+
```json
139+
{
140+
"type": "kanban",
141+
"columns": [
142+
{
143+
"id": "new",
144+
"title": "New Issues",
145+
"cards": [
146+
{
147+
"id": "issue-1",
148+
"title": "Bug: Login fails on Safari",
149+
"description": "Users can't login using Safari browser",
150+
"badges": [
151+
{ "label": "Bug", "variant": "destructive" },
152+
{ "label": "P0", "variant": "destructive" }
153+
]
154+
}
155+
]
156+
},
157+
{
158+
"id": "investigating",
159+
"title": "Investigating",
160+
"limit": 3,
161+
"cards": []
162+
},
163+
{
164+
"id": "fixed",
165+
"title": "Fixed",
166+
"cards": []
167+
}
168+
]
169+
}
170+
```
171+
172+
## Styling
173+
174+
The Kanban component uses Tailwind CSS and can be customized using the `className` prop:
175+
176+
```json
177+
{
178+
"type": "kanban",
179+
"className": "w-full h-[800px] bg-gray-50 p-4 rounded-lg",
180+
"columns": [...]
181+
}
182+
```
183+
184+
Individual columns can also be styled:
185+
186+
```json
187+
{
188+
"id": "urgent",
189+
"title": "🔥 Urgent",
190+
"className": "bg-red-50",
191+
"cards": [...]
192+
}
193+
```
194+
195+
## Technical Details
196+
197+
- Built with React 18+ and TypeScript
198+
- Uses @dnd-kit for drag-and-drop functionality
199+
- Integrates with Shadcn UI components (Card, Badge, ScrollArea)
200+
- Supports both pointer and touch interactions
201+
- Accessible keyboard navigation (via @dnd-kit)
202+
203+
## Browser Support
204+
205+
- Chrome/Edge: Full support
206+
- Firefox: Full support
207+
- Safari: Full support
208+
- Mobile browsers: Full support with touch gestures
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import './calendar-view';
22
import './carousel';
3+
import './kanban';
34
import './filter-builder';
45
import './scroll-area';
56
import './resizable';
6-
import './scroll-area';
77
import './table';
88
import './data-table';
99
import './timeline';
10-
import './calendar-view';
10+

0 commit comments

Comments
 (0)