diff --git a/app/components/AbilitiesSelector.tsx b/app/components/AbilitiesSelector.tsx
index cfb059ce3..6920bb770 100644
--- a/app/components/AbilitiesSelector.tsx
+++ b/app/components/AbilitiesSelector.tsx
@@ -1,3 +1,5 @@
+import clsx from "clsx";
+import React from "react";
import invariant from "tiny-invariant";
import { abilities } from "~/modules/in-game-lists";
import type { BuildAbilitiesTupleWithUnknown } from "~/modules/in-game-lists/types";
@@ -40,6 +42,38 @@ export function AbilitiesSelector({
onChange(addAbility({ oldAbilities: selectedAbilities, ability }));
};
+ const [draggingAbility, setDraggingAbility] = React.useState<
+ typeof abilities[number] | undefined
+ >();
+
+ const onDragStart =
+ (ability: typeof abilities[number]) => (event: React.DragEvent) => {
+ setDraggingAbility(ability);
+ event.dataTransfer.setData("text/plain", JSON.stringify(ability));
+ };
+
+ const onDragEnd = () => {
+ setDraggingAbility(undefined);
+ };
+
+ const onDrop =
+ (atRowIndex: number, atAbilityIndex: number) =>
+ (event: React.DragEvent) => {
+ event.preventDefault();
+ const ability = JSON.parse(
+ event.dataTransfer.getData("text/plain")
+ ) as typeof abilities[number];
+
+ onChange(
+ addAbility({
+ oldAbilities: selectedAbilities,
+ ability,
+ atRowIndex,
+ atAbilityIndex,
+ })
+ );
+ };
+
return (
@@ -50,6 +84,13 @@ export function AbilitiesSelector({
ability={ability}
size={abilityI === 0 ? "MAIN" : "SUB"}
onClick={() => onSlotClick({ rowI, abilityI })}
+ dragStarted={!!draggingAbility}
+ dropAllowed={canPlaceAbilityAtSlot(
+ rowI,
+ abilityI,
+ draggingAbility
+ )}
+ onDrop={onDrop(rowI, abilityI)}
/>
))
)}
@@ -58,10 +99,15 @@ export function AbilitiesSelector({
{abilities.map((ability) => (