Skip to content

Little ui fixes#1640

Merged
ragnep merged 7 commits intomainfrom
submissions-badge-add
Dec 11, 2025
Merged

Little ui fixes#1640
ragnep merged 7 commits intomainfrom
submissions-badge-add

Conversation

@ragnep
Copy link
Copy Markdown
Contributor

@ragnep ragnep commented Dec 11, 2025

Summary by CodeRabbit

  • New Features

    • Winner badges and a unified Artist Preview modal with tabbed navigation (active submissions & winners)
    • New reusable ActionButton and updated SecondaryButton component
  • Bug Fixes

    • Improved modal click/backdrop handling to avoid unintended dismissals
  • Style

    • Refined button visuals, card and list layouts, spacing, text sizing and colors; footer and drop layout spacing adjusted for vertical stacking

✏️ 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 11, 2025

Warning

Rate limit exceeded

@ragnep has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 46 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between b1557b5 and 49e4c37.

📒 Files selected for processing (2)
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (3 hunks)
  • components/waves/drops/ArtistPreviewModal.tsx (2 hunks)

Walkthrough

Consolidates artist-preview modal control into a new useArtistPreviewModal hook, wires winner-aware badges to open specific modal tabs, adds an ActionButton component and tweaks SecondaryButton, and applies multiple UI/className updates across meme and wave components (layout, spacing, and minor typography).

Changes

Cohort / File(s) Summary
Artist preview hook & modal
hooks/useArtistPreviewModal.ts, components/waves/drops/ArtistPreviewModal.tsx
Add useArtistPreviewModal (isModalOpen, modalInitialTab, handleBadgeClick, handleModalClose) and ArtistPreviewTab type; ArtistPreviewModal now accepts initialTab (externally typed), and backdrop/desktop click handlers call stopPropagation before onClose.
Badge & artist-info integrations
components/waves/drops/ProfileWinnerBadge.tsx (new), components/memes/drops/MemesLeaderboardDropArtistInfo.tsx, components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx, components/waves/drop/SingleWaveDropAuthor.tsx, components/waves/drops/WaveDropHeader.tsx
Replace local modal state with useArtistPreviewModal; compute winnerCount from winner_main_stage_drop_ids; render ProfileWinnerBadge when winnerCount > 0; unify badge clicks to call `handleBadgeClick("active"
Meme leaderboard layout
components/memes/drops/MemesLeaderboardDrop.tsx
Change footer container classes to flex column with gap (tw-flex tw-flex-col tw-gap-y-4), altering vertical stacking and spacing of Traits, Vote Summary, and Vote Button.
Button components & header
components/utils/button/ActionButton.tsx, components/utils/button/SecondaryButton.tsx, components/waves/list/header/WavesListHeader.tsx
Add new ActionButton component; adjust SecondaryButton padding and border-radius; replace inline header buttons with SecondaryButton/PrimaryButton usages.
Wave list & item UI
components/waves/list/WaveItem.tsx, components/waves/list/WaveItemDropped.tsx, components/waves/list/WaveItemFollow.tsx
Visual/layout refactor: update CARD_BASE_CLASSES (use ring utilities), reorganize responsive wrappers, adjust avatar/author styling, replace inline tooltip blocks with Tooltip, tweak drops count colors/sizes, and swap follow button implementation to SecondaryButton/ActionButton.
Minor presentation tweaks
components/waves/drops/DropItemChat.tsx, components/memes/drops/MemesLeaderboardDrop.tsx
Adjust chat title sizing (tw-text-lgtw-text-base with sm:tw-text-lg) and other small className refinements.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Badge as ProfileWinnerBadge/ArtistSubmissionBadge
    participant Parent as WaveDropHeader/MemeArtistInfo/SingleWaveDropAuthor
    participant Hook as useArtistPreviewModal
    participant Modal as ArtistPreviewModal

    User->>Badge: click badge (winners | active)
    Badge->>Parent: invoke onBadgeClick(tab)
    Parent->>Hook: handleBadgeClick(tab)
    Hook-->>Parent: set modalInitialTab, isModalOpen = true
    Parent->>Modal: render isOpen=true, initialTab=modalInitialTab
    Modal->>User: show modal with selected tab
    User->>Modal: close modal
    Modal->>Hook: onClose()
    Hook-->>Parent: isModalOpen = false
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify initialTab type flows from useArtistPreviewModal through parent components into ArtistPreviewModal.
  • Review ArtistPreviewModal click handlers (stopPropagation) and body overflow cleanup behavior.
  • Visual QA for WaveItem CARD_BASE_CLASSES, tooltip → Tooltip replacement, and button appearance/interaction (ActionButton/SecondaryButton).
  • Confirm winner detection uses winner_main_stage_drop_ids and correct tooltipId/handlers are passed to badges.

Possibly related PRs

Suggested reviewers

  • simo6529
  • analyticsflowee
  • GelatoGenesis

"I hop with tiny paws and cheer,
Badges click and modals appear,
Buttons crisp and layouts neat,
Winners sparkle — what a treat! 🐇🎉"

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 'Little ui fixes' is vague and generic, using non-descriptive language that fails to convey meaningful information about the specific changes in this substantial pull request. Replace with a more specific title that describes the main change, such as 'Add artist preview modal with winner badge support' or 'Consolidate modal state management with useArtistPreviewModal hook'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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.

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 (1)
components/memes/drops/MemesLeaderboardDrop.tsx (1)

135-147: Replace <img> with next/image for voter avatars

To comply with Next.js ESLint (@next/next/no-img-element) and repo guidelines, use next/image for the voter avatar instead of a raw <img>. Add the import and update the component:

+import Image from "next/image";
+import Link from "next/link";
@@
-                            {voter.profile.pfp ? (
-                              <img
-                                className="tw-w-6 tw-h-6 tw-rounded-md tw-border-2 tw-border-solid tw-border-[#111] tw-bg-iron-800 tw-object-contain"
-                                src={voter.profile.pfp}
-                                alt="Recent voter"
-                              />
+                            {voter.profile.pfp ? (
+                              <Image
+                                className="tw-w-6 tw-h-6 tw-rounded-md tw-border-2 tw-border-solid tw-border-[#111] tw-bg-iron-800 tw-object-contain"
+                                src={voter.profile.pfp}
+                                alt="Recent voter"
+                                width={24}
+                                height={24}
+                              />

This keeps styling intact while satisfying Next's image requirements.

🧹 Nitpick comments (10)
components/waves/drop/SingleWaveDropAuthor.tsx (1)

86-86: Remove inline comment.

As per coding guidelines, code should be self-explanatory without comments.

-      {/* Artist Preview Modal */}
       <ArtistPreviewModal
components/utils/button/ActionButton.tsx (1)

3-9: Prefer direct import for ReactNode.

Per coding guidelines, prefer direct named imports for React types over namespace usage.

+import { ReactNode } from "react";
 import CircleLoader from "@/components/distribution-plan-tool/common/CircleLoader";

 interface ActionButtonProps {
   readonly onClicked: () => void;
-  readonly children: React.ReactNode;
+  readonly children: ReactNode;
   readonly size?: "default" | "sm";
   readonly disabled?: boolean;
   readonly loading?: boolean;
 }
components/waves/list/WaveItemFollow.tsx (1)

32-35: Potential stale closure in useEffect.

The getCanSubscribe function captures connectedProfile and activeProfileProxy but the dependency array only lists those values, not the function itself. While this works, the pattern could be simplified by computing directly in the effect or using a stable callback.

Consider simplifying by computing directly:

-  const getCanSubscribe = () =>
-    !!connectedProfile?.handle && !activeProfileProxy;
-  const [canSubscribe, setCanSubscribe] = useState(getCanSubscribe());
-  useEffect(
-    () => setCanSubscribe(getCanSubscribe()),
-    [connectedProfile, activeProfileProxy]
-  );
+  const canSubscribe = !!connectedProfile?.handle && !activeProfileProxy;

This eliminates the state and effect entirely since it's derived from existing values.

components/utils/button/SecondaryButton.tsx (1)

3-10: Prefer direct import for ReactNode for consistency.

Similar to the suggested change in ActionButton.tsx, prefer direct named imports for React types.

+import { ReactNode } from "react";
 import CircleLoader from "@/components/distribution-plan-tool/common/CircleLoader";

 interface SecondaryButtonProps {
   readonly onClicked: () => void;
-  readonly children: React.ReactNode;
+  readonly children: ReactNode;
   readonly size?: "default" | "sm";
   readonly disabled?: boolean;
   readonly className?: string;
   readonly loading?: boolean;
 }
components/waves/drops/WaveDropHeader.tsx (1)

149-149: Remove inline comment.

As per coding guidelines, code should be self-explanatory without comments.

-      {/* Artist Preview Modal */}
       <ArtistPreviewModal
components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx (1)

105-105: Remove inline comment.

As per coding guidelines, code should be self-explanatory without comments.

-      {/* Artist Preview Modal */}
       <ArtistPreviewModal
components/waves/list/WaveItem.tsx (1)

368-395: Align tooltip rendering condition with trigger condition.

The Tooltip component (line 382) is rendered when wave && followersTooltipId exist, but the tooltip trigger (line 368) is rendered when waveHref && followersTooltipId exist. Since wave can exist without waveHref, the Tooltip component could be rendered without its trigger being present, which is inefficient.

Update the Tooltip component condition to match the trigger:

-          {wave && followersTooltipId && (
+          {waveHref && followersTooltipId && (
             <Tooltip
components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (3)

16-27: Winner badge + artist modal tab wiring is coherent

Importing ProfileWinnerBadge, tracking modalInitialTab as "active" | "winners", and routing both ProfileWinnerBadge ("winners") and ArtistSubmissionBadge ("active") through handleBadgeClick aligns cleanly with ArtistPreviewModal’s initialTab behavior and its internal activeTab state. This gives a single source of truth for which tab the modal opens on and should behave correctly even when clicking badges while the modal is already open.

If the ModalTab union type is exported from the modal module, consider reusing that instead of the inline "active" | "winners" literal to avoid type drift in the future.

Also applies to: 81-92, 112-118


31-34: Avoid adding new inline comments in TSX per repo guidelines

The new comments (// Check if this drop author has any main stage winner drop IDs and {/* Artist Preview Modal */}) go against the stated guideline to keep TS/TSX self-explanatory without inline comments. The surrounding naming already makes the intent clear, so these can be safely removed:

-  // Check if this drop author has any main stage winner drop IDs
   const winnerCount = drop.author.winner_main_stage_drop_ids?.length || 0;
@@
-      {/* Artist Preview Modal */}
       <ArtistPreviewModal

Also applies to: 112-112


28-29: Consider guarding drop.author when computing submission/winner counts

If there’s any path where drop.author can be null/undefined, the direct property access here could throw before optional chaining on the nested fields runs. A defensive pattern would be:

-  const submissionCount = drop.author.active_main_stage_submission_ids?.length || 0;
+  const submissionCount =
+    drop.author?.active_main_stage_submission_ids?.length ?? 0;
@@
-  const winnerCount = drop.author.winner_main_stage_drop_ids?.length || 0;
+  const winnerCount =
+    drop.author?.winner_main_stage_drop_ids?.length ?? 0;

If ExtendedDrop.author is guaranteed to be present in this context, you can leave as-is; otherwise this hardens the component against partial data.

Also applies to: 32-33

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 892c581 and 883cfe2.

📒 Files selected for processing (13)
  • components/memes/drops/MemesLeaderboardDrop.tsx (1 hunks)
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (4 hunks)
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx (3 hunks)
  • components/utils/button/ActionButton.tsx (1 hunks)
  • components/utils/button/SecondaryButton.tsx (2 hunks)
  • components/waves/drop/SingleWaveDropAuthor.tsx (2 hunks)
  • components/waves/drops/ArtistPreviewModal.tsx (1 hunks)
  • components/waves/drops/DropItemChat.tsx (1 hunks)
  • components/waves/drops/WaveDropHeader.tsx (4 hunks)
  • components/waves/list/WaveItem.tsx (10 hunks)
  • components/waves/list/WaveItemDropped.tsx (1 hunks)
  • components/waves/list/WaveItemFollow.tsx (4 hunks)
  • components/waves/list/header/WavesListHeader.tsx (2 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/list/header/WavesListHeader.tsx
  • components/memes/drops/MemesLeaderboardDrop.tsx
  • components/waves/drops/WaveDropHeader.tsx
  • components/waves/drop/SingleWaveDropAuthor.tsx
  • components/utils/button/ActionButton.tsx
  • components/waves/list/WaveItemDropped.tsx
  • components/waves/list/WaveItem.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/list/WaveItemFollow.tsx
  • components/utils/button/SecondaryButton.tsx
  • components/waves/drops/DropItemChat.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.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/list/header/WavesListHeader.tsx
  • components/memes/drops/MemesLeaderboardDrop.tsx
  • components/waves/drops/WaveDropHeader.tsx
  • components/waves/drop/SingleWaveDropAuthor.tsx
  • components/utils/button/ActionButton.tsx
  • components/waves/list/WaveItemDropped.tsx
  • components/waves/list/WaveItem.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/list/WaveItemFollow.tsx
  • components/utils/button/SecondaryButton.tsx
  • components/waves/drops/DropItemChat.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.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/list/header/WavesListHeader.tsx
  • components/memes/drops/MemesLeaderboardDrop.tsx
  • components/waves/drops/WaveDropHeader.tsx
  • components/waves/drop/SingleWaveDropAuthor.tsx
  • components/utils/button/ActionButton.tsx
  • components/waves/list/WaveItemDropped.tsx
  • components/waves/list/WaveItem.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/list/WaveItemFollow.tsx
  • components/utils/button/SecondaryButton.tsx
  • components/waves/drops/DropItemChat.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.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/list/header/WavesListHeader.tsx
  • components/memes/drops/MemesLeaderboardDrop.tsx
  • components/waves/drops/WaveDropHeader.tsx
  • components/waves/drop/SingleWaveDropAuthor.tsx
  • components/utils/button/ActionButton.tsx
  • components/waves/list/WaveItemDropped.tsx
  • components/waves/list/WaveItem.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/list/WaveItemFollow.tsx
  • components/utils/button/SecondaryButton.tsx
  • components/waves/drops/DropItemChat.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx
🧠 Learnings (6)
📚 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 **/*.{tsx,jsx} : Use FontAwesome for icons in React components

Applied to files:

  • components/waves/list/header/WavesListHeader.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/memes/drops/MemesLeaderboardDrop.tsx
  • components/waves/drops/WaveDropHeader.tsx
  • components/waves/drop/SingleWaveDropAuthor.tsx
  • components/waves/list/WaveItemFollow.tsx
  • components/waves/drops/ArtistPreviewModal.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/drop/SingleWaveDropAuthor.tsx
  • components/utils/button/ActionButton.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/drop/SingleWaveDropAuthor.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 `<Link href="/path">` for internal navigation instead of plain HTML links

Applied to files:

  • components/waves/drops/DropItemChat.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: Applies to **/*.{ts,tsx,js,jsx} : 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

Applied to files:

  • components/waves/drops/DropItemChat.tsx
🧬 Code graph analysis (6)
components/waves/drops/WaveDropHeader.tsx (2)
components/waves/drops/ProfileWinnerBadge.tsx (1)
  • ProfileWinnerBadge (26-88)
components/waves/drops/ArtistPreviewModal.tsx (1)
  • ArtistPreviewModal (20-156)
components/waves/list/WaveItemDropped.tsx (1)
helpers/Helpers.ts (1)
  • numberWithCommas (84-101)
components/waves/list/WaveItem.tsx (3)
helpers/image.helpers.ts (1)
  • getScaledImageUri (17-45)
components/waves/list/WaveItemDropped.tsx (1)
  • WaveItemDropped (9-112)
components/waves/list/WaveItemFollow.tsx (1)
  • WaveItemFollow (23-182)
components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (3)
components/waves/drops/ProfileWinnerBadge.tsx (1)
  • ProfileWinnerBadge (26-88)
components/waves/drops/ArtistSubmissionBadge.tsx (1)
  • ArtistSubmissionBadge (26-90)
components/waves/drops/ArtistPreviewModal.tsx (1)
  • ArtistPreviewModal (20-156)
components/waves/list/WaveItemFollow.tsx (2)
components/utils/button/SecondaryButton.tsx (1)
  • SecondaryButton (12-40)
components/utils/button/ActionButton.tsx (1)
  • ActionButton (11-36)
components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx (2)
components/waves/drops/ProfileWinnerBadge.tsx (1)
  • ProfileWinnerBadge (26-88)
components/waves/drops/ArtistSubmissionBadge.tsx (1)
  • ArtistSubmissionBadge (26-90)
⏰ 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 (14)
components/waves/drops/DropItemChat.tsx (1)

34-34: LGTM! Responsive typography enhancement.

The responsive text sizing (tw-text-base sm:tw-text-lg) appropriately scales the title for different screen sizes, providing better mobile UX while maintaining readability on larger screens.

components/waves/drop/SingleWaveDropAuthor.tsx (1)

22-38: LGTM!

The modal state management with modalInitialTab and the badge click handlers are well-structured. The pattern aligns with the consolidated modal approach used across other components in this PR.

components/utils/button/ActionButton.tsx (1)

23-35: LGTM!

The button component correctly handles loading and disabled states with appropriate styling and accessibility. The type="button" prevents accidental form submissions.

components/waves/list/WaveItemFollow.tsx (1)

127-181: LGTM!

The refactoring to use SecondaryButton and ActionButton components improves consistency and reduces code duplication. The conditional rendering based on follow state is clean.

components/utils/button/SecondaryButton.tsx (1)

20-34: LGTM!

The styling updates align well with ActionButton for a consistent button component ecosystem. The rounded corners and text size standardization look intentional.

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

63-70: LGTM!

The consolidated modal handling with handleBadgeClick(tab) and handleModalClose using useCallback is well-implemented and aligns with the unified modal approach across the PR.

components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx (2)

22-40: LGTM!

The modal state management and badge click handling are well-implemented. The winnerCount derivation correctly uses the actual array length, consistent with SingleWaveDropAuthor.tsx.


71-84: LGTM!

The badge components are properly wired to open the modal with the correct initial tab. The implementation aligns well with the PR's goal of consolidating modal management.

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

94-94: LGTM! Modal close behavior is correctly implemented.

The backdrop and desktop modal container click handlers properly stop propagation and trigger onClose(). The Dialog.Panel on line 109 correctly stops propagation to prevent closing when clicking modal content, while allowing backdrop/container clicks to close the modal.

Also applies to: 98-98

components/waves/list/WaveItemDropped.tsx (1)

103-108: LGTM! Typography improvements enhance visual hierarchy.

The text color and font weight adjustments improve the contrast and readability of the drops count display, aligning with the broader UI refinements across the PR.

components/waves/list/header/WavesListHeader.tsx (1)

54-60: LGTM! Button consolidation improves consistency.

Replacing the inline button implementation with SecondaryButton improves code reusability and maintains consistent styling across the application.

components/waves/list/WaveItem.tsx (2)

186-187: LGTM! Improved image scaling and alt text.

The updated image scale (W_200_H_200) and more specific alt text with conditional formatting enhance both performance and accessibility.


355-419: LGTM! Well-structured layout improvements.

The restructured card layout with proper sectioning, responsive behavior using container queries, and clear visual hierarchy enhances both the UI and code maintainability. The use of semantic separators and proper alignment creates a polished appearance.

components/memes/drops/MemesLeaderboardDrop.tsx (1)

115-166: Footer flex-column layout change looks good

Adding tw-flex tw-flex-col tw-gap-y-4 on the footer wrapper cleanly stacks traits and the vote row with consistent spacing and doesn’t introduce any obvious interaction issues. Layout-wise this is a safe, incremental improvement.

Comment thread components/waves/drop/SingleWaveDropAuthor.tsx
Comment thread components/waves/drops/WaveDropHeader.tsx
Comment thread components/waves/list/header/WavesListHeader.tsx
Comment thread components/waves/list/WaveItem.tsx
Signed-off-by: ragnep <ragneinfo@gmail.com>
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: 0

Caution

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

⚠️ Outside diff range comments (1)
components/waves/drops/ArtistPreviewModal.tsx (1)

24-25: Unused modalRef — focus logic is ineffective.

modalRef is declared but never attached to any element (no ref={modalRef} on Dialog.Panel). The setTimeout call on line 50 will always attempt to focus null. Either attach the ref to the Dialog.Panel or remove the dead code.

-  const modalRef = useRef<HTMLDialogElement>(null);

Or attach it to the panel if focus management is intended:

-              <Dialog.Panel className="tw-relative tw-w-full tw-max-w-5xl ...">
+              <Dialog.Panel ref={modalRef} className="tw-relative tw-w-full tw-max-w-5xl ..." tabIndex={-1}>
♻️ Duplicate comments (1)
components/waves/drops/WaveDropHeader.tsx (1)

95-101: winCount is hardcoded to 1 instead of using actual count.

Unlike MemeDropArtistInfo.tsx (line 30-31) and MemesLeaderboardDropArtistInfo.tsx (line 32-33) which derive winnerCount from drop.author.winner_main_stage_drop_ids?.length, this component hardcodes winCount={1}. This causes incorrect tooltip text when there are multiple wins.

Apply this fix for consistency:

+  const winnerCount = useMemo(() =>
+    drop.author.winner_main_stage_drop_ids?.length || 0,
+    [drop.author.winner_main_stage_drop_ids]
+  );
+
   const isWinner = useMemo(() =>
-    drop.author.winner_main_stage_drop_ids &&
-    drop.author.winner_main_stage_drop_ids.length > 0,
+    winnerCount > 0,
-    [drop.author.winner_main_stage_drop_ids]
+    [winnerCount]
   );

Then update the badge:

             <ProfileWinnerBadge
-              winCount={1}
+              winCount={winnerCount}
               onBadgeClick={() => handleBadgeClick("winners")}
🧹 Nitpick comments (3)
components/waves/drops/ArtistPreviewModal.tsx (1)

11-11: Consider importing ArtistPreviewTab from the hook instead of defining a duplicate type.

ModalTab in this file and ArtistPreviewTab in hooks/useArtistPreviewModal.ts are identical. Consolidating to a single source of truth avoids drift.

-export type ModalTab = "active" | "winners";
+import { ArtistPreviewTab as ModalTab } from "@/hooks/useArtistPreviewModal";
+export type { ModalTab };
components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx (1)

3-3: Consider using named imports per coding guidelines.

The coding guidelines prefer direct named imports for React hooks (e.g., import { useMemo } from "react") over namespace usage. Since this file doesn't use any React hooks directly (they're in the custom hook), this import could be removed entirely or kept minimal.

If no React namespace usage is needed:

-import React from "react";
components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (1)

3-3: Same optional refactor: consider removing unused React namespace import.

-import React from "react";
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 883cfe2 and a6c83aa.

📒 Files selected for processing (5)
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (5 hunks)
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx (4 hunks)
  • components/waves/drops/ArtistPreviewModal.tsx (2 hunks)
  • components/waves/drops/WaveDropHeader.tsx (4 hunks)
  • hooks/useArtistPreviewModal.ts (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:

  • hooks/useArtistPreviewModal.ts
  • components/waves/drops/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.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:

  • hooks/useArtistPreviewModal.ts
  • components/waves/drops/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.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:

  • hooks/useArtistPreviewModal.ts
  • components/waves/drops/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.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/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx
🧠 Learnings (3)
📚 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:

  • hooks/useArtistPreviewModal.ts
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.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/drops/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.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} : Prefer Server Components over Client Components; use Server Functions/Server Actions (`'use server'`) for mutations

Applied to files:

  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx
🧬 Code graph analysis (3)
components/waves/drops/WaveDropHeader.tsx (4)
hooks/useArtistPreviewModal.ts (1)
  • useArtistPreviewModal (5-24)
helpers/Helpers.ts (1)
  • cicToType (497-515)
components/waves/drops/ProfileWinnerBadge.tsx (1)
  • ProfileWinnerBadge (26-88)
components/waves/drops/ArtistPreviewModal.tsx (1)
  • ArtistPreviewModal (20-156)
components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (4)
hooks/useArtistPreviewModal.ts (1)
  • useArtistPreviewModal (5-24)
components/waves/drops/ProfileWinnerBadge.tsx (1)
  • ProfileWinnerBadge (26-88)
components/waves/drops/ArtistSubmissionBadge.tsx (1)
  • ArtistSubmissionBadge (26-90)
components/waves/drops/ArtistPreviewModal.tsx (1)
  • ArtistPreviewModal (20-156)
components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx (5)
helpers/waves/drop.helpers.ts (1)
  • ExtendedDrop (16-20)
hooks/useArtistPreviewModal.ts (1)
  • useArtistPreviewModal (5-24)
components/waves/drops/ProfileWinnerBadge.tsx (1)
  • ProfileWinnerBadge (26-88)
components/waves/drops/ArtistSubmissionBadge.tsx (1)
  • ArtistSubmissionBadge (26-90)
components/waves/drops/ArtistPreviewModal.tsx (1)
  • ArtistPreviewModal (20-156)
⏰ 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 (5)
components/waves/drops/ArtistPreviewModal.tsx (1)

82-95: Good improvement wiring onClose to the Dialog.

The Dialog now correctly calls onClose when clicking the backdrop or pressing Escape, and using Dialog.Backdrop is the idiomatic Headless UI approach.

hooks/useArtistPreviewModal.ts (1)

1-24: Clean hook implementation consolidating modal state.

The hook correctly encapsulates modal state and provides stable callback references via useCallback. This is a good abstraction for the repeated modal pattern across components.

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

37-38: Hook integration looks good.

The migration to useArtistPreviewModal is clean, and the modal correctly receives initialTab from the hook state.

Also applies to: 141-147

components/memes/drops/meme-participation-drop/MemeDropArtistInfo.tsx (1)

24-31: Good implementation with correct winner count derivation.

Unlike WaveDropHeader.tsx, this component correctly derives winnerCount from drop.author.winner_main_stage_drop_ids?.length and passes it to ProfileWinnerBadge. The hook integration is clean.

Also applies to: 62-75

components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (1)

26-33: Correct implementation with proper winner count handling.

The hook integration and winner count derivation are implemented correctly and consistently with MemeDropArtistInfo.tsx.

Also applies to: 72-85

Signed-off-by: ragnep <ragneinfo@gmail.com>
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: 0

Caution

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

⚠️ Outside diff range comments (1)
components/waves/drops/ArtistPreviewModal.tsx (1)

83-99: Restore ESC-key close support by wiring the Dialog's onClose handler

The onClose={() => {}} handler on the Dialog component disables ESC-key closing, which is a UX/a11y regression. Users expect to close modals with ESC, and this is required per accessibility guidelines.

The custom backdrop and container click handlers with stopPropagation() will continue to work correctly alongside Dialog's internal ESC handling. Restore it by passing the prop:

-      <Dialog as="div" className="tw-cursor-default tw-relative tw-z-[9999]" onClose={() => {}}>
+      <Dialog as="div" className="tw-cursor-default tw-relative tw-z-[9999]" onClose={onClose}>
🧹 Nitpick comments (2)
components/waves/drops/ArtistPreviewModal.tsx (2)

24-27: modalRef is never attached; focus management effect is a no‑op

modalRef is created and used in the effect to call modalRef.current?.focus(), but it is not attached to any JSX element, so current stays null and the focus logic never runs in practice.

Either:

  • Attach modalRef to the element you actually want to receive focus (e.g. the visible Dialog.Panel), or
  • Remove the ref and the focus logic if you no longer need custom focus handling.

Right now this is dead complexity and gives a false sense of focus management being in place. As per coding guidelines, prefer keeping side‑effect code minimal and purposeful.

Also applies to: 40-52


28-39: Inline comments in TSX conflict with “no comments in code” guideline

There are several inline comments (e.g., “Check if user has winning artworks”, “Desktop modal”, “Mobile slide-up modal”, etc.). The repo guidelines ask for no comments in TS/TSX/JS/JSX, favoring self‑explanatory code instead.

Not urgent, but consider removing these comments or replacing them with clearer naming/structure so the code is self‑documenting.

Also applies to: 63-78, 97-99, 124-125

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a6c83aa and fbab55e.

📒 Files selected for processing (1)
  • components/waves/drops/ArtistPreviewModal.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/ArtistPreviewModal.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/ArtistPreviewModal.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/ArtistPreviewModal.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/ArtistPreviewModal.tsx
🧠 Learnings (1)
📚 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/drops/ArtistPreviewModal.tsx
⏰ 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)

Signed-off-by: ragnep <ragneinfo@gmail.com>
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: 0

Caution

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

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

47-69: Else branch renders Link with potentially undefined handle.

When drop.author?.handle is falsy, the else branch still renders a Link to /${drop.author?.handle} and displays {drop.author?.handle} which would be empty or "undefined". This appears to be unreachable or erroneous UI.

Consider either removing the else branch entirely or providing a fallback display:

          {drop.author?.handle ? (
            <UserProfileTooltipWrapper user={drop.author.handle ?? drop.author.id}>
              <Link
                href={`/${drop.author?.handle}`}
                onClick={(e) => e.stopPropagation()}
                className="tw-no-underline desktop-hover:hover:tw-underline"
              >
                <span className="tw-text-sm tw-font-bold tw-text-white">
                  {drop.author?.handle}
                </span>
              </Link>
            </UserProfileTooltipWrapper>
-          ) : (
-            <Link
-              href={`/${drop.author?.handle}`}
-              onClick={(e) => e.stopPropagation()}
-              className="tw-no-underline desktop-hover:hover:tw-underline"
-            >
-              <span className="tw-text-sm tw-font-bold tw-text-white">
-                {drop.author?.handle}
-              </span>
-            </Link>
-          )}
+          ) : null}
🧹 Nitpick comments (1)
components/waves/drops/ArtistPreviewModal.tsx (1)

41-50: Body overflow cleanup uses 'unset' instead of preserving original value.

The cleanup sets overflow to 'unset' rather than restoring the original value. This works in most cases but could override intentional overflow settings on the body if they existed before the modal opened.

If the body might have pre-existing overflow styles, consider preserving the original:

  useEffect(() => {
    if (isOpen && !isApp) {
+     const originalOverflow = document.body.style.overflow;
      document.body.style.overflow = 'hidden';

      return () => {
-       document.body.style.overflow = 'unset';
+       document.body.style.overflow = originalOverflow;
      };
    }
  }, [isOpen, isApp]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fbab55e and b1557b5.

📒 Files selected for processing (3)
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (3 hunks)
  • components/waves/drops/ArtistPreviewModal.tsx (3 hunks)
  • components/waves/drops/WaveDropHeader.tsx (4 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/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.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/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.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/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.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/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.tsx
🧠 Learnings (4)
📓 Common learnings
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
📚 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/drops/WaveDropHeader.tsx
  • components/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.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/memes/drops/MemesLeaderboardDropArtistInfo.tsx
  • components/waves/drops/ArtistPreviewModal.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/ArtistPreviewModal.tsx
🧬 Code graph analysis (1)
components/waves/drops/WaveDropHeader.tsx (2)
hooks/useArtistPreviewModal.ts (1)
  • useArtistPreviewModal (5-24)
components/waves/drops/ArtistPreviewModal.tsx (1)
  • ArtistPreviewModal (21-147)
⏰ 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 (7)
components/waves/drops/WaveDropHeader.tsx (3)

16-17: Good consolidation of modal state management.

The migration to useArtistPreviewModal hook properly centralizes modal control logic. This aligns well with the PR's objective to unify modal handling across components.

Also applies to: 37-38


51-56: Previous issue resolved: winCount now uses actual count.

The hardcoded winCount={1} flagged in previous review is fixed. The component now correctly derives winnerCount from drop.author.winner_main_stage_drop_ids?.length and passes it to ProfileWinnerBadge.


96-102: Badge integration looks correct.

The ProfileWinnerBadge properly receives winCount={winnerCount} and triggers handleBadgeClick("winners") to open the modal on the correct tab.

components/memes/drops/MemesLeaderboardDropArtistInfo.tsx (2)

15-16: Consistent hook integration.

The component correctly adopts useArtistPreviewModal for centralized modal control, matching the pattern used in other components.

Also applies to: 22-26


71-84: Badge integration is correct.

Both ProfileWinnerBadge and ArtistSubmissionBadge properly use handleBadgeClick with the appropriate tab identifiers.

components/waves/drops/ArtistPreviewModal.tsx (2)

6-6: Clean import refactoring and type re-export.

The import cleanup and re-export of ModalTab type from the hook centralizes the type definition, improving maintainability.

Also applies to: 10-10, 12-12


74-74: Dialog onClose no-op disables Escape key dismissal.

Passing onClose={() => {}} to Headless UI's Dialog prevents the Escape key from closing the modal, which may impact keyboard accessibility. If Escape should close the modal, pass onClose directly.

If Escape key dismissal is desired:

-      <Dialog as="div" className="tw-cursor-default tw-relative tw-z-[9999]" onClose={() => {}}>
+      <Dialog as="div" className="tw-cursor-default tw-relative tw-z-[9999]" onClose={onClose}>

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

@ragnep ragnep merged commit 3c6e5fd into main Dec 11, 2025
8 checks passed
@ragnep ragnep deleted the submissions-badge-add branch December 11, 2025 13:14
@coderabbitai coderabbitai Bot mentioned this pull request Jan 3, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Mar 5, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Apr 17, 2026
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