From 6b40e59df6e253fa9d65a078e2b709a0a6c3acc0 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Tue, 22 Sep 2026 21:34:25 +0300 Subject: [PATCH] Draggable tiers --- .../components/TierRow.module.css | 41 ++++----- .../tier-list-maker/components/TierRow.tsx | 61 ++++++------- .../tier-list-maker/hooks/useTierList.ts | 86 ++++++++++--------- .../routes/tier-list-maker.tsx | 59 +++++++++++-- .../tier-list-maker/tier-list-maker-utils.ts | 14 +++ ...2026-09-22-tier-list-maker-tier-reorder.md | 5 ++ e2e/helpers/playwright.ts | 23 +++++ .../tier-list-maker/tier-list-maker-page.ts | 38 +++++--- e2e/tier-list-maker.spec.ts | 35 +++++++- 9 files changed, 242 insertions(+), 120 deletions(-) create mode 100644 changelog/2026-09-22-tier-list-maker-tier-reorder.md diff --git a/app/features/tier-list-maker/components/TierRow.module.css b/app/features/tier-list-maker/components/TierRow.module.css index 2f119d797..16690127e 100644 --- a/app/features/tier-list-maker/components/TierRow.module.css +++ b/app/features/tier-list-maker/components/TierRow.module.css @@ -5,6 +5,12 @@ min-height: 68px; } +.containerReordering { + position: relative; + z-index: 1; + opacity: 0.75; +} + .tierLabel { grid-column: 1; display: flex; @@ -93,14 +99,8 @@ justify-content: center; } -.arrowControls { +.dragHandle { grid-column: 3; - display: grid; - grid-template-rows: 1fr 1fr; - gap: var(--s-1); -} - -.arrowButton { display: flex; align-items: center; justify-content: center; @@ -109,31 +109,24 @@ padding: var(--s-1); background: var(--color-bg-high); border: none; - cursor: pointer; - transition: opacity 0.2s; + border-radius: 0 var(--radius-field) var(--radius-field) 0; + color: var(--color-text-high); + cursor: grab; + touch-action: none; + transition: color 0.2s; - &:hover:not(:disabled) { - opacity: 0.8; + &:hover { + color: var(--color-text); } - &:disabled { - opacity: 0.3; - cursor: not-allowed; + &:active { + cursor: grabbing; } } -.arrowButtonUpper { - border-radius: 0 var(--radius-field) 0 0; -} - -.arrowButtonLower { - border-radius: 0 0 var(--radius-field) 0; -} - -.arrowIcon { +.dragHandleIcon { width: 20px; height: 20px; - color: var(--color-text); } .colorGrid { diff --git a/app/features/tier-list-maker/components/TierRow.tsx b/app/features/tier-list-maker/components/TierRow.tsx index 34a19f768..912a310a7 100644 --- a/app/features/tier-list-maker/components/TierRow.tsx +++ b/app/features/tier-list-maker/components/TierRow.tsx @@ -2,9 +2,11 @@ import { useDroppable } from "@dnd-kit/core"; import { horizontalListSortingStrategy, SortableContext, + useSortable, } from "@dnd-kit/sortable"; +import { CSS } from "@dnd-kit/utilities"; import clsx from "clsx"; -import { ChevronDown, ChevronUp, Plus, Trash } from "lucide-react"; +import { GripVertical, Plus, Trash } from "lucide-react"; import type { KeyboardEvent } from "react"; import { useLayoutEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; @@ -20,6 +22,7 @@ import { isLightColor, tierListItemId, tierNameFontSize, + tierSortableId, tierTextColor, } from "../tier-list-maker-utils"; import { DraggableItem } from "./DraggableItem"; @@ -31,14 +34,11 @@ interface TierRowProps { export function TierRow({ tier }: TierRowProps) { const { - state, activeItem, getItemsInTier, handleRemoveTier, handleRenameTier, handleChangeTierColor, - handleMoveTierUp, - handleMoveTierDown, showTierHeaders, placementMode, selectedTierId, @@ -56,11 +56,15 @@ export function TierRow({ tier }: TierRowProps) { isDragging: activeItem !== null, }); - const tierIndex = state.tiers.findIndex( - (candidate) => candidate.id === tier.id, - ); - const isFirstTier = tierIndex === 0; - const isLastTier = tierIndex === state.tiers.length - 1; + const { + attributes, + listeners, + setNodeRef: setSortableNodeRef, + setActivatorNodeRef, + transform, + transition, + isDragging: isReordering, + } = useSortable({ id: tierSortableId(tier.id) }); const isClickMode = placementMode === "click"; const isSelected = isClickMode && selectedTierId === tier.id; @@ -82,7 +86,14 @@ export function TierRow({ tier }: TierRowProps) { : {}; return ( -