Skip to content

text alignment fix#1644

Merged
ragnep merged 1 commit intomainfrom
ui-fixes-pfp
Dec 12, 2025
Merged

text alignment fix#1644
ragnep merged 1 commit intomainfrom
ui-fixes-pfp

Conversation

@ragnep
Copy link
Copy Markdown
Contributor

@ragnep ragnep commented Dec 12, 2025

Summary by CodeRabbit

  • New Features

    • Introduced modal-based voting interface for participation drops
  • Style

    • Refined horizontal spacing and alignment across drop layouts
    • Adjusted avatar sizing for improved visual consistency
    • Reorganized header and footer structure for better visual hierarchy
    • Enhanced mobile layout responsiveness

✏️ Tip: You can customize this high-level summary in your review settings.

Signed-off-by: ragnep <ragneinfo@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 12, 2025

Walkthrough

The PR reorganizes drop components across memes and waves systems with consistent spacing adjustments (3.25rem → 3.5rem margins), introduces voting modals in participation drops, adds mobile/touch support with device detection and long-press handlers, modularizes components into sub-components, adjusts avatar sizing, and updates two public component APIs to accept onDropClick callbacks and wave data.

Changes

Cohort / File(s) Summary
Meme Drop Modularization
components/memes/drops/MemeParticipationDrop.tsx
Reorganized imports with expanded UI component dependencies (MobileVotingModal, VotingModal, VotingModalButton); introduced modularized sub-components (MemeDropActions, MemeDropArtistInfo, MemeDropHeader, MemeDropDescription); adjusted left margin from 3.75rem to 3.5rem in descriptive container.
Wave Drop Avatar & Spacing Updates
components/waves/drops/ArtistPreviewModalHeader.tsx, components/waves/drops/WaveDropAuthorPfp.tsx, components/waves/drops/winner/DefaultWinnerDrop.tsx, components/waves/winners/drops/header/WaveWinnersDropHeaderAuthorPfp.tsx
Simplified avatar styling with fixed sizes (11x11 or smaller), removed dynamic shadow logic based on winner status, increased horizontal spacing from 3.25rem to 3.5rem consistently across files.
Wave Drop Layout Reorganization
components/waves/drops/WaveDrop.tsx
Increased horizontal spacing (maxWidth and left margin adjustments from 3.25rem to 3.5rem); reorganized imports with additional model and hook imports (ApiDrop, ApiDropType, ExtendedDrop, useIsMobileDevice).
Participation Drop Enhancement
components/waves/drops/participation/ParticipationDropFooter.tsx, components/waves/drops/participation/ParticipationDropHeader.tsx, components/waves/drops/participation/ParticipationDropMetadata.tsx
Added modal voting UI (MobileVotingModal, VotingModal integration); reorganized header layout with tightened gap (4 → 2), moved author info and WaveDropTime to separate sibling elements; adjusted left margins from 3.25rem to 3.5rem; added buildTooltipId helper import.
Leaderboard Drop API Update
components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx
Updated public props to include wave: ApiWave and onDropClick callback; introduced mobile dropdown wrapper and voting modal integration; reorganized imports and adjusted vertical gap (tw-gap-3); changed left margin to 3.5rem.
Leaderboard Drop Author Header
components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
Increased avatar size from 10x10 to 11x11; changed layout from horizontal row to vertical stack (tw-flex-col with gap-y-1.5); wrapped WinnerDropBadge in dedicated flex container.
Winners Drop with Mobile Support
components/waves/winners/drops/DefaultWaveWinnerDrop.tsx
Updated public props to include onDropClick callback; added useDeviceInfo and useLongPressInteraction for touch behavior; introduced CommonDropdownItemsMobileWrapper; adjusted left margin from 3.75rem to 3.5rem; wired touch handlers to main container.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • DefaultWaveLeaderboardDrop API change: Verify all callers are updated with new wave prop and onDropClick callback requirements
  • DefaultWaveWinnersDropProps API change: Ensure onDropClick callback is properly wired and called throughout the component tree
  • Voting modal state management: Review modal open/close logic and integration in ParticipationDropFooter
  • Touch/mobile handling: Validate useDeviceInfo and useLongPressInteraction integration in DefaultWaveWinnerDrop
  • Spacing consistency: Confirm all 3.25rem → 3.5rem margin adjustments are intentional and aligned across files

Possibly related PRs

  • #1640: Introduces useArtistPreviewModal, ProfileWinnerBadge, and updates MemeDropArtistInfo component — directly related to meme drop modularization and artist preview modal wiring in this PR.
  • #1639: Makes concurrent changes to leaderboard/drop components including onDropClick props, ApiWave integration, and voting modal additions — shares overlapping component enhancements with this PR.

Suggested reviewers

  • simo6529

Poem

🐰 A spacing dance, margins grow neat,
Modular drops make code complete,
Touch and modal, polls now flow,
Three-point-five rem steals the show!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'text alignment fix' is vague and generic, failing to describe the actual scope of changes which include comprehensive spacing adjustments, component refactoring, layout reorganization, and public API signature updates across 12+ files. Revise the title to be more specific and descriptive of the primary changes, such as 'Refactor wave drop components with spacing adjustments and responsive layout updates' or 'Update drop component styling and reorganize participation/leaderboard drop structures'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ui-fixes-pfp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

@ragnep ragnep merged commit da0508b into main Dec 12, 2025
7 of 8 checks passed
@ragnep ragnep deleted the ui-fixes-pfp branch December 12, 2025 10:48
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
components/memes/drops/MemeParticipationDrop.tsx (1)

59-85: Guard drop.parts[0] access in reply/quote handlers to avoid crashes on empty parts. artworkMedia is already using at(0), but handleOnReply/handleOnQuote will throw if drop.parts.length === 0.

   const handleOnReply = useCallback(() => {
-    onReply({ drop, partId: drop.parts[0].part_id });
+    const partId = drop.parts.at(0)?.part_id;
+    if (!partId) return;
+    onReply({ drop, partId });
   }, [onReply, drop]);

   const handleOnQuote = useCallback(() => {
-    onQuote({ drop, partId: drop.parts[0].part_id });
+    const partId = drop.parts.at(0)?.part_id;
+    if (!partId) return;
+    onQuote({ drop, partId });
   }, [onQuote, drop]);
components/waves/winners/drops/header/WaveWinnersDropHeaderAuthorPfp.tsx (1)

12-21: Replace <img> with next/image to satisfy Next.js ESLint rules.
This component still renders a raw <img> (Line 17-21), which will typically trip @next/next/no-img-element. As per coding guidelines, use <Image />.

+import Image from "next/image";
 ...
-              <img
-                src={winner.drop.author.pfp}
-                alt="Profile picture"
-                className="tw-bg-transparent tw-max-w-full tw-max-h-full tw-h-auto tw-w-auto tw-mx-auto tw-object-contain"
-              />
+              <Image
+                src={winner.drop.author.pfp}
+                alt="Profile picture"
+                width={44}
+                height={44}
+                className="tw-bg-transparent tw-max-w-full tw-max-h-full tw-h-auto tw-w-auto tw-mx-auto tw-object-contain"
+              />

As per coding guidelines, this should be migrated to next/image.

components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (1)

27-43: Replace <img> with next/image in the avatar (ESLint/Core Web Vitals).
<img> is still used for drop.author.pfp (Line 32-37).

+import Image from "next/image";
 ...
-                  <img
-                    src={drop.author.pfp}
-                    alt="Profile picture"
-                    className="tw-bg-transparent tw-max-w-full tw-max-h-full tw-h-auto tw-w-auto tw-mx-auto tw-object-contain"
-                  />
+                  <Image
+                    src={drop.author.pfp}
+                    alt="Profile picture"
+                    width={44}
+                    height={44}
+                    className="tw-bg-transparent tw-max-w-full tw-max-h-full tw-h-auto tw-w-auto tw-mx-auto tw-object-contain"
+                  />

As per coding guidelines, internal images should use next/image.

components/waves/drops/ArtistPreviewModalHeader.tsx (1)

46-85: Replace <img> with next/image and use FontAwesome for the close icon (project standards compliance).

  • Avatar still uses <img> (lines 49-54); replace with <Image /> from next/image with width={44} and height={44} to match container dimensions.
  • Close button uses Heroicons; replace XMarkIcon from @heroicons/react with FontAwesome (project standard per .cursorrules).
-import { XMarkIcon } from "@heroicons/react/24/outline";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faXmark } from "@fortawesome/free-solid-svg-icons";
+import Image from "next/image";
 ...
             {user.pfp && (
-              <img
-                src={user.pfp}
-                alt="Profile"
-                className="tw-w-full tw-h-full tw-object-contain tw-bg-transparent"
-              />
+              <Image
+                src={user.pfp}
+                alt="Profile"
+                width={44}
+                height={44}
+                className="tw-w-full tw-h-full tw-object-contain tw-bg-transparent"
+              />
             )}
 ...
-            <XMarkIcon className="tw-w-5 tw-h-5 tw-flex-shrink-0" />
+            <FontAwesomeIcon icon={faXmark} className="tw-w-5 tw-h-5 tw-flex-shrink-0" />
components/waves/drops/WaveDrop.tsx (1)

394-400: Make the width calc consistent with the new 3.5rem left offset.
tw-w-[calc(100%-3.25rem)] + tw-ml-[3.5rem] is internally inconsistent and can cause layout issues.

- className={`tw-mx-2 tw-flex tw-w-[calc(100%-3.25rem)] tw-ml-[3.5rem] tw-items-center tw-gap-x-2 tw-gap-y-1 tw-flex-wrap`}>
+ className={`tw-mx-2 tw-flex tw-w-[calc(100%-3.5rem)] tw-ml-[3.5rem] tw-items-center tw-gap-x-2 tw-gap-y-1 tw-flex-wrap`}>
🧹 Nitpick comments (3)
components/waves/drops/winner/DefaultWinnerDrop.tsx (1)

3-10: Prefer direct React type imports over React.RefObject for TS consistency.
Guidelines prefer named imports/types; you can avoid the React. namespace in parentContainerRef.

-import { memo, useCallback, useState } from "react";
+import { memo, useCallback, useState } from "react";
+import type { RefObject } from "react";
 ...
-  readonly parentContainerRef?: React.RefObject<HTMLElement | null>;
+  readonly parentContainerRef?: RefObject<HTMLElement | null>;

As per coding guidelines, prefer named imports for React hooks and types.

Also applies to: 86-87

components/waves/drops/participation/ParticipationDropMetadata.tsx (1)

4-7: Guard against non-unique/nullable meta.data_key for Tooltip IDs + React keys.
If meta.data_key isn’t guaranteed unique/present, buildTooltipId(...) (Line 21) and key={meta.data_key} can collide.

-  const tooltipId = buildTooltipId("metadata", contextId, meta.data_key);
+  const metaKey = meta.data_key ?? "unknown-key";
+  const tooltipId = buildTooltipId("metadata", contextId, metaKey);

And in the maps:

-          key={meta.data_key}
+          key={`${contextId ?? "ctx"}:${meta.data_key ?? meta.data_value}`}

Given react-tooltip behavior can vary by version, please sanity-check in-app (hover, focus, portal layering).

Also applies to: 21-47

components/waves/drops/WaveDropAuthorPfp.tsx (1)

23-31: Good sizing alignment; consider dropping React. namespace types/imports.
The 44px sizes matches the new tw-h-11 tw-w-11 container well, but this file still relies on React.FC / React.MouseEvent. Consider switching to named imports (FC, MouseEvent) to match repo guidelines.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f082eed and 0d65bd7.

📒 Files selected for processing (12)
  • components/memes/drops/MemeParticipationDrop.tsx (2 hunks)
  • components/waves/drops/ArtistPreviewModalHeader.tsx (1 hunks)
  • components/waves/drops/WaveDrop.tsx (4 hunks)
  • components/waves/drops/WaveDropAuthorPfp.tsx (1 hunks)
  • components/waves/drops/participation/ParticipationDropFooter.tsx (3 hunks)
  • components/waves/drops/participation/ParticipationDropHeader.tsx (1 hunks)
  • components/waves/drops/participation/ParticipationDropMetadata.tsx (2 hunks)
  • components/waves/drops/winner/DefaultWinnerDrop.tsx (2 hunks)
  • components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx (3 hunks)
  • components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (3 hunks)
  • components/waves/winners/drops/DefaultWaveWinnerDrop.tsx (2 hunks)
  • components/waves/winners/drops/header/WaveWinnersDropHeaderAuthorPfp.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version

**/*.{ts,tsx,js,jsx}: Replace <img> elements with <Image /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • components/waves/drops/WaveDropAuthorPfp.tsx
  • components/waves/drops/ArtistPreviewModalHeader.tsx
  • components/waves/winners/drops/DefaultWaveWinnerDrop.tsx
  • components/waves/drops/participation/ParticipationDropHeader.tsx
  • components/waves/winners/drops/header/WaveWinnersDropHeaderAuthorPfp.tsx
  • components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx
  • components/waves/drops/participation/ParticipationDropMetadata.tsx
  • components/waves/drops/winner/DefaultWinnerDrop.tsx
  • components/waves/drops/WaveDrop.tsx
  • components/waves/drops/participation/ParticipationDropFooter.tsx
  • components/memes/drops/MemeParticipationDrop.tsx
  • components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always add readonly before props in React components

Files:

  • components/waves/drops/WaveDropAuthorPfp.tsx
  • components/waves/drops/ArtistPreviewModalHeader.tsx
  • components/waves/winners/drops/DefaultWaveWinnerDrop.tsx
  • components/waves/drops/participation/ParticipationDropHeader.tsx
  • components/waves/winners/drops/header/WaveWinnersDropHeaderAuthorPfp.tsx
  • components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx
  • components/waves/drops/participation/ParticipationDropMetadata.tsx
  • components/waves/drops/winner/DefaultWinnerDrop.tsx
  • components/waves/drops/WaveDrop.tsx
  • components/waves/drops/participation/ParticipationDropFooter.tsx
  • components/memes/drops/MemeParticipationDrop.tsx
  • components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use <Link>, images should use next/image, and adopt Next's ESLint rules (Core Web Vitals)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Files:

  • components/waves/drops/WaveDropAuthorPfp.tsx
  • components/waves/drops/ArtistPreviewModalHeader.tsx
  • components/waves/winners/drops/DefaultWaveWinnerDrop.tsx
  • components/waves/drops/participation/ParticipationDropHeader.tsx
  • components/waves/winners/drops/header/WaveWinnersDropHeaderAuthorPfp.tsx
  • components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx
  • components/waves/drops/participation/ParticipationDropMetadata.tsx
  • components/waves/drops/winner/DefaultWinnerDrop.tsx
  • components/waves/drops/WaveDrop.tsx
  • components/waves/drops/participation/ParticipationDropFooter.tsx
  • components/memes/drops/MemeParticipationDrop.tsx
  • components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") over React. namespace usage (React.useMemo, React.useRef, etc.)
If the react-hooks/exhaustive-deps lint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic in useEffectEvent

**/*.{ts,tsx}: Must pass tsc --noEmit for TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for images, adopt Next's ESLint rules
Use 'use cache' directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace <img> elements with <Image /> from next/image
Use <Link href="/path"> for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with 'use server' directive

Files:

  • components/waves/drops/WaveDropAuthorPfp.tsx
  • components/waves/drops/ArtistPreviewModalHeader.tsx
  • components/waves/winners/drops/DefaultWaveWinnerDrop.tsx
  • components/waves/drops/participation/ParticipationDropHeader.tsx
  • components/waves/winners/drops/header/WaveWinnersDropHeaderAuthorPfp.tsx
  • components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx
  • components/waves/drops/participation/ParticipationDropMetadata.tsx
  • components/waves/drops/winner/DefaultWinnerDrop.tsx
  • components/waves/drops/WaveDrop.tsx
  • components/waves/drops/participation/ParticipationDropFooter.tsx
  • components/memes/drops/MemeParticipationDrop.tsx
  • components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx
🧠 Learnings (4)
📚 Learning: 2025-11-25T08:35:58.729Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T08:35:58.729Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Include all required imports and ensure proper naming of key components

Applied to files:

  • components/waves/winners/drops/DefaultWaveWinnerDrop.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions

Applied to files:

  • components/waves/winners/drops/DefaultWaveWinnerDrop.tsx
  • components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx
  • components/waves/drops/winner/DefaultWinnerDrop.tsx
  • components/waves/drops/WaveDrop.tsx
  • components/memes/drops/MemeParticipationDrop.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks

Applied to files:

  • components/waves/winners/drops/DefaultWaveWinnerDrop.tsx
  • components/waves/drops/winner/DefaultWinnerDrop.tsx
  • components/waves/drops/WaveDrop.tsx
  • components/waves/drops/participation/ParticipationDropFooter.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Applied to files:

  • components/waves/drops/winner/DefaultWinnerDrop.tsx
  • components/waves/drops/WaveDrop.tsx
  • components/memes/drops/MemeParticipationDrop.tsx
🧬 Code graph analysis (1)
components/waves/drops/participation/ParticipationDropHeader.tsx (1)
components/user/utils/UserCICAndLevel.tsx (1)
  • UserCICAndLevel (11-53)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (9)
components/memes/drops/MemeParticipationDrop.tsx (2)

3-19: Imports + modular subcomponents integration looks coherent.


104-110: Alignment tweak (sm:tw-ml-[3.75rem] → sm:tw-ml-[3.5rem]) is straightforward and localized.

components/waves/leaderboard/drops/header/WaveLeaderboardDropAuthor.tsx (1)

45-73: New author vertical stack + dedicated badge row looks consistent.
The split into two rows (Line 45-73) reads cleaner and should improve alignment predictability.

components/waves/drops/winner/DefaultWinnerDrop.tsx (1)

234-242: Spacing tweak to tw-ml-[3.5rem] matches the PR’s alignment goal.
Looks consistent with the other 3.5rem left-alignment shifts.

components/waves/drops/participation/ParticipationDropMetadata.tsx (1)

72-73: Margin shift to sm:tw-ml-[3.5rem] aligns with the PR’s layout changes.

components/waves/drops/participation/ParticipationDropHeader.tsx (1)

24-53: Header layout split (author/time + badge row) looks cleaner and should help alignment.
Only potential footgun: the Link uses href={\/${drop.author.handle}`}(Line 35-36). Ifhandle` can be null/empty, consider guarding or falling back to a safe route/id.

components/waves/drops/participation/ParticipationDropFooter.tsx (1)

3-57: Modal voting wiring looks reasonable; please smoke-test event propagation + a11y behaviors.
Specifically: clicking inside the modal should not trigger any parent “drop” click handlers, and desktop should support Escape/focus trap as expected (depends on MobileVotingModal/VotingModal implementation).

components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx (1)

63-67: Verify long-press doesn’t also trigger onDropClick.
Same pattern: onClick on the outer wrapper + touchHandlers on the inner wrapper; please confirm long-press opens the mobile menu without also navigating/opening the drop.

Also applies to: 122-145

components/waves/winners/drops/DefaultWaveWinnerDrop.tsx (1)

68-72: Add stopPropagation() to the outer onClick handler or preventDefault() on touchEnd to prevent synthetic clicks.

Long-press handlers are on the inner div, but onClick is on the outer div. On iOS/Android, releasing a long-press can synthesize a click event that bubbles to the outer div, causing both the menu to open and the onDropClick action to fire. Wrap the onClick handler with stopPropagation() or prevent synthetic clicks in the useLongPressInteraction hook's handleTouchEnd.

This applies to lines 68–72, 72–90 (inner content), and 130–146 (menu portal).

Comment on lines +68 to 70
<div className="tw-mt-4 tw-px-4 tw-flex tw-w-[calc(100%-3.25rem)] tw-ml-[3.5rem] tw-items-center tw-gap-x-2 tw-gap-y-1 tw-flex-wrap">
<WaveDropReactions drop={drop} />
</div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix width calc mismatch: calc(100% - 3.25rem) should match tw-ml-[3.5rem].
Right now the row is offset by 3.5rem but only shrinks by 3.25rem, which can cause subtle overflow/misalignment.

-      <div className="tw-mt-4 tw-px-4 tw-flex tw-w-[calc(100%-3.25rem)] tw-ml-[3.5rem] tw-items-center tw-gap-x-2 tw-gap-y-1 tw-flex-wrap">
+      <div className="tw-mt-4 tw-px-4 tw-flex tw-w-[calc(100%-3.5rem)] tw-ml-[3.5rem] tw-items-center tw-gap-x-2 tw-gap-y-1 tw-flex-wrap">
         <WaveDropReactions drop={drop} />
       </div>
🤖 Prompt for AI Agents
In components/waves/drops/participation/ParticipationDropFooter.tsx around lines
68 to 70, the container uses tw-w-[calc(100%-3.25rem)] while the left margin is
tw-ml-[3.5rem], causing a 0.25rem mismatch and potential overflow; change the
calc to tw-w-[calc(100%-3.5rem)] (or otherwise ensure both values come from the
same constant/utility) so the width subtraction matches the left margin exactly.

Comment on lines +3 to +14
import { ApiDrop } from "@/generated/models/ApiDrop";
import { ApiDropMentionedUser } from "@/generated/models/ApiDropMentionedUser";
import { ApiDropType } from "@/generated/models/ApiDropType";
import { ApiUpdateDropRequest } from "@/generated/models/ApiUpdateDropRequest";
import { ExtendedDrop } from "@/helpers/waves/drop.helpers";
import { useDropUpdateMutation } from "@/hooks/drops/useDropUpdateMutation";
import useIsMobileDevice from "@/hooks/isMobileDevice";
import { selectEditingDropId, setEditingDropId } from "@/store/editSlice";
import { ActiveDropState } from "@/types/dropInteractionTypes";
import { memo, useCallback, useEffect, useRef, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { DropInteractionParams, DropLocation } from "./Drop";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix TypeScript: React.* types used without importing React.
After switching to named imports from "react", the file still references React.RefObject / React.TouchEvent, which will fail tsc --noEmit.

- import { memo, useCallback, useEffect, useRef, useState } from "react";
+ import {
+   memo,
+   useCallback,
+   useEffect,
+   useRef,
+   useState,
+   type RefObject,
+   type TouchEvent,
+ } from "react";

  interface WaveDropProps {
    readonly drop: ExtendedDrop;
    ...
-   readonly parentContainerRef?: React.RefObject<HTMLElement | null>;
+   readonly parentContainerRef?: RefObject<HTMLElement | null>;
  }

  const handleTouchStart = useCallback(
-   (e: React.TouchEvent) => {
+   (e: TouchEvent) => {
      ...
    },
    ...
  );

- const handleTouchEnd = useCallback((e: React.TouchEvent) => {
+ const handleTouchEnd = useCallback((e: TouchEvent) => {
    ...
  }, []);

- const handleTouchMove = useCallback((e: React.TouchEvent) => {
+ const handleTouchMove = useCallback((e: TouchEvent) => {
    ...
  }, []);

Also applies to: 117-132, 193-213

🤖 Prompt for AI Agents
In components/waves/drops/WaveDrop.tsx around lines 3-14 (and also where
React.RefObject / React.TouchEvent are used at 117-132 and 193-213), the code
references React types but only uses named imports from "react"; add the missing
type imports (e.g., RefObject and TouchEvent — or any other React.* types used)
to the existing import from 'react' so the file imports these types directly (or
alternatively import React as a namespace), then update any type annotations if
necessary to use the newly imported names.

Comment on lines +3 to 22
import CommonDropdownItemsMobileWrapper from "@/components/utils/select/dropdown/CommonDropdownItemsMobileWrapper";
import { MobileVotingModal, VotingModal } from "@/components/voting";
import VotingModalButton from "@/components/voting/VotingModalButton";
import WaveDropActionsOpen from "@/components/waves/drops/WaveDropActionsOpen";
import WaveDropMobileMenuOpen from "@/components/waves/drops/WaveDropMobileMenuOpen";
import WaveDropActionsOptions from "@/components/waves/drops/WaveDropActionsOptions";
import WaveDropMobileMenuDelete from "@/components/waves/drops/WaveDropMobileMenuDelete";
import { VotingModal, MobileVotingModal } from "@/components/voting";
import VotingModalButton from "@/components/voting/VotingModalButton";
import WaveDropMobileMenuOpen from "@/components/waves/drops/WaveDropMobileMenuOpen";
import { ApiWave } from "@/generated/models/ObjectSerializer";
import { ExtendedDrop } from "@/helpers/waves/drop.helpers";
import { useDropInteractionRules } from "@/hooks/drops/useDropInteractionRules";
import useIsMobileScreen from "@/hooks/isMobileScreen";
import useDeviceInfo from "@/hooks/useDeviceInfo";
import CommonDropdownItemsMobileWrapper from "@/components/utils/select/dropdown/CommonDropdownItemsMobileWrapper";
import useLongPressInteraction from "@/hooks/useLongPressInteraction";
import React, { useState } from "react";
import { createPortal } from "react-dom";
import { WaveLeaderboardDropContent } from "../content/WaveLeaderboardDropContent";
import { WaveLeaderboardDropFooter } from "./footer/WaveLeaderboardDropFooter";
import { WaveLeaderboardDropHeader } from "./header/WaveLeaderboardDropHeader";
import { WaveLeaderboardDropRaters } from "./header/WaveleaderboardDropRaters";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for the actual file with its correct casing
echo "=== Searching for the actual file ==="
fd -a "Wave.*DropRaters\.(ts|tsx)$" . | head -20

echo ""
echo "=== Checking all import statements with case-insensitive search ==="
rg -in "waveleaderboarddropraters|wavelearboard" . --type=ts --type=tsx | head -30

echo ""
echo "=== Checking specific import statements in the target file ==="
rg -n "WaveleaderboardDropRaters|WaveLeaderboardDropRaters" . --type=ts --type=tsx

Repository: 6529-Collections/6529seize-frontend

Length of output: 413


🏁 Script executed:

#!/bin/bash
# Read the specific import line from the target file to verify the exact casing
echo "=== Reading import lines from DefaultWaveLeaderboardDrop.tsx ==="
sed -n '1,30p' components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx | grep -i "waveleaderboard\|waveleaderboard"

echo ""
echo "=== Listing the actual header file to confirm casing ==="
ls -la components/waves/leaderboard/drops/header/ | grep -i raters

Repository: 6529-Collections/6529seize-frontend

Length of output: 733


🏁 Script executed:

#!/bin/bash
# Check the actual export from the WaveleaderboardDropRaters.tsx file
echo "=== Reading WaveleaderboardDropRaters.tsx export ==="
head -50 components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx | grep -E "export|const|function"

echo ""
echo "=== Check full export statement ==="
rg "export.*WaveLeaderboard|export.*Waveleaderboard" components/waves/leaderboard/drops/header/WaveleaderboardDropRaters.tsx -A 2

Repository: 6529-Collections/6529seize-frontend

Length of output: 643


Fix import path casing: file should be named WaveLeaderboardDropRaters.tsx.
The component exports WaveLeaderboardDropRaters but the file is named WaveleaderboardDropRaters.tsx (with lowercase 'leaderboard'). This mismatch will break on case-sensitive filesystems (Linux/macOS CI). Rename the file to match the exported component name.

🤖 Prompt for AI Agents
In components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx around
lines 3 to 22, the import path for WaveLeaderboardDropRaters uses a filename
with a lowercase "leaderboard" that doesn't match the exported component name;
rename the physical file from WaveleaderboardDropRaters.tsx to
WaveLeaderboardDropRaters.tsx and update the import in this file to import {
WaveLeaderboardDropRaters } from "./header/WaveLeaderboardDropRaters"; ensure
git tracks the rename (use git mv) so case-only change is reflected on
case-insensitive systems and run the build to verify no other imports reference
the old casing.

Comment on lines +1 to 20
import CommonDropdownItemsMobileWrapper from "@/components/utils/select/dropdown/CommonDropdownItemsMobileWrapper";
import WaveDropActionsOpen from "@/components/waves/drops/WaveDropActionsOpen";
import WaveDropMobileMenuOpen from "@/components/waves/drops/WaveDropMobileMenuOpen";
import { ApiWaveDecisionWinner } from "@/generated/models/ApiWaveDecisionWinner";
import { formatNumberWithCommas } from "@/helpers/Helpers";
import {
ExtendedDrop,
convertApiDropToExtendedDrop,
ExtendedDrop,
convertApiDropToExtendedDrop,
} from "@/helpers/waves/drop.helpers";
import useDeviceInfo from "@/hooks/useDeviceInfo";
import useLongPressInteraction from "@/hooks/useLongPressInteraction";
import React from "react";
import { createPortal } from "react-dom";
import { WaveWinnersDropHeader } from "./header/WaveWinnersDropHeader";
import { WaveWinnersDropContent } from "./WaveWinnersDropContent";
import WaveWinnersDropOutcome from "./header/WaveWinnersDropOutcome";
import { ApiWaveDecisionWinner } from "@/generated/models/ApiWaveDecisionWinner";
import WaveWinnersDropHeaderAuthorPfp from "./header/WaveWinnersDropHeaderAuthorPfp";
import WaveWinnersDropHeaderTotalVotes from "./header/WaveWinnersDropHeaderTotalVotes";
import WaveWinnersDropHeaderVoters from "./header/WaveWinnersDropHeaderVoters";
import useDeviceInfo from "@/hooks/useDeviceInfo";
import useLongPressInteraction from "@/hooks/useLongPressInteraction";
import WaveDropActionsOpen from "@/components/waves/drops/WaveDropActionsOpen";
import CommonDropdownItemsMobileWrapper from "@/components/utils/select/dropdown/CommonDropdownItemsMobileWrapper";
import WaveDropMobileMenuOpen from "@/components/waves/drops/WaveDropMobileMenuOpen";
import { formatNumberWithCommas } from "@/helpers/Helpers";
import WaveWinnersDropOutcome from "./header/WaveWinnersDropOutcome";
import { WaveWinnersDropContent } from "./WaveWinnersDropContent";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add "use client"; (module uses document + client hooks).
This file uses createPortal(... document.body) and client hooks; it should be a Client Component.

+ "use client";
+
 import CommonDropdownItemsMobileWrapper from "@/components/utils/select/dropdown/CommonDropdownItemsMobileWrapper";
 ...

Also applies to: 130-146

🤖 Prompt for AI Agents
components/waves/winners/drops/DefaultWaveWinnerDrop.tsx lines 1-20 (also
applies to lines 130-146): this module uses document (createPortal) and
client-only hooks, so it must be a Next.js Client Component; add the directive
"use client"; as the very first line of the file (above all imports) to mark the
file as a client component and prevent server-side rendering errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants