diff --git a/__tests__/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.interaction.test.tsx b/__tests__/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.interaction.test.tsx
index 1b9592c91f..7d3db094f4 100644
--- a/__tests__/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.interaction.test.tsx
+++ b/__tests__/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.interaction.test.tsx
@@ -1,74 +1,144 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
-import { DefaultWaveLeaderboardDrop } from '@/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop';
+import React from "react";
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { DefaultWaveLeaderboardDrop } from "@/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop";
-jest.mock('next/navigation', () => ({
+jest.mock("next/navigation", () => ({
useRouter: jest.fn(() => ({ push: jest.fn() })),
- usePathname: () => '/',
- useSearchParams: () => ({ toString: () => '', get: () => null }),
+ usePathname: () => "/",
+ useSearchParams: () => ({ toString: () => "", get: () => null }),
}));
-jest.mock('@/hooks/drops/useDropInteractionRules', () => ({
+jest.mock("@/hooks/drops/useDropInteractionRules", () => ({
useDropInteractionRules: jest.fn(),
}));
-jest.mock('@/hooks/useDeviceInfo', () => jest.fn());
-jest.mock('@/hooks/isMobileScreen', () => jest.fn());
-jest.mock('@/hooks/useLongPressInteraction', () => jest.fn());
-jest.mock('@/components/voting', () => ({
+jest.mock("@/hooks/useDeviceInfo", () => jest.fn());
+jest.mock("@/hooks/isMobileScreen", () => jest.fn());
+jest.mock("@/hooks/useLongPressInteraction", () => jest.fn());
+jest.mock("@/components/voting", () => ({
VotingModal: (p: any) =>
{String(p.isOpen)}
,
- MobileVotingModal: (p: any) => {String(p.isOpen)}
,
+ MobileVotingModal: (p: any) => (
+ {String(p.isOpen)}
+ ),
}));
-jest.mock('@/components/voting/VotingModalButton', () => (p: any) => );
-jest.mock('@/components/waves/drops/WaveDropActionsOptions', () => ({ __esModule: true, default: () => }));
-jest.mock('@/components/waves/drops/WaveDropActionsOpen', () => ({ __esModule: true, default: () => }));
-jest.mock('@/components/waves/drops/WaveDropMobileMenuOpen', () => () => );
-jest.mock('@/components/waves/drops/WaveDropMobileMenuDelete', () => () => );
-jest.mock('@/components/utils/select/dropdown/CommonDropdownItemsMobileWrapper', () => (p: any) => {p.children}
);
-jest.mock('@/components/waves/leaderboard/drops/header/WaveLeaderboardDropHeader', () => ({ WaveLeaderboardDropHeader: () => }));
-jest.mock('@/components/waves/leaderboard/content/WaveLeaderboardDropContent', () => ({ WaveLeaderboardDropContent: () => }));
-jest.mock('@/components/waves/leaderboard/drops/footer/WaveLeaderboardDropFooter', () => ({ WaveLeaderboardDropFooter: () => }));
-jest.mock('@/components/waves/leaderboard/drops/header/WaveleaderboardDropRaters', () => ({ WaveLeaderboardDropRaters: () => }));
+jest.mock("@/components/voting/VotingModalButton", () => (p: any) => (
+
+));
+jest.mock("@/components/waves/drops/WaveDropActionsOptions", () => ({
+ __esModule: true,
+ default: () => ,
+}));
+jest.mock("@/components/waves/drops/WaveDropActionsOpen", () => ({
+ __esModule: true,
+ default: () => ,
+}));
+jest.mock("@/components/waves/drops/WaveDropMobileMenuOpen", () => () => (
+
+));
+jest.mock("@/components/waves/drops/WaveDropMobileMenuDelete", () => () => (
+
+));
+jest.mock(
+ "@/components/utils/select/dropdown/CommonDropdownItemsMobileWrapper",
+ () => (p: any) => {p.children}
+);
+jest.mock(
+ "@/components/waves/leaderboard/drops/header/WaveLeaderboardDropHeader",
+ () => ({ WaveLeaderboardDropHeader: () => })
+);
+jest.mock(
+ "@/components/waves/leaderboard/content/WaveLeaderboardDropContent",
+ () => ({ WaveLeaderboardDropContent: () => })
+);
+jest.mock(
+ "@/components/waves/leaderboard/drops/footer/WaveLeaderboardDropFooter",
+ () => ({ WaveLeaderboardDropFooter: () => })
+);
+jest.mock(
+ "@/components/waves/leaderboard/drops/header/WaveleaderboardDropRaters",
+ () => ({ WaveLeaderboardDropRaters: () => })
+);
-const useRules = require('@/hooks/drops/useDropInteractionRules').useDropInteractionRules as jest.Mock;
-const useDeviceInfo = require('@/hooks/useDeviceInfo') as jest.Mock;
-const useIsMobileScreen = require('@/hooks/isMobileScreen') as jest.Mock;
-const useLongPressInteraction = require('@/hooks/useLongPressInteraction') as jest.Mock;
+const useRules = require("@/hooks/drops/useDropInteractionRules")
+ .useDropInteractionRules as jest.Mock;
+const useDeviceInfo = require("@/hooks/useDeviceInfo") as jest.Mock;
+const useIsMobileScreen = require("@/hooks/isMobileScreen") as jest.Mock;
+const useLongPressInteraction =
+ require("@/hooks/useLongPressInteraction") as jest.Mock;
-const drop = {
- id: 'd1',
+const drop = {
+ id: "d1",
rank: 1,
author: {
- handle: 'testuser',
+ handle: "testuser",
pfp: null,
level: 1,
- cic: 0
+ cic: 0,
},
- created_at: new Date().toISOString()
+ created_at: new Date().toISOString(),
} as any;
-const wave = { id: 'w1' } as any;
+const wave = { id: "w1" } as any;
beforeEach(() => {
- useLongPressInteraction.mockReturnValue({ isActive: false, setIsActive: jest.fn(), touchHandlers: {} });
+ useLongPressInteraction.mockReturnValue({
+ isActive: false,
+ setIsActive: jest.fn(),
+ touchHandlers: {},
+ });
});
-test('opens voting modal when button clicked', async () => {
+test("opens voting modal when button clicked", async () => {
const user = userEvent.setup();
useRules.mockReturnValue({ canShowVote: true, canDelete: true });
useDeviceInfo.mockReturnValue({ hasTouchScreen: false });
useIsMobileScreen.mockReturnValue(false);
- render();
- expect(screen.getByTestId('modal')).toHaveTextContent('false');
- await user.click(screen.getByTestId('vote-btn'));
- expect(screen.getByTestId('modal')).toHaveTextContent('true');
- expect(screen.getByTestId('options')).toBeInTheDocument();
+ render(
+
+ );
+ expect(screen.getByTestId("modal")).toHaveTextContent("false");
+ await user.click(screen.getByTestId("vote-btn"));
+ expect(screen.getByTestId("modal")).toHaveTextContent("true");
+ expect(screen.getByTestId("options")).toBeInTheDocument();
});
-test('uses mobile modal and hides options when cannot delete', () => {
+test("uses mobile modal and hides options when cannot delete", () => {
useRules.mockReturnValue({ canShowVote: true, canDelete: false });
useDeviceInfo.mockReturnValue({ hasTouchScreen: false });
useIsMobileScreen.mockReturnValue(true);
- useLongPressInteraction.mockReturnValue({ isActive: false, setIsActive: jest.fn(), touchHandlers: {} });
- render();
- expect(screen.getByTestId('mobile')).toHaveTextContent('false');
- expect(screen.queryByTestId('options')).toBeNull();
+ useLongPressInteraction.mockReturnValue({
+ isActive: false,
+ setIsActive: jest.fn(),
+ touchHandlers: {},
+ });
+ render(
+
+ );
+ expect(screen.getByTestId("mobile")).toHaveTextContent("false");
+ expect(screen.queryByTestId("options")).toBeNull();
+});
+
+test("keeps native touch scrolling enabled for long-press handlers", () => {
+ useRules.mockReturnValue({ canShowVote: true, canDelete: false });
+ useDeviceInfo.mockReturnValue({ hasTouchScreen: true });
+ useIsMobileScreen.mockReturnValue(true);
+
+ render(
+
+ );
+
+ expect(useLongPressInteraction).toHaveBeenCalledWith({
+ hasTouchScreen: true,
+ preventDefault: false,
+ });
});
diff --git a/components/brain/BrainMobile.tsx b/components/brain/BrainMobile.tsx
index 4d118c9145..27159387f4 100644
--- a/components/brain/BrainMobile.tsx
+++ b/components/brain/BrainMobile.tsx
@@ -344,7 +344,7 @@ const BrainMobile: React.FC = ({ children }) => {
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
transition={{ duration: 0.2, ease: "easeInOut" }}
- className="tw-flex-1"
+ className="tw-min-w-0 tw-flex-1"
>
{viewComponents[activeView]}
diff --git a/components/brain/my-stream/MyStreamWave.tsx b/components/brain/my-stream/MyStreamWave.tsx
index 4718d1e54a..7844db1a20 100644
--- a/components/brain/my-stream/MyStreamWave.tsx
+++ b/components/brain/my-stream/MyStreamWave.tsx
@@ -135,7 +135,7 @@ const MyStreamWave: React.FC = ({ waveId }) => {
return (
{/* Always render tab container (hidden on app inside MyStreamWaveTabs) */}
@@ -147,7 +147,7 @@ const MyStreamWave: React.FC
= ({ waveId }) => {
/>
diff --git a/components/brain/my-stream/MyStreamWaveLeaderboard.tsx b/components/brain/my-stream/MyStreamWaveLeaderboard.tsx
index 28dfb3bbba..a1dabd70b4 100644
--- a/components/brain/my-stream/MyStreamWaveLeaderboard.tsx
+++ b/components/brain/my-stream/MyStreamWaveLeaderboard.tsx
@@ -58,7 +58,7 @@ const MyStreamWaveLeaderboard: React.FC = ({
}, []);
const containerClassName = useMemo(() => {
- return `tw-w-full tw-flex tw-flex-col tw-rounded-t-xl tw-overflow-y-auto tw-scrollbar-thin tw-scrollbar-thumb-iron-500 tw-scrollbar-track-iron-800 desktop-hover:hover:tw-scrollbar-thumb-iron-300 tw-overflow-x-hidden tw-flex-grow tw-px-2 sm:tw-px-4`;
+ return `tw-w-full tw-min-w-0 tw-flex tw-flex-col tw-rounded-t-xl tw-overflow-y-auto tw-scrollbar-thin tw-scrollbar-thumb-iron-500 tw-scrollbar-track-iron-800 desktop-hover:hover:tw-scrollbar-thumb-iron-300 tw-overflow-x-hidden tw-flex-grow tw-px-2 sm:tw-px-4`;
}, []);
const [isCreateDropOpen, setIsCreateDropOpen] = useState(false);
@@ -287,7 +287,7 @@ const MyStreamWaveLeaderboard: React.FC = ({
{/* Content section */}
-
+
{showToggleableDropInput && (
{
- {rank === 1 ? "LEADING" : `CURRENT ${formatOrdinal(rank)} PLACE`}
+ {rank === 1 ? "LEADING" : `${formatOrdinal(rank)} PLACE`}
diff --git a/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx b/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx
index 8068377679..c4a0724598 100644
--- a/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx
+++ b/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx
@@ -37,6 +37,7 @@ export const DefaultWaveLeaderboardDrop: React.FC<
// Use the hook for long press interactions
const { isActive, setIsActive, touchHandlers } = useLongPressInteraction({
hasTouchScreen,
+ preventDefault: false,
});
const getBorderClasses = () => {
diff --git a/components/waves/leaderboard/gallery/WaveLeaderboardGallery.tsx b/components/waves/leaderboard/gallery/WaveLeaderboardGallery.tsx
index a88ab0851b..5603f8216c 100644
--- a/components/waves/leaderboard/gallery/WaveLeaderboardGallery.tsx
+++ b/components/waves/leaderboard/gallery/WaveLeaderboardGallery.tsx
@@ -71,8 +71,8 @@ export const WaveLeaderboardGallery: React.FC = ({
}
return (
-
-
+
+
{dropsWithMedia.map((drop) => (
(
? ""
: "tw-transition-all tw-duration-300 tw-ease-out";
const groupClasses = artFocused ? `tw-group ${transitionClasses}` : "";
- const containerClass = `${groupClasses} tw-relative tw-bg-iron-950/50 tw-border tw-border-solid tw-border-iron-800 tw-rounded-lg desktop-hover:hover:tw-border-iron-700 tw-shadow-lg desktop-hover:hover:tw-shadow-xl`;
+ const containerClass = `${groupClasses} tw-relative tw-w-full tw-min-w-0 tw-bg-iron-950/50 tw-border tw-border-solid tw-border-iron-800 tw-rounded-lg desktop-hover:hover:tw-border-iron-700 tw-shadow-lg desktop-hover:hover:tw-shadow-xl`;
const highlightAnimation =
isHighlighting && !hasTouchScreen ? "tw-animate-gallery-reveal" : "";
@@ -167,7 +167,7 @@ export const WaveLeaderboardGalleryItem = memo(
-
+
(
e.stopPropagation()}
href={`/${drop.author?.handle}`}
- className="tw-mt-0.5 tw-text-xs tw-text-iron-400 tw-no-underline tw-transition-colors tw-duration-150 desktop-hover:hover:tw-text-iron-300 desktop-hover:hover:tw-underline"
+ className="tw-mt-0.5 tw-block tw-max-w-full tw-truncate tw-text-xs tw-text-iron-400 tw-no-underline tw-transition-colors tw-duration-150 desktop-hover:hover:tw-text-iron-300 desktop-hover:hover:tw-underline"
>
{drop.author?.handle}
@@ -202,12 +202,14 @@ export const WaveLeaderboardGalleryItem = memo(
/>
)}
-
-
-
+
-
+
{hasUserVoted && (
-
+
{WAVE_VOTE_STATS_LABELS.YOUR_VOTES}:{" "}
{isNegativeVote && "-"}
@@ -240,7 +242,7 @@ export const WaveLeaderboardGalleryItem = memo(
)}
{canShowVote && (
-
+
= 0;
-
+
const getColorClass = () => {
if (variant === "subtle") {
return "tw-text-iron-200";
@@ -22,14 +22,16 @@ export default function WaveLeaderboardGalleryItemVotes({
};
return (
-
-
+
+
{formatNumberWithCommas(current)}
);