Refactor drag and drop for mobile
Replaced drag and drop functionality with a click-to-select and click-to-drop interaction for mobile friendliness. When a box in the container is clicked, columns become highlighted and clickable. Clicking a column drops the box there, and the columns return to their default state. Existing features like double-clicking and desktop drag-and-drop remain.
This commit is contained in:
parent
1700a6f984
commit
cbe2461204
1 changed files with 43 additions and 3 deletions
|
|
@ -24,6 +24,7 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
|
|||
const [highlightedBoxes, setHighlightedBoxes] = useState<Set<number>>(new Set());
|
||||
const [isAnimating, setIsAnimating] = useState(false);
|
||||
const [lastUsedColumn, setLastUsedColumn] = useState<number | null>(null);
|
||||
const [selectedBoxForMove, setSelectedBoxForMove] = useState<number | null>(null);
|
||||
|
||||
const totalBoxes = (n * (n + 1)) / 2;
|
||||
|
||||
|
|
@ -98,6 +99,33 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
|
|||
setDraggedBox(null);
|
||||
};
|
||||
|
||||
const handleBoxClick = (boxId: number) => {
|
||||
const box = boxes.find(b => b.id === boxId);
|
||||
if (!box || box.columnIndex !== null || isPlaying) return;
|
||||
|
||||
// Select box for moving
|
||||
setSelectedBoxForMove(boxId);
|
||||
};
|
||||
|
||||
const handleColumnClick = (e: React.MouseEvent, columnIndex: number) => {
|
||||
e.stopPropagation();
|
||||
if (selectedBoxForMove === null || isPlaying) return;
|
||||
|
||||
// Move selected box to this column
|
||||
setColumns(prev => prev.map((col, idx) =>
|
||||
idx === columnIndex ? [...col, selectedBoxForMove] : col
|
||||
));
|
||||
|
||||
// Update box location
|
||||
setBoxes(prev => prev.map(b =>
|
||||
b.id === selectedBoxForMove ? { ...b, columnIndex } : b
|
||||
));
|
||||
|
||||
// Track last used column and clear selection
|
||||
setLastUsedColumn(columnIndex);
|
||||
setSelectedBoxForMove(null);
|
||||
};
|
||||
|
||||
const handleDoubleClick = (boxId: number) => {
|
||||
const box = boxes.find(b => b.id === boxId);
|
||||
if (!box) return;
|
||||
|
|
@ -258,8 +286,14 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
|
|||
|
||||
const containerBoxes = boxes.filter(box => box.columnIndex === null);
|
||||
|
||||
const handleBackgroundClick = () => {
|
||||
if (selectedBoxForMove !== null) {
|
||||
setSelectedBoxForMove(null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto p-6 space-y-8">
|
||||
<div className="max-w-6xl mx-auto p-6 space-y-8" onClick={handleBackgroundClick}>
|
||||
<div className="text-center space-y-4">
|
||||
<h1 className="text-4xl font-bold text-foreground">Bulgarian Solitaire</h1>
|
||||
<p className="text-muted-foreground text-lg max-w-3xl mx-auto">
|
||||
|
|
@ -302,7 +336,10 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
|
|||
draggable={!isPlaying}
|
||||
onDragStart={(e) => handleDragStart(e, box.id)}
|
||||
onDoubleClick={() => handleDoubleClick(box.id)}
|
||||
className="w-8 h-8 bg-primary rounded cursor-move hover:bg-primary/80 transition-colors"
|
||||
onClick={() => handleBoxClick(box.id)}
|
||||
className={`w-8 h-8 bg-primary rounded cursor-pointer hover:bg-primary/80 transition-colors ${
|
||||
selectedBoxForMove === box.id ? 'ring-2 ring-blue-500 ring-offset-2' : ''
|
||||
}`}
|
||||
>
|
||||
</div>
|
||||
))}
|
||||
|
|
@ -325,7 +362,10 @@ const BulgarianSolitaire: React.FC<BulgarianSolitaireProps> = ({ showSocialShare
|
|||
key={index}
|
||||
onDragOver={handleDragOver}
|
||||
onDrop={(e) => handleDrop(e, index)}
|
||||
className="border border-muted-foreground rounded-lg min-h-[100px] w-12 p-1 bg-background/50 flex flex-col-reverse gap-1 transition-all duration-500"
|
||||
onClick={(e) => handleColumnClick(e, index)}
|
||||
className={`border rounded-lg min-h-[100px] w-12 p-1 bg-background/50 flex flex-col-reverse gap-1 transition-all duration-500 ${
|
||||
selectedBoxForMove !== null ? 'border-blue-500 border-2 cursor-pointer hover:bg-blue-50' : 'border-muted-foreground'
|
||||
}`}
|
||||
style={{ flexBasis: `calc(${100/15}% - 0.25rem)`, minWidth: '48px' }}
|
||||
>
|
||||
<div className="text-xs text-center text-muted-foreground mb-1 transform rotate-0">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue