Adjustments to Drag and Drop features, as well as theme features
This commit is contained in:
parent
9a1aad6ed0
commit
0d7336858c
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useDroppable } from "@dnd-kit/core";
|
||||
import { useDndContext, useDroppable } from "@dnd-kit/core";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { GripVertical, MoreVertical, Trash2 } from "lucide-react";
|
||||
|
||||
|
|
@ -21,6 +21,19 @@ import type { CategoryDTO } from "@/types/board";
|
|||
export function CategoryLane({ category }: { category: CategoryDTO }) {
|
||||
const { removeCategory } = useBoard();
|
||||
|
||||
// The lane itself is sortable (so lanes can be reordered), which
|
||||
// registers its *entire* rect -- header, cards, empty space, all of it --
|
||||
// as a droppable. Dragging a group card over empty lane space then had
|
||||
// two overlapping droppables to resolve against: this lane's own
|
||||
// "category" droppable and the narrower "category-dropzone" below. With
|
||||
// `closestCenter`, the much larger lane rect often won, so drop handling
|
||||
// never saw a "group" or "category-dropzone" target and silently did
|
||||
// nothing. Disabling this lane's droppable side while a *group* (not a
|
||||
// lane) is being dragged removes it from collision detection entirely,
|
||||
// leaving only the group cards and the dropzone as valid targets.
|
||||
const { active } = useDndContext();
|
||||
const isDraggingGroup = active?.data.current?.type === "group";
|
||||
|
||||
const {
|
||||
setNodeRef,
|
||||
setActivatorNodeRef,
|
||||
|
|
@ -32,6 +45,7 @@ export function CategoryLane({ category }: { category: CategoryDTO }) {
|
|||
} = useSortable({
|
||||
id: category.id,
|
||||
data: { type: "category" },
|
||||
disabled: { draggable: false, droppable: isDraggingGroup },
|
||||
});
|
||||
|
||||
const { setNodeRef: setDropzoneRef } = useDroppable({
|
||||
|
|
@ -75,7 +89,7 @@ export function CategoryLane({ category }: { category: CategoryDTO }) {
|
|||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem
|
||||
variant="destructive"
|
||||
onSelect={() => removeCategory(category.id)}
|
||||
onClick={() => removeCategory(category.id)}
|
||||
>
|
||||
<Trash2 className="size-4" />
|
||||
Delete category
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { useTheme } from "next-themes";
|
||||
|
|
@ -47,10 +47,18 @@ export function GroupCard({ group }: { group: GroupDTO }) {
|
|||
// portaled Popover/Dialog content nested inside the card (the notes
|
||||
// editor, the "add to-do" popover). Wiring the same node as the
|
||||
// activator restores the target check.
|
||||
function setCardRef(node: HTMLDivElement | null) {
|
||||
setNodeRef(node);
|
||||
setActivatorNodeRef(node);
|
||||
}
|
||||
//
|
||||
// This must be memoized: a fresh function identity on every render makes
|
||||
// React detach+reattach the ref each time, which during a drag (many
|
||||
// re-renders as transform/isDragging change) resets dnd-kit's node
|
||||
// registration and broke drop detection entirely.
|
||||
const setCardRef = useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
setNodeRef(node);
|
||||
setActivatorNodeRef(node);
|
||||
},
|
||||
[setNodeRef, setActivatorNodeRef]
|
||||
);
|
||||
|
||||
const color = getGroupColor(group.color);
|
||||
const borderColor = resolvedTheme === "dark" ? color.dark : color.light;
|
||||
|
|
@ -90,7 +98,7 @@ export function GroupCard({ group }: { group: GroupDTO }) {
|
|||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem
|
||||
variant="destructive"
|
||||
onSelect={() => removeGroup(group.id, group.categoryId)}
|
||||
onClick={() => removeGroup(group.id, group.categoryId)}
|
||||
>
|
||||
<Trash2 className="size-4" />
|
||||
Delete group
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export function ThemeToggle({ collapsed }: { collapsed?: boolean }) {
|
|||
/>
|
||||
<DropdownMenuContent align="start" side="right">
|
||||
{OPTIONS.map((option) => (
|
||||
<DropdownMenuItem key={option.value} onSelect={() => setTheme(option.value)}>
|
||||
<DropdownMenuItem key={option.value} onClick={() => setTheme(option.value)}>
|
||||
<option.icon className="size-4" />
|
||||
{option.label}
|
||||
</DropdownMenuItem>
|
||||
|
|
|
|||
Loading…
Reference in New Issue