Skip to content

Instantly share code, notes, and snippets.

@denisraslov
Last active May 14, 2025 21:17
Show Gist options
  • Select an option

  • Save denisraslov/420df4698fc65b113840027365b6f8e5 to your computer and use it in GitHub Desktop.

Select an option

Save denisraslov/420df4698fc65b113840027365b6f8e5 to your computer and use it in GitHub Desktop.
import { DndContext, useDraggable, useDroppable } from '@dnd-kit/core'
// Draggable model image component
function DraggableProductImage({ imageId }) {
const { attributes, listeners, setNodeRef, transform } = useDraggable({
id: `image_${imageId}`,
})
return (
<img
ref={setNodeRef}
style={{
transform: transform
? `translate(${transform.x}px, ${transform.y}px)`
: undefined,
padding: 12,
border: '1px solid #ccc',
cursor: 'grab',
}}
{...listeners}
{...attributes}
/>
)
}
// Droppable model container which contains images
function DroppableModelContainer({ modelId, children }) {
const { setNodeRef, isOver } = useDroppable({ id: `model_${modelId}` })
return (
<div
ref={setNodeRef}
style={{
height: 120,
border: '2px dashed #bbb',
background: isOver ? '#d3f9d8' : '#fafafa',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{children}
</div>
)
}
type Model = {
id: number
images: {
id: number
}[]
}
export default function App({ models }: { models: Model[] }) {
return (
<DndContext
onDragEnd={({ over }) => {
if (over) {
// Drag-n-drop finished on FE, check the IDs of model and image in the arguments
// and send a request to BE to link an image to a model
}
}}
>
{models.map(({ images }) => (
<DroppableModelContainer modelId={1}>
{images.map((image) => (
<DraggableProductImage imageId={image.id} />
))}
</DroppableModelContainer>
))}
<button
onClick={() => {
// send create model API request and add a new model to the "models" array
}}
>
Add model
</button>
</DndContext>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment