feat: introduce Sortable component with DnD capabilities and Storybook examples#54
feat: introduce Sortable component with DnD capabilities and Storybook examples#54
Conversation
…k examples - Added `Sortable`, `SortableItem`, `SortableDragHandle`, `SortableProvider`, and `DragOverlay` components using `@dnd-kit` for drag-and-drop functionality. - Integrated examples for vertical, horizontal, grid, drag handle, multiple lists, and custom UI in `Sortable.stories.tsx` within Storybook. - Exported the new components in `ui/index.ts` for external use. - Updated `package.json` to include `@dnd-kit` dependencies.
📝 WalkthroughWalkthroughAdds a new Sortable UI system built on dnd-kit (container, item, drag handle, provider, and DragOverlay), Storybook stories demonstrating usages, new dnd-kit dependencies in package.json, and adjusts public exports including PopoverPortal and PopoverHeader while removing PopoverClose and PopoverArrow. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant App as App State
participant Sortable
participant Dnd as DndContext
participant Item as SortableItem(s)
User->>Item: pointer down (activate handle)
Item->>Dnd: startDrag(activeId)
Dnd->>Sortable: onDragStart(activeId)
Sortable->>App: mark active, prepare overlay
User->>Dnd: pointer move (drag)
Dnd->>Sortable: onDragOver(target)
Sortable->>App: compute new order (arrayMove)
App-->>Sortable: updated items
User->>Dnd: release pointer
Dnd->>Sortable: onDragEnd
Sortable->>App: commit order, call onValueChange/onMove
Sortable->>Dnd: clear active/overlay
Item->>Item: remove drag styling
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
src/components/ui/sortable.tsx (3)
1-1:"use strict"is unnecessary in TypeScript/ESM files.TypeScript modules and ES modules are always in strict mode. This directive is a no-op here.
🧹 Remove unnecessary directive
-"use strict"; - import * as React from "react";🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ui/sortable.tsx` at line 1, Remove the unnecessary "use strict" directive at the top of this module: delete the standalone string literal "use strict" from src/components/ui/sortable.tsx since TypeScript/ESM modules are already strict; no other changes required.
232-250:SortableProviderdoesn't exposeonDragEnd/onDragStarthandling — document the intended usage.
SortableProvideris a bareDndContextwrapper with no built-in state management for active items or reordering. This is presumably intended for advanced use cases (e.g., cross-list dragging), but there are no stories or documentation showing how a consumer would wire it up. A doc comment or a corresponding Storybook story usingSortableProviderwith<Sortable container={false}>would help clarify the intended pattern.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ui/sortable.tsx` around lines 232 - 250, SortableProvider currently wraps DndContext but doesn't document or demonstrate how consumers should handle drag lifecycle (onDragEnd/onDragStart) or manage active item/reordering state; add a short doc comment above the SortableProvider function explaining that it intentionally forwards DndContext props and that consumers must supply handlers like onDragEnd/onDragStart (and maintain item order/active id) for reordering or cross-list behavior, and add a Storybook story demonstrating usage (e.g., using SortableProvider with sensors prop and a consumer-managed onDragEnd that updates an array, and an example using <Sortable container={false}> for advanced patterns) so users can see the expected wiring.
36-49: Consider documenting theonMovevsonValueChangedistinction.The props expose both
onMove(called with the rawDragEndEvent) andonValueChange(called with the reordered array). Their relationship isn't immediately obvious —onMovefires on every drag end regardless of whether a reorder occurred (line 95), whileonValueChangeonly fires when items actually swap. A JSDoc comment ononMovewould help consumers understand the contract.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ui/sortable.tsx` around lines 36 - 49, Add a JSDoc comment to the onMove prop in the SortableProps interface clarifying its contract: state that onMove receives the raw DragEndEvent (type DragEndEvent) and is invoked on every drag end regardless of whether items changed, while onValueChange is only called when the items array actually reorders; mention that consumers can use onMove for low-level event handling and onValueChange for finalized reordered data. Reference the SortableProps interface, onMove, onValueChange, and DragEndEvent so readers can find the relevant types and behavior.src/components/ui/Sortable.stories.tsx (1)
4-8: Consider re-exporting sorting strategies from the sortable module.Stories (and consumers) currently import
verticalListSortingStrategy,horizontalListSortingStrategy, andrectSortingStrategydirectly from@dnd-kit/sortable. For a cleaner DX, re-export these from yoursortable.tsxmodule so consumers don't need to add@dnd-kit/sortableas a direct dependency or know the underlying library.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ui/Sortable.stories.tsx` around lines 4 - 8, Update your sortable.tsx module to re-export verticalListSortingStrategy, horizontalListSortingStrategy, and rectSortingStrategy from "@dnd-kit/sortable" (e.g., export { verticalListSortingStrategy, horizontalListSortingStrategy, rectSortingStrategy } from "@dnd-kit/sortable"), and then change imports in Sortable.stories.tsx to import these strategies from your sortable module instead of directly from "@dnd-kit/sortable" so consumers can import strategies via your component module.src/components/ui/popover.tsx (1)
15-17: Inconsistent export style forPopoverPortal.
PopoverPortaluses an inlineexport functiondeclaration while all other components in this file are declared withoutexportand then exported together in the named export block at the bottom (Lines 87–94). Consider movingPopoverPortalinto the bottom export block for consistency.♻️ Suggested fix
-export function PopoverPortal({ ...props }: PopoverPrimitive.Portal.Props) { +function PopoverPortal({ ...props }: PopoverPrimitive.Portal.Props) { return <PopoverPrimitive.Portal data-slot="popover-portal" {...props} />; }Then add it to the bottom export (which it already is in
index.ts, but keep the source consistent):export { Popover, PopoverContent, PopoverDescription, PopoverHeader, + PopoverPortal, PopoverTitle, PopoverTrigger, }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ui/popover.tsx` around lines 15 - 17, PopoverPortal is declared with an inline export while the rest of the components are declared without export and then exported together; change PopoverPortal to a non-exported function declaration (function PopoverPortal(props: PopoverPrimitive.Portal.Props) { ... }) so it matches the other components, and ensure its identifier PopoverPortal is included in the named export block at the bottom alongside the other components; keep the existing JSX (<PopoverPrimitive.Portal data-slot="popover-portal" {...props} />) and type (PopoverPrimitive.Portal.Props) intact.src/index.ts (1)
146-151: Re-exportingDragOverlaydirectly from dnd-kit couples the public API to the library.
DragOverlayis a raw dnd-kit component re-exported as part of this package's public surface. If dnd-kit's API changes in a future version, it becomes a breaking change for your consumers. Consider wrapping it in a thin component (similar to howSortablewrapsDndContext) so you own the API contract.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/index.ts` around lines 146 - 151, The public export currently re-exports DragOverlay from dnd-kit (symbol DragOverlay in src/index.ts) which couples our API to the external library; create a thin wrapper component (e.g., OurDragOverlay or SortableDragOverlay) that imports DragOverlay from '@dnd-kit/core', forwards props/children and any refs, and export that wrapper from the module instead of re-exporting DragOverlay directly; update the export list (replace DragOverlay with the new wrapper name), add matching TypeScript types/exports for the wrapper, and adjust any internal imports/tests to use the new wrapper so consumers rely on our stable API surface.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@package.json`:
- Around line 60-64: Remove the unused and incompatible dependency entry
"@dnd-kit/react": "^0.3.0" from package.json (it's not imported anywhere and
conflicts with the legacy dnd-kit packages like "@dnd-kit/core" and
"@dnd-kit/sortable"); delete that line from the dependencies block, then update
your lockfile by reinstalling (run npm install or yarn install) so the lockfile
and node_modules are consistent.
In `@src/components/ui/Sortable.stories.tsx`:
- Around line 319-362: The MultipleLists story uses two independent Sortable
components (each with its own DndContext) so items cannot be dragged between
lists; either change the implementation to share a single
SortableProvider/DndContext around both lists to enable cross-list dragging
(wrap both lists with a common SortableProvider or move a single DndContext to
encompass both Sortable instances and coordinate on a shared onValueChange
handler for itemsA/itemsB and SortableItem ids), or if cross-list dragging is
not desired, rename MultipleLists to IndependentLists or SideBySideLists to make
behavior clear; update the story accordingly (referencing MultipleLists,
Sortable, SortableProvider/DndContext, SortableItem, itemsA/itemsB,
setItemsA/setItemsB).
In `@src/components/ui/sortable.tsx`:
- Around line 80-109: The DndContext handlers are being overridden by the
trailing {...props}; to fix, destructure onDragStart, onDragEnd, and
onDragCancel from the component props (keep onValueChange, onMove, etc.), then
compose them inside the DndContext: call your internal logic (setActiveId,
arrayMove + onValueChange, setActiveId(null), onMove) and after that call the
user-supplied handlers (the destructured onDragStart/onDragEnd/onDragCancel)
with the same event; finally spread the remaining props (the rest) into
DndContext so user props cannot silently override the internal handlers. Ensure
references to DndContext, onDragEnd, onDragStart, onDragCancel, setActiveId,
onMove, and onValueChange are updated accordingly.
---
Nitpick comments:
In `@src/components/ui/popover.tsx`:
- Around line 15-17: PopoverPortal is declared with an inline export while the
rest of the components are declared without export and then exported together;
change PopoverPortal to a non-exported function declaration (function
PopoverPortal(props: PopoverPrimitive.Portal.Props) { ... }) so it matches the
other components, and ensure its identifier PopoverPortal is included in the
named export block at the bottom alongside the other components; keep the
existing JSX (<PopoverPrimitive.Portal data-slot="popover-portal" {...props} />)
and type (PopoverPrimitive.Portal.Props) intact.
In `@src/components/ui/Sortable.stories.tsx`:
- Around line 4-8: Update your sortable.tsx module to re-export
verticalListSortingStrategy, horizontalListSortingStrategy, and
rectSortingStrategy from "@dnd-kit/sortable" (e.g., export {
verticalListSortingStrategy, horizontalListSortingStrategy, rectSortingStrategy
} from "@dnd-kit/sortable"), and then change imports in Sortable.stories.tsx to
import these strategies from your sortable module instead of directly from
"@dnd-kit/sortable" so consumers can import strategies via your component
module.
In `@src/components/ui/sortable.tsx`:
- Line 1: Remove the unnecessary "use strict" directive at the top of this
module: delete the standalone string literal "use strict" from
src/components/ui/sortable.tsx since TypeScript/ESM modules are already strict;
no other changes required.
- Around line 232-250: SortableProvider currently wraps DndContext but doesn't
document or demonstrate how consumers should handle drag lifecycle
(onDragEnd/onDragStart) or manage active item/reordering state; add a short doc
comment above the SortableProvider function explaining that it intentionally
forwards DndContext props and that consumers must supply handlers like
onDragEnd/onDragStart (and maintain item order/active id) for reordering or
cross-list behavior, and add a Storybook story demonstrating usage (e.g., using
SortableProvider with sensors prop and a consumer-managed onDragEnd that updates
an array, and an example using <Sortable container={false}> for advanced
patterns) so users can see the expected wiring.
- Around line 36-49: Add a JSDoc comment to the onMove prop in the SortableProps
interface clarifying its contract: state that onMove receives the raw
DragEndEvent (type DragEndEvent) and is invoked on every drag end regardless of
whether items changed, while onValueChange is only called when the items array
actually reorders; mention that consumers can use onMove for low-level event
handling and onValueChange for finalized reordered data. Reference the
SortableProps interface, onMove, onValueChange, and DragEndEvent so readers can
find the relevant types and behavior.
In `@src/index.ts`:
- Around line 146-151: The public export currently re-exports DragOverlay from
dnd-kit (symbol DragOverlay in src/index.ts) which couples our API to the
external library; create a thin wrapper component (e.g., OurDragOverlay or
SortableDragOverlay) that imports DragOverlay from '@dnd-kit/core', forwards
props/children and any refs, and export that wrapper from the module instead of
re-exporting DragOverlay directly; update the export list (replace DragOverlay
with the new wrapper name), add matching TypeScript types/exports for the
wrapper, and adjust any internal imports/tests to use the new wrapper so
consumers rely on our stable API surface.
package.json
Outdated
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
dnd-kit npm packages @dnd-kit/core @dnd-kit/sortable @dnd-kit/react compatibility 2025 2026
💡 Result:
Compatibility (2025–2026)
1) “Legacy” dnd-kit (stable)
- Use
@dnd-kit/core+@dnd-kit/sortabletogether (Sortable is built on top of Core). [1][2] - Latest visible package versions (as of the sources crawled):
@dnd-kit/core6.3.1 and@dnd-kit/sortable10.0.0. [3][2]
2) “New” dnd-kit (rewrite)
@dnd-kit/reactis the new React API layer (published as 0.x, e.g. 0.1.21 in the npm listing snippet). [4]- The official migration guide says to migrate from
@dnd-kit/core/@dnd-kit/sortable/@dnd-kit/utilitiesto@dnd-kit/react(and@dnd-kit/helpers), i.e. it’s a replacement track, not an add-on. [5] - The legacy docs explicitly note there’s a new version and recommend using the latest instead of the legacy install path. [6]
Practical takeaway
- Don’t mix
@dnd-kit/react(new 0.x line) with the legacy@dnd-kit/core/@dnd-kit/sortablestack in the same implementation—pick one track:- Legacy:
@dnd-kit/core+@dnd-kit/sortable[1][2] - New:
@dnd-kit/react(+@dnd-kit/helpers, plus other new-scope packages as needed) [5][4]
- Legacy:
Sources: [1] @dnd-kit Sortable docs [2] Snyk package info for @dnd-kit/sortable [3] npm listing snippet for @dnd-kit/core [4] npm listing snippet for @dnd-kit/react [5] official migration guide (core → react) [6] legacy installation page noting a new version is available.
🏁 Script executed:
# Find and examine sortable.tsx to see which APIs are actually imported
fd -e tsx -e ts | xargs rg -l "sortable.tsx|useSortable|SortableContext" | head -5Repository: getdokan/plugin-ui
Length of output: 92
🏁 Script executed:
# Also check the actual package.json to see the full context
cat -n package.json | sed -n '50,75p'Repository: getdokan/plugin-ui
Length of output: 1084
🏁 Script executed:
cat -n src/components/ui/sortable.tsx | head -50Repository: getdokan/plugin-ui
Length of output: 1696
🏁 Script executed:
# Search for imports from dnd-kit packages
rg "from ['\"]@dnd-kit" src/components/ui/sortable.tsx -A 1 -B 1Repository: getdokan/plugin-ui
Length of output: 270
🏁 Script executed:
rg "@dnd-kit/react" --type ts --type tsxRepository: getdokan/plugin-ui
Length of output: 89
🏁 Script executed:
rg "@dnd-kit/react" --type typescriptRepository: getdokan/plugin-ui
Length of output: 96
🏁 Script executed:
# Also try searching without type restriction
rg "@dnd-kit/react" src/Repository: getdokan/plugin-ui
Length of output: 44
Remove unused @dnd-kit/react dependency — incompatible with the legacy dnd-kit stack in use.
The codebase uses the legacy dnd-kit track (@dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities), which is explicitly incompatible with @dnd-kit/react. The latter is a replacement API from a complete dnd-kit rewrite (available as 0.x pre-release) and should not be mixed with the legacy packages. A search of the entire codebase confirms @dnd-kit/react is never imported or used anywhere—only the legacy packages are referenced in sortable.tsx. Remove @dnd-kit/react@^0.3.0 from dependencies.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@package.json` around lines 60 - 64, Remove the unused and incompatible
dependency entry "@dnd-kit/react": "^0.3.0" from package.json (it's not imported
anywhere and conflicts with the legacy dnd-kit packages like "@dnd-kit/core" and
"@dnd-kit/sortable"); delete that line from the dependencies block, then update
your lockfile by reinstalling (run npm install or yarn install) so the lockfile
and node_modules are consistent.
| export const MultipleLists: Story = { | ||
| render: () => { | ||
| function Demo() { | ||
| const [itemsA, setItemsA] = useState([ | ||
| { id: "A1", content: "A1" }, | ||
| { id: "A2", content: "A2" }, | ||
| ]); | ||
| const [itemsB, setItemsB] = useState([ | ||
| { id: "B1", content: "B1" }, | ||
| { id: "B2", content: "B2" }, | ||
| ]); | ||
|
|
||
| return ( | ||
| <div className="flex gap-8 p-4"> | ||
| <div className="w-48 space-y-4"> | ||
| <h3 className="font-bold">List A</h3> | ||
| <Sortable items={itemsA} onValueChange={setItemsA}> | ||
| <div className="min-h-[100px] rounded-lg border bg-muted/50 p-2 space-y-2"> | ||
| {itemsA.map(item => ( | ||
| <SortableItem key={item.id} id={item.id}> | ||
| <div className="rounded border bg-card p-2 shadow-sm text-center">{item.content}</div> | ||
| </SortableItem> | ||
| ))} | ||
| </div> | ||
| </Sortable> | ||
| </div> | ||
| <div className="w-48 space-y-4"> | ||
| <h3 className="font-bold">List B</h3> | ||
| <Sortable items={itemsB} onValueChange={setItemsB}> | ||
| <div className="min-h-[100px] rounded-lg border bg-muted/50 p-2 space-y-2"> | ||
| {itemsB.map(item => ( | ||
| <SortableItem key={item.id} id={item.id}> | ||
| <div className="rounded border bg-card p-2 shadow-sm text-center">{item.content}</div> | ||
| </SortableItem> | ||
| ))} | ||
| </div> | ||
| </Sortable> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| return <Demo />; | ||
| }, | ||
| }; |
There was a problem hiding this comment.
MultipleLists story doesn't demonstrate cross-list dragging.
Each list has its own independent <Sortable> (and thus its own DndContext), so items can only be reordered within each list, not dragged between them. If cross-list DnD is intended, both lists would need to share a single SortableProvider. If the intent is just "two independent sortable lists on one page," consider renaming to something like IndependentLists or SideBySideLists to set correct expectations.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/ui/Sortable.stories.tsx` around lines 319 - 362, The
MultipleLists story uses two independent Sortable components (each with its own
DndContext) so items cannot be dragged between lists; either change the
implementation to share a single SortableProvider/DndContext around both lists
to enable cross-list dragging (wrap both lists with a common SortableProvider or
move a single DndContext to encompass both Sortable instances and coordinate on
a shared onValueChange handler for itemsA/itemsB and SortableItem ids), or if
cross-list dragging is not desired, rename MultipleLists to IndependentLists or
SideBySideLists to make behavior clear; update the story accordingly
(referencing MultipleLists, Sortable, SortableProvider/DndContext, SortableItem,
itemsA/itemsB, setItemsA/setItemsB).
| return ( | ||
| <DndContext | ||
| sensors={sensors} | ||
| collisionDetection={collisionDetection} | ||
| onDragStart={(event) => setActiveId(event.active.id)} | ||
| onDragEnd={(event) => { | ||
| const { active, over } = event; | ||
| if (over && active.id !== over.id) { | ||
| const oldIndex = items.findIndex((item) => item.id === active.id); | ||
| const newIndex = items.findIndex((item) => item.id === over.id); | ||
|
|
||
| if (oldIndex !== -1 && newIndex !== -1) { | ||
| onValueChange?.(arrayMove(items, oldIndex, newIndex)); | ||
| } | ||
| } | ||
| onMove?.(event); | ||
| setActiveId(null); | ||
| }} | ||
| onDragCancel={() => setActiveId(null)} | ||
| {...props} | ||
| > | ||
| {content} | ||
| {overlay && ( | ||
| <DragOverlay> | ||
| {activeId ? overlay : null} | ||
| </DragOverlay> | ||
| )} | ||
| </DndContext> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
{...props} spread after inline handlers will silently override internal drag logic.
SortableProps extends DndContextProps, so onDragStart, onDragEnd, and onDragCancel are not destructured out and remain in ...props. Since {...props} is spread after the explicit handlers (line 99), React uses the last value — meaning a consumer passing onDragEnd will completely bypass the internal arrayMove reordering logic.
Move {...props} before the inline handlers, or destructure onDragStart/onDragEnd/onDragCancel from props and compose them with the internal logic.
🐛 Proposed fix — destructure and compose handlers
const Sortable = <TData extends { id: UniqueIdentifier }>({
items,
onValueChange,
onMove,
strategy = verticalListSortingStrategy,
children,
overlay,
sensors: propSensors,
collisionDetection = closestCenter,
container = true,
+ onDragStart: onDragStartProp,
+ onDragEnd: onDragEndProp,
+ onDragCancel: onDragCancelProp,
...props
}: SortableProps<TData>) => {
const [activeId, setActiveId] = React.useState<UniqueIdentifier | null>(null);
...
return (
<DndContext
sensors={sensors}
collisionDetection={collisionDetection}
- onDragStart={(event) => setActiveId(event.active.id)}
- onDragEnd={(event) => {
+ onDragStart={(event) => {
+ setActiveId(event.active.id);
+ onDragStartProp?.(event);
+ }}
+ onDragEnd={(event) => {
const { active, over } = event;
if (over && active.id !== over.id) {
const oldIndex = items.findIndex((item) => item.id === active.id);
const newIndex = items.findIndex((item) => item.id === over.id);
if (oldIndex !== -1 && newIndex !== -1) {
onValueChange?.(arrayMove(items, oldIndex, newIndex));
}
}
onMove?.(event);
setActiveId(null);
+ onDragEndProp?.(event);
+ }}
+ onDragCancel={(event) => {
+ setActiveId(null);
+ onDragCancelProp?.(event);
}}
- onDragCancel={() => setActiveId(null)}
{...props}
>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/ui/sortable.tsx` around lines 80 - 109, The DndContext
handlers are being overridden by the trailing {...props}; to fix, destructure
onDragStart, onDragEnd, and onDragCancel from the component props (keep
onValueChange, onMove, etc.), then compose them inside the DndContext: call your
internal logic (setActiveId, arrayMove + onValueChange, setActiveId(null),
onMove) and after that call the user-supplied handlers (the destructured
onDragStart/onDragEnd/onDragCancel) with the same event; finally spread the
remaining props (the rest) into DndContext so user props cannot silently
override the internal handlers. Ensure references to DndContext, onDragEnd,
onDragStart, onDragCancel, setActiveId, onMove, and onValueChange are updated
accordingly.
# Conflicts: # package.json
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/index.ts (1)
146-151: ExportDragOverlayPropstype alongsideDragOverlayfor API consistency.
DragOverlay(line 151) is exported without a matching props type export, while the other Sortable-related components have type exports (lines 221–224):SortableProps,SortableItemProps,SortableDragHandleProps, andSortableProviderProps. Consumers needing to type-check or extendDragOverlayprops would have to import directly from@dnd-kit/react. AddDragOverlayPropsto maintain consistent API design.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/index.ts` around lines 146 - 151, Export the DragOverlayProps type alongside the existing DragOverlay export to maintain API consistency: add an export of DragOverlayProps (re-exporting the type from the same module you import DragOverlay from, e.g., `@dnd-kit/react`) so consumers can import { DragOverlay, DragOverlayProps } from this package; update the export list where Sortable, SortableItem, SortableDragHandle, SortableProvider and DragOverlay are exported to include DragOverlayProps.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/index.ts`:
- Around line 137-143: The barrel export in src/index.ts has dropped
PopoverClose and PopoverArrow which still exist in
src/components/ui/popover.tsx; restore the public API by re-adding PopoverClose
and PopoverArrow to the export list in src/index.ts (or, if the removal is
intentional, add a changelog/migration note explaining the breaking change and
update any consumer docs). Locate the export block containing Popover,
PopoverContent, PopoverDescription, PopoverHeader, PopoverPortal, PopoverTitle,
PopoverTrigger and include PopoverClose and PopoverArrow there so consumers
importing from the main barrel continue to work.
- Around line 146-151: There are mixed dnd-kit stacks being exported (Sortable,
SortableItem, SortableDragHandle, SortableProvider, DragOverlay) causing runtime
conflicts; pick one approach and update the exports and imports accordingly:
either remove all usages and exports of `@dnd-kit/react` (DragOverlay and any
react-stack imports) and keep the legacy stack (ensure
src/components/ui/sortable.tsx uses `@dnd-kit/core`@^6.3.x +
`@dnd-kit/sortable`@^10.0.0 and export only Sortable, SortableItem,
SortableDragHandle, SortableProvider), or migrate fully to the new stack by
removing `@dnd-kit/core` and `@dnd-kit/sortable`, update
src/components/ui/sortable.tsx to use `@dnd-kit/react`@0.3.0 (import sortable
utilities from `@dnd-kit/react/sortable`) and export the new equivalents
(including DragOverlay) consistently; make sure imports/exports across the
codebase match the chosen stack.
---
Nitpick comments:
In `@src/index.ts`:
- Around line 146-151: Export the DragOverlayProps type alongside the existing
DragOverlay export to maintain API consistency: add an export of
DragOverlayProps (re-exporting the type from the same module you import
DragOverlay from, e.g., `@dnd-kit/react`) so consumers can import { DragOverlay,
DragOverlayProps } from this package; update the export list where Sortable,
SortableItem, SortableDragHandle, SortableProvider and DragOverlay are exported
to include DragOverlayProps.
| Popover, | ||
| PopoverArrow, | ||
| PopoverClose, | ||
| PopoverContent, | ||
| PopoverDescription, | ||
| PopoverHeader, | ||
| PopoverPortal, | ||
| PopoverTitle, | ||
| PopoverTrigger, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if PopoverClose and PopoverArrow are still defined/exported anywhere in the codebase
echo "=== Searching for PopoverClose and PopoverArrow in TypeScript files ==="
rg -n 'PopoverClose|PopoverArrow' --type=ts -A 2 -B 2Repository: getdokan/plugin-ui
Length of output: 995
🏁 Script executed:
#!/bin/bash
# Get the current state of src/index.ts around the Popover export section
echo "=== Current state of Popover exports in src/index.ts ==="
head -160 src/index.ts | tail -40Repository: getdokan/plugin-ui
Length of output: 956
🏁 Script executed:
#!/bin/bash
# Check the import statements and what's being re-exported from the underlying ui package
echo "=== Popover imports in src/index.ts ==="
rg -n 'from.*popover|Popover' src/index.ts | head -20Repository: getdokan/plugin-ui
Length of output: 281
Breaking change: PopoverClose and PopoverArrow removed from barrel export.
PopoverClose and PopoverArrow still exist in src/components/ui/popover.tsx but are no longer re-exported from src/index.ts. This breaks the public API for consumers importing from the main barrel. Ensure this removal is intentional and communicated in a changelog or migration guide.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/index.ts` around lines 137 - 143, The barrel export in src/index.ts has
dropped PopoverClose and PopoverArrow which still exist in
src/components/ui/popover.tsx; restore the public API by re-adding PopoverClose
and PopoverArrow to the export list in src/index.ts (or, if the removal is
intentional, add a changelog/migration note explaining the breaking change and
update any consumer docs). Locate the export block containing Popover,
PopoverContent, PopoverDescription, PopoverHeader, PopoverPortal, PopoverTitle,
PopoverTrigger and include PopoverClose and PopoverArrow there so consumers
importing from the main barrel continue to work.
| // Sortable | ||
| Sortable, | ||
| SortableItem, | ||
| SortableDragHandle, | ||
| SortableProvider, | ||
| DragOverlay, |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
@dnd-kit/react 0.3.0 @dnd-kit/sortable 10.0.0 compatibility
💡 Result:
They’re not compatible.
@dnd-kit/sortable@10.0.0is part of the legacy stack and has a peer dependency on@dnd-kit/core^6.3.0(not@dnd-kit/react). [1]@dnd-kit/react@0.3.0is the new React package in the “migrate from@dnd-kit/coreto@dnd-kit/react” track, where you replace@dnd-kit/core+@dnd-kit/sortablewith@dnd-kit/react(+ related new packages). [2]- Sortable support in the new stack is exposed via
@dnd-kit/react/sortable(not@dnd-kit/sortable). [3]
So you should either:
- Stay legacy: use
@dnd-kit/core@^6.3.xwith@dnd-kit/sortable@10.0.0, or - Go new: use
@dnd-kit/react@0.3.0with@dnd-kit/react/sortable(matching the same new-version line). [1][2][3]
Sources: [1] [2] [3]
🏁 Script executed:
# Find and check package.json for actual dependencies and versions
fd -e package.json -type f | head -5Repository: getdokan/plugin-ui
Length of output: 232
🏁 Script executed:
# Find package.json correctly
find . -name "package.json" -type f | head -5Repository: getdokan/plugin-ui
Length of output: 76
🏁 Script executed:
# Check imports in src/index.ts
cat src/index.ts | head -20Repository: getdokan/plugin-ui
Length of output: 631
🏁 Script executed:
# Check package.json for `@dnd-kit` dependencies
cat package.json | grep -A 20 "@dnd-kit"Repository: getdokan/plugin-ui
Length of output: 914
🏁 Script executed:
# Look for dnd-kit imports in src/index.ts
rg "@dnd-kit|Sortable" src/index.ts -A 2 -B 2Repository: getdokan/plugin-ui
Length of output: 434
🏁 Script executed:
# Find where Sortable components are imported from
rg "from.*Sortable|from.*@dnd-kit" src/ -A 1 -B 1 | head -40Repository: getdokan/plugin-ui
Length of output: 659
🏁 Script executed:
# Check if there's a Sortable component file
find src -name "*ortable*" -o -name "*sortable*" | head -20Repository: getdokan/plugin-ui
Length of output: 131
Remove @dnd-kit/react or migrate to the new dnd-kit stack — do not mix them.
The codebase has incompatible @dnd-kit versions. @dnd-kit/sortable@10.0.0 is the legacy stack and requires @dnd-kit/core@^6.3.0, while @dnd-kit/react@0.3.0 is the new stack that replaces both. These are mutually exclusive—mixing them will cause runtime conflicts.
Choose one:
- Stay legacy: Remove
@dnd-kit/react, keep@dnd-kit/core@^6.3.1+@dnd-kit/sortable@^10.0.0(current setup insrc/components/ui/sortable.tsx). - Migrate to new: Remove
@dnd-kit/coreand@dnd-kit/sortable, use@dnd-kit/react@0.3.0and import sortable utilities from@dnd-kit/react/sortable.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/index.ts` around lines 146 - 151, There are mixed dnd-kit stacks being
exported (Sortable, SortableItem, SortableDragHandle, SortableProvider,
DragOverlay) causing runtime conflicts; pick one approach and update the exports
and imports accordingly: either remove all usages and exports of `@dnd-kit/react`
(DragOverlay and any react-stack imports) and keep the legacy stack (ensure
src/components/ui/sortable.tsx uses `@dnd-kit/core`@^6.3.x +
`@dnd-kit/sortable`@^10.0.0 and export only Sortable, SortableItem,
SortableDragHandle, SortableProvider), or migrate fully to the new stack by
removing `@dnd-kit/core` and `@dnd-kit/sortable`, update
src/components/ui/sortable.tsx to use `@dnd-kit/react`@0.3.0 (import sortable
utilities from `@dnd-kit/react/sortable`) and export the new equivalents
(including DragOverlay) consistently; make sure imports/exports across the
codebase match the chosen stack.
Summary by CodeRabbit