Skip to content

Commit

Permalink
Updated the Drag effect in the Draggable list (#232)
Browse files Browse the repository at this point in the history
* Updated the Drag effect in the Draggable list

* Removed unneeded class names.
  • Loading branch information
natashapl authored Jun 28, 2024
1 parent da882a5 commit 30d1af1
Showing 1 changed file with 74 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Children } from 'react';
import React, { Children, useState } from 'react';
import {
DndContext,
closestCenter,
Expand All @@ -7,6 +7,7 @@ import {
useSensor,
useSensors,
UniqueIdentifier,
DragOverlay,
} from '@dnd-kit/core';
import {
arrayMove,
Expand All @@ -24,6 +25,7 @@ type DraggableListProps = React.PropsWithChildren<{
order: UniqueIdentifier[];
updateOrder: (order: UniqueIdentifier[]) => void;
}>;

export const DraggableList: React.FC<DraggableListProps> = ({
children,
order,
Expand All @@ -35,19 +37,25 @@ export const DraggableList: React.FC<DraggableListProps> = ({
);

const arrayChildren = Children.toArray(children);
const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);

return (
<div
onFocus={event => {
onFocus={(event) => {
// Stop onFocus events from bubbling up to parent elements.
event.stopPropagation();
}}
>
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={event => {
onDragStart={(event) => {
setActiveId(event.active.id);
}}
onDragEnd={(event) => {
const { active, over } = event;
setActiveId(null);

if (over === null) {
return;
}
Expand All @@ -58,47 +66,107 @@ export const DraggableList: React.FC<DraggableListProps> = ({
updateOrder(newOrder);
}
}}
onDragCancel={() => {
setActiveId(null);
}}
>
<SortableContext items={order} strategy={verticalListSortingStrategy}>
{arrayChildren.map((child, index) => {
const patternId = order[index];
return (
<SortableItem key={patternId} id={patternId}>
<SortableItem
key={patternId}
id={patternId}
isActive={patternId === activeId}
isOver={patternId === activeId}
>
{child}
</SortableItem>
);
})}
</SortableContext>

<DragOverlay>
{activeId ? (
<SortableItemOverlay>
{arrayChildren[order.indexOf(activeId)]}
</SortableItemOverlay>
) : null}
</DragOverlay>
</DndContext>
</div>
);
};

const SortableItemOverlay = ({
children,
}: {
children: React.ReactNode;
}) => {
const context = useFormManagerStore((state) => state.context);

return (
<div
className={`${styles.draggableListWrapper} draggable-list-item-wrapper bg-white margin-bottom-3`}
style={{
boxShadow: '0 16px 24px rgba(0, 0, 0, 0.4)',
cursor: 'grabbing',
}}
>
<div className="grid-row draggable-list-item">
<div
className="grid-col-12 width-full draggable-list-button padding-2"
style={{ outline: '.25rem solid #783cb9' }}
>
<svg
className="usa-icon margin-x-auto display-block"
aria-hidden="true"
focusable="false"
role="img"
>
<use
xlinkHref={`${context.uswdsRoot}img/sprite.svg#drag_handle`}
></use>
</svg>
</div>
<div className="grid-col-12 grid-col">{children}</div>
</div>
</div>
);
};

const SortableItem = ({
id,
children,
isActive,
isOver,
}: {
id: UniqueIdentifier;
children: React.ReactNode;
isActive: boolean;
isOver: boolean;
}) => {
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ id });
const context = useFormManagerStore(state => state.context);
const context = useFormManagerStore((state) => state.context);

return (
<div
className={`${styles.draggableListWrapper} draggable-list-item-wrapper bg-white margin-bottom-3`}
ref={setNodeRef}
style={{
transform: CSS.Transform.toString(transform),
transform: CSS.Translate.toString(transform),
transition,
opacity: isOver ? 0.4 : 1,
border: isOver ? '1px dashed #8168B3' : 'none',
}}
>
<div className="grid-row draggable-list-item cursor-pointer">
<div
className="grid-col-12 width-full draggable-list-button cursor-grab padding-2"
{...listeners}
{...attributes}
style={{ outline: isActive ? 'none' : '' }}
>
<svg
className="usa-icon margin-x-auto display-block"
Expand Down

0 comments on commit 30d1af1

Please sign in to comment.