diff --git a/src/components/catalog-row/catalog-row.module.css b/src/components/catalog-row/catalog-row.module.css index d28ba1c8..f09270bb 100644 --- a/src/components/catalog-row/catalog-row.module.css +++ b/src/components/catalog-row/catalog-row.module.css @@ -79,36 +79,10 @@ text-decoration: none; } -.postMenuBtnPadding { - left: 5px; - top: 5px; - position: relative; +.post .postMenu { + visibility: hidden; } -.postMenuBtn { - position: absolute; - bottom: 5px; - line-height: 1em; - color: var(--catalog-post-menu-btn-color); - opacity: 0; - transition: transform 0.1s; -} - -.post:hover .postMenuBtn { - opacity: var(--catalog-post-menu-btn-opacity); -} - -.post:hover .postMenuBtn:hover { - cursor: pointer; - color: var(--catalog-post-menu-btn-hover-color); - opacity: var(--catalog-post-menu-btn-hover-opacity); -} - -.postMenuBtn { - /* preserve unicode triangle for button, some browsers will use an emoji */ - font-variant: normal; - font-feature-settings: "tnum"; - -webkit-font-feature-settings: "tnum"; /* Chrome, Opera, and Safari */ - -moz-font-feature-settings: "tnum"; /* Firefox */ - font-variant-numeric: tabular-nums; +.post:hover .postMenu { + visibility: visible; } \ No newline at end of file diff --git a/src/components/catalog-row/catalog-row.tsx b/src/components/catalog-row/catalog-row.tsx index db5cc4ca..f1bc7a1d 100644 --- a/src/components/catalog-row/catalog-row.tsx +++ b/src/components/catalog-row/catalog-row.tsx @@ -1,4 +1,3 @@ -import { useEffect, useState } from 'react'; import { Link, useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Comment } from '@plebbit/plebbit-react-hooks'; @@ -7,6 +6,7 @@ import { isAllView } from '../../lib/utils/view-utils'; import useFetchGifFirstFrame from '../../hooks/use-fetch-gif-first-frame'; import useCountLinksInReplies from '../../hooks/use-count-links-in-replies'; import styles from './catalog-row.module.css'; +import PostMenu from '../post/post-menu/post-menu'; export const CatalogPostMedia = ({ commentMediaInfo }: { commentMediaInfo: any }) => { const { patternThumbnailUrl, thumbnail, type, url } = commentMediaInfo || {}; @@ -30,13 +30,7 @@ export const CatalogPostMedia = ({ commentMediaInfo }: { commentMediaInfo: any } return thumbnailComponent; }; -interface CatalogPostProps { - post: Comment; - openMenu: boolean; - toggleMenu: () => void; -} - -const CatalogPost = ({ openMenu, post, toggleMenu }: CatalogPostProps) => { +const CatalogPost = ({ post }: { post: Comment }) => { const { t } = useTranslation(); const { cid, content, isDescription, isRules, link, linkHeight, linkWidth, locked, pinned, replyCount, subplebbitAddress, title } = post || {}; const commentMediaInfo = getCommentMediaInfo(post); @@ -76,19 +70,6 @@ const CatalogPost = ({ openMenu, post, toggleMenu }: CatalogPostProps) => { ); - useEffect(() => { - const handlePageClick = () => { - if (openMenu) { - toggleMenu(); - } - }; - document.addEventListener('click', handlePageClick); - - return () => { - document.removeEventListener('click', handlePageClick); - }; - }, [openMenu, toggleMenu]); - return (
{hasThumbnail ? ( @@ -111,18 +92,8 @@ const CatalogPost = ({ openMenu, post, toggleMenu }: CatalogPostProps) => { / L: {linkCount} )} - - { - e.stopPropagation(); - toggleMenu(); - }} - style={{ transform: openMenu ? 'rotate(90deg)' : 'rotate(0deg)' }} - > - ▶ - + +
@@ -141,16 +112,10 @@ interface CatalogRowProps { } const CatalogRow = ({ row }: CatalogRowProps) => { - const [postWithMenuOpen, setPostWithMenuOpen] = useState(null); - - const handleToggleMenu = (index: number) => { - setPostWithMenuOpen(postWithMenuOpen === index ? null : index); - }; - return (
{row.map((post, index) => ( - handleToggleMenu(index)} /> + ))}
); diff --git a/src/components/post/post-menu/post-menu.module.css b/src/components/post/post-menu/post-menu.module.css index a97282c7..451151f5 100644 --- a/src/components/post/post-menu/post-menu.module.css +++ b/src/components/post/post-menu/post-menu.module.css @@ -60,6 +60,36 @@ display: block; } +.postMenuBtnCatalogWrapper { + left: 5px; + top: 5px; + position: relative; +} + +.postMenuBtnCatalog { + position: absolute; + bottom: 5px; + line-height: 1em; + color: var(--catalog-post-menu-btn-color); + opacity: var(--catalog-post-menu-btn-opacity); + transition: transform 0.1s; +} + +.postMenuBtnCatalog:hover { + cursor: pointer; + color: var(--catalog-post-menu-btn-hover-color); + opacity: var(--catalog-post-menu-btn-hover-opacity); +} + +.postMenuBtnCatalog { + /* preserve unicode triangle for button, some browsers will use an emoji */ + font-variant: normal; + font-feature-settings: "tnum"; + -webkit-font-feature-settings: "tnum"; /* Chrome, Opera, and Safari */ + -moz-font-feature-settings: "tnum"; /* Firefox */ + font-variant-numeric: tabular-nums; +} + @media (max-width: 640px) { .postMenuBtn { width: 1em; diff --git a/src/components/post/post-menu/post-menu.tsx b/src/components/post/post-menu/post-menu.tsx index 241ff171..39dd653d 100644 --- a/src/components/post/post-menu/post-menu.tsx +++ b/src/components/post/post-menu/post-menu.tsx @@ -1,9 +1,12 @@ import { useState } from 'react'; +import { createPortal } from 'react-dom'; +import { useLocation } from 'react-router-dom'; import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react'; import { Comment } from '@plebbit/plebbit-react-hooks'; import styles from './post-menu.module.css'; import { getCommentMediaInfo } from '../../../lib/utils/media-utils'; import { copyShareLinkToClipboard, isValidURL } from '../../../lib/utils/url-utils'; +import { isCatalogView } from '../../../lib/utils/view-utils'; interface PostMenuProps { cid: string; @@ -84,11 +87,13 @@ const PostMenu = ({ post }: { post: Comment }) => { const { thumbnail, type, url } = commentMediaInfo || {}; const [menuBtnRotated, setMenuBtnRotated] = useState(false); + const isInCatalogView = isCatalogView(useLocation().pathname); + const { refs, floatingStyles, context } = useFloating({ placement: 'bottom-start', open: menuBtnRotated, onOpenChange: setMenuBtnRotated, - middleware: [offset({ mainAxis: 10, crossAxis: 5 }), flip({ fallbackAxisSideDirection: 'end' }), shift({ padding: 10 })], + middleware: [offset({ mainAxis: isInCatalogView ? -2 : 6, crossAxis: isInCatalogView ? -1 : 5 }), flip({ fallbackAxisSideDirection: 'end' }), shift({ padding: 10 })], whileElementsMounted: autoUpdate, }); const click = useClick(context); @@ -101,9 +106,9 @@ const PostMenu = ({ post }: { post: Comment }) => { return ( <> - + setMenuBtnRotated((prev) => !prev)} style={{ transform: menuBtnRotated ? 'rotate(90deg)' : 'rotate(0deg)' }} @@ -111,15 +116,17 @@ const PostMenu = ({ post }: { post: Comment }) => { ▶ - {menuBtnRotated && ( - -
- {cid && subplebbitAddress && } - {link && isValidURL(link) && (type === 'image' || type === 'gif' || thumbnail) && url && } - -
-
- )} + {menuBtnRotated && + createPortal( + +
+ {cid && subplebbitAddress && } + {link && isValidURL(link) && (type === 'image' || type === 'gif' || thumbnail) && url && } + +
+
, + document.body, + )} ); };