SortableSection.tsx 1.1 KB

123456789101112131415161718192021222324252627282930313233343536
  1. import { useSortable } from '@dnd-kit/sortable'
  2. import { GripVertical } from 'lucide-react'
  3. import type { CSSProperties, ReactNode } from 'react'
  4. import { cn } from 'ui'
  5. type SortableSectionProps = {
  6. id: string
  7. children: ReactNode
  8. }
  9. export const SortableSection = ({ id, children }: SortableSectionProps) => {
  10. const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
  11. id,
  12. })
  13. const style: CSSProperties = {
  14. transform: transform
  15. ? `translate3d(${Math.round(transform.x)}px, ${Math.round(transform.y)}px, 0)`
  16. : undefined,
  17. transition,
  18. }
  19. return (
  20. <div ref={setNodeRef} style={style} className="relative will-change-transform">
  21. <button
  22. aria-label="Drag to reorder section"
  23. className="absolute -left-6 top-2 text-foreground-muted hover:text-foreground focus:outline-hidden cursor-grab active:cursor-grabbing"
  24. {...attributes}
  25. {...listeners}
  26. >
  27. <GripVertical size={14} />
  28. </button>
  29. <div className={cn(isDragging && 'opacity-70')}>{children}</div>
  30. </div>
  31. )
  32. }