Skip to content

Commit f1fa397

Browse files
committed
DND event based styling
1 parent a26264e commit f1fa397

File tree

5 files changed

+98
-7
lines changed

5 files changed

+98
-7
lines changed

Task Snap Space/src/atoms/.gitkeep

Whitespace-only changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { atom } from 'jotai';
2+
import { Task } from '../types/task';
3+
4+
export const activeTaskAtom = atom<Task | null>(null);

Task Snap Space/src/pages/app/sections/dashboard.tsx

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1+
import {
2+
DndContext,
3+
DragEndEvent,
4+
DragOverEvent,
5+
DragOverlay,
6+
DragStartEvent,
7+
KeyboardSensor,
8+
MouseSensor,
9+
PointerSensor,
10+
useSensor,
11+
useSensors,
12+
} from '@dnd-kit/core';
13+
import { useAtom } from 'jotai';
14+
import { createPortal } from 'react-dom';
115
import { useShallow } from 'zustand/shallow';
16+
import { activeTaskAtom } from '../../../atoms/activeTask';
217
import { useBoundStore } from '../../../store/store';
18+
import TaskCard from '../task/card';
319
import TaskCategory from '../task/category';
4-
import { DndContext, KeyboardSensor, MouseSensor, PointerSensor, useSensor, useSensors } from '@dnd-kit/core';
520

621
export default function Dashboard() {
722
const { categories, tasks } = useBoundStore(
@@ -11,6 +26,8 @@ export default function Dashboard() {
1126
}))
1227
);
1328

29+
const [activeTask, setActiveTask] = useAtom(activeTaskAtom);
30+
1431
const sensors = useSensors(
1532
useSensor(KeyboardSensor),
1633
useSensor(PointerSensor, { activationConstraint: { distance: 0.1 } }),
@@ -20,13 +37,36 @@ export default function Dashboard() {
2037
return (
2138
<section className='bg-white px-12 py-6 flex flex-col gap-y-5 rounded-xl shadow-lg shadow-black/25'>
2239
<h2 className='font-bold'>Your Task Dashboard</h2>
23-
<DndContext sensors={sensors}>
40+
<DndContext sensors={sensors} onDragStart={onDragStart} onDragEnd={onDragEnd} onDragOver={onDragOver}>
2441
<div className='grid grid-cols-3 gap-x-12'>
2542
{categories.map((category) => (
2643
<TaskCategory key={category.id} type={category.id} taskList={tasks.filter((task) => task.columnId === category.id)} />
2744
))}
2845
</div>
46+
{activeTask &&
47+
createPortal(
48+
<DragOverlay>
49+
<TaskCard task={activeTask} />
50+
</DragOverlay>,
51+
document.body
52+
)}
2953
</DndContext>
3054
</section>
3155
);
56+
57+
function onDragStart(event: DragStartEvent) {
58+
const { active } = event;
59+
60+
setActiveTask(active.data.current?.task);
61+
}
62+
63+
function onDragOver(event: DragOverEvent) {
64+
const { active, over } = event;
65+
66+
console.log(active, over);
67+
}
68+
69+
function onDragEnd() {
70+
setActiveTask(null);
71+
}
3272
}

Task Snap Space/src/pages/app/task/card.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import { CSS } from '@dnd-kit/utilities';
66

77
type Props = {
88
task: Task;
9+
bg?: string;
10+
transparent?: boolean;
911
};
1012

11-
export default function TaskCard({ task }: Props) {
12-
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
13+
export default function TaskCard({ task, bg, transparent }: Props) {
14+
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
1315
id: task.id,
1416
data: {
1517
type: 'task',
@@ -22,8 +24,28 @@ export default function TaskCard({ task }: Props) {
2224
transition,
2325
};
2426

27+
if (isDragging) {
28+
return (
29+
<div
30+
ref={setNodeRef}
31+
style={style}
32+
className={`opacity-75 first:rounded-b-xl rounded-xl w-full min-h-12 max-h-36 ${bg} ring-2 ring-inset ring-slate-950 shadow-lg shadow-black/15 py-2 flex items-center gap-x-2 px-3`}>
33+
<button className='invisible'>
34+
<IoCloseOutline className='w-7 h-7' />
35+
</button>
36+
<p className='break-all flex-grow invisible'>{task.content}</p>
37+
<button className='invisible' {...listeners} {...attributes}>
38+
<MdOutlineDragIndicator />
39+
</button>
40+
</div>
41+
);
42+
}
43+
2544
return (
26-
<div ref={setNodeRef} style={style} className='bg-slate-50 shadow-lg shadow-black/15 py-2 flex items-center gap-x-2 px-3'>
45+
<div
46+
ref={setNodeRef}
47+
style={style}
48+
className={`${transparent ? 'opacity-25' : ''} w-full min-h-12 max-h-36 first:rounded-b-xl rounded-xl bg-slate-50 shadow-lg shadow-black/15 py-2 flex items-center gap-x-2 px-3`}>
2749
<button>
2850
<IoCloseOutline className='w-7 h-7' />
2951
</button>

Task Snap Space/src/pages/app/task/category.tsx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ type Props = {
1313
export default function TaskCategory({ taskList, type }: Props) {
1414
const taskIds = useMemo(() => taskList.map((task) => task.id), [taskList]);
1515

16-
const { setNodeRef } = useDroppable({
16+
const { setNodeRef, over } = useDroppable({
1717
id: type,
1818
data: {
1919
type,
@@ -27,6 +27,31 @@ export default function TaskCategory({ taskList, type }: Props) {
2727
completed: { heading: 'Completed', bg: 'bg-[#4F46E5]' },
2828
}[type];
2929

30+
if (over?.data.current?.task !== undefined) {
31+
if (over?.data.current?.task.columnId !== type) {
32+
return (
33+
<div>
34+
<div
35+
className={`flex justify-between items-center ${bg} text-white shadow-xl shadow-black/50 font-bold px-3 py-2 rounded-tl-xl rounded-tr-xl`}>
36+
<h3>{heading}</h3>
37+
<FiCheckSquare className='text-2xl' />
38+
</div>
39+
40+
<div ref={setNodeRef} className={`${bg} relative bg-opacity-25 flex flex-col gap-y-2.5 pb-12`}>
41+
<SortableContext items={taskIds} strategy={verticalListSortingStrategy}>
42+
{taskList.map((task) => (
43+
<TaskCard key={task.id} task={task} bg={bg} transparent />
44+
))}
45+
</SortableContext>
46+
<p className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center text-xl text-slate-950'>
47+
Move Task Here
48+
</p>
49+
</div>
50+
</div>
51+
);
52+
}
53+
}
54+
3055
return (
3156
<div>
3257
<div
@@ -38,7 +63,7 @@ export default function TaskCategory({ taskList, type }: Props) {
3863
<div ref={setNodeRef} className='bg-slate-100 flex flex-col gap-y-2.5 pb-12'>
3964
<SortableContext items={taskIds} strategy={verticalListSortingStrategy}>
4065
{taskList.map((task) => (
41-
<TaskCard key={task.id} task={task} />
66+
<TaskCard key={task.id} task={task} bg={bg} />
4267
))}
4368
</SortableContext>
4469
</div>

0 commit comments

Comments
 (0)