From 08cb0736daee6dabbc9f5e3ec0e6165ed008c04b Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Mon, 27 May 2024 12:28:18 +0200 Subject: [PATCH] feat(post): add post menu component with links to other clients --- .../post/post-desktop/post-desktop.tsx | 33 +------ src/components/post/post-menu/index.ts | 1 + .../post/post-menu/post-menu.module.css | 86 +++++++++++++++++++ src/components/post/post-menu/post-menu.tsx | 72 ++++++++++++++++ src/components/post/post.module.css | 49 ----------- src/themes.css | 74 ++++++++++++---- src/views/post-page/post-page.module.css | 3 + 7 files changed, 223 insertions(+), 95 deletions(-) create mode 100644 src/components/post/post-menu/index.ts create mode 100644 src/components/post/post-menu/post-menu.module.css create mode 100644 src/components/post/post-menu/post-menu.tsx diff --git a/src/components/post/post-desktop/post-desktop.tsx b/src/components/post/post-desktop/post-desktop.tsx index d23a0b06..0e1f3eb8 100644 --- a/src/components/post/post-desktop/post-desktop.tsx +++ b/src/components/post/post-desktop/post-desktop.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { useLocation, useParams } from 'react-router-dom'; import { Link } from 'react-router-dom'; @@ -17,6 +17,7 @@ import LoadingEllipsis from '../../loading-ellipsis'; import Markdown from '../../markdown'; import { PostProps } from '../post'; import styles from '../post.module.css'; +import PostMenu from '../post-menu'; import _ from 'lodash'; const PostInfo = ({ openReplyModal, post, roles }: PostProps) => { @@ -41,30 +42,6 @@ const PostInfo = ({ openReplyModal, post, roles }: PostProps) => { const account = useAccount(); const accountShortAddress = account?.author?.shortAddress; - const [menuBtnRotated, setMenuBtnRotated] = useState(false); - const menuRef = useRef(null); - - const handleMenuButtonClick = () => { - setMenuBtnRotated((prev) => !prev); - }; - - const handleClickOutside = (event: MouseEvent) => { - if (menuRef.current && !menuRef.current.contains(event.target as Node)) { - setMenuBtnRotated(false); - } - }; - - useEffect(() => { - if (menuBtnRotated) { - document.addEventListener('mousedown', handleClickOutside); - } else { - document.removeEventListener('mousedown', handleClickOutside); - } - return () => { - document.removeEventListener('mousedown', handleClickOutside); - }; - }, [menuBtnRotated]); - return (
@@ -125,11 +102,7 @@ const PostInfo = ({ openReplyModal, post, roles }: PostProps) => { )} - - - ▶ - - +
); }; diff --git a/src/components/post/post-menu/index.ts b/src/components/post/post-menu/index.ts new file mode 100644 index 00000000..7c04c4cc --- /dev/null +++ b/src/components/post/post-menu/index.ts @@ -0,0 +1 @@ +export { default } from './post-menu'; diff --git a/src/components/post/post-menu/post-menu.module.css b/src/components/post/post-menu/post-menu.module.css new file mode 100644 index 00000000..79dd778e --- /dev/null +++ b/src/components/post/post-menu/post-menu.module.css @@ -0,0 +1,86 @@ +.postMenu { + position: absolute; + background-color: var(--post-menu-background-color); + border-bottom: 2px solid var(--post-menu-border-color); + border-right: 1px solid var(--post-menu-border-color); + outline: none; +} + +.postMenuBtnWrapper { + position: relative; + display: inline-block; + padding-left: 15px; +} + +.postMenuBtn { + color: var(--post-menu-button-color); + transition: transform 0.1s; + transform: rotate(90deg); + position: absolute; + bottom: -4px; +} + +.postMenuBtn:hover { + cursor: pointer; + color: var(--post-menu-button-color-hover); +} + +.postMenuItem { + cursor: pointer; + padding: 2px 4px; + border: 1px solid var(--post-menu-item-border-color); + background-color: var(--post-menu-item-background-color); + border-bottom: none; +} + +.postMenuItem:hover { + background-color: var(--post-menu-item-hover-background-color); +} + +.dropdown { + position: relative; + display: inline-block; +} + +.dropdownMenu { + position: absolute; + left: 100%; + top: -1px; + display: none; + border-bottom: 2px solid var(--post-menu-border-color); + border-right: 1px solid var(--post-menu-border-color); +} + +.dropdown a { + text-decoration: none; + color: inherit; +} + +.dropdown:hover .dropdownMenu { + display: block; +} + +@media (max-width: 640px) { + .postMenuBtn { + width: 1em; + text-align: center; + font-weight: 700; + font-size: 16px; + } + + .postMenuBtnWrapper { + position: relative; + padding-right: 12px; + } +} + +@media (min-width: 640px) { + .postMenuBtn { + right: -2px; + opacity: var(--post-menu-btn-opacity); + } + + .stickyIconWrapper { + padding-right: 18px; + } +} diff --git a/src/components/post/post-menu/post-menu.tsx b/src/components/post/post-menu/post-menu.tsx new file mode 100644 index 00000000..d9f00ba7 --- /dev/null +++ b/src/components/post/post-menu/post-menu.tsx @@ -0,0 +1,72 @@ +import { useState } from 'react'; +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'; + +const PostMenu = ({ post }: Comment) => { + const { cid, isDescription, isRules, link, subplebbitAddress } = post; + const [menuBtnRotated, setMenuBtnRotated] = useState(false); + const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false); + + const { refs, floatingStyles, context } = useFloating({ + placement: 'bottom-start', + open: menuBtnRotated, + onOpenChange: setMenuBtnRotated, + middleware: [offset({ mainAxis: 10, crossAxis: 5 }), flip({ fallbackAxisSideDirection: 'end' }), shift({ padding: 10 })], + whileElementsMounted: autoUpdate, + }); + + const click = useClick(context); + const dismiss = useDismiss(context); + const role = useRole(context); + + const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss, role]); + + const headingId = useId(); + + const viewOnOtherClientLink = `p/${subplebbitAddress}${isDescription || isRules ? '' : `/c/${cid}`}`; + + return ( + <> + + setMenuBtnRotated((prev) => !prev)} + style={{ transform: menuBtnRotated ? 'rotate(90deg)' : 'rotate(0deg)' }} + > + ▶ + + + {menuBtnRotated && ( + +
+
setIsClientRedirectMenuOpen(true)} + onMouseLeave={() => setIsClientRedirectMenuOpen(false)} + > + View on » + {isClientRedirectMenuOpen && ( + + )} +
+
+
+ )} + + ); +}; + +export default PostMenu; diff --git a/src/components/post/post.module.css b/src/components/post/post.module.css index 902debc5..8cfe0d3b 100644 --- a/src/components/post/post.module.css +++ b/src/components/post/post.module.css @@ -131,37 +131,6 @@ color: var(--button-desktop-text-color-hover); } -.postMenuBtnWrapper { - position: relative; - display: inline-block; - padding-left: 5px; -} - -.replyDesktop .postMenuBtnWrapper { - padding-right: 12px; -} - -.replyDesktop .stickyIconWrapper { - padding-right: 18px; -} - -.postDesktop .postMenuBtn, .replyDesktop .postMenuBtn { - color: var(--post-menu-button-color); - transition: transform 0.1s; - position: absolute; - opacity: var(--post-menu-btn-opacity); - bottom: -4px; -} - -.replyDesktop .postMenuBtn { - right: -2px; -} - -.postDesktop .postMenuBtn:hover, .replyDesktop .postMenuBtn:hover { - cursor: pointer; - color: var(--post-menu-button-color-hover); -} - .postDesktop .spacer { width: 100%; padding: 5px; @@ -260,20 +229,6 @@ clear: left; } -.postMobile .postMenuBtn { - color: var(--post-mobile-menu-button-color); - line-height: 1em; - width: 1em; - text-align: center; - transition: transform 0.1s; - transform: rotate(90deg); - -webkit-transform: rotate(90deg); - float: left; - font-weight: 700; - font-size: 16px; - height: 100%; -} - .postMobile .nameBlock { clear: none; } @@ -408,10 +363,6 @@ color: var(--post-mobile-info-text-color); } -.replyMobile .postInfo .postMenuBtn { - width: 1em; -} - .replyMobile .nameBlock { display: inline; float: left; diff --git a/src/themes.css b/src/themes.css index 88f4de91..e08c2e23 100644 --- a/src/themes.css +++ b/src/themes.css @@ -103,6 +103,29 @@ --post-greentext-color: #789922; --post-replies-expand-button-background-image: url("/public/assets/buttons/plus-red.png"); + /* post form */ + --post-form-toggle-font-size: 22px; + --post-form-toggle-font-weight: 700; + --post-form-field-title-background-color: #ea8; + --post-form-field-title-color: #800; + --post-form-field-border: 1px solid #800; + --post-form-field-title-font-weight: 700; + --post-form-field-title-padding: 0 5px; + --post-form-field-title-font-size: 10pt; + --post-form-field-input-border: 1px solid #aaa; + --post-form-field-font-family: arial, helvetica, sans-serif; + --post-form-field-input-appearance: none; + --post-form-field-input-outline: none; + --post-form-field-input-focus-border: 1px solid #ea8; + --post-form-field-input-color: #000; + + /* post menu */ + --post-menu-border-color: #d9bfb7; + --post-menu-background-color: #f0e0d6; + --post-menu-item-border-color: #d9bfb7; + --post-menu-item-background-color: #f0e0d6; + --post-menu-item-hover-background-color: #ffe; + /* post mobile */ --post-mobile-background-color: #f5e9e1; --post-mobile-info-border-bottom: 1px solid #d9bfb7; @@ -120,22 +143,6 @@ --post-mobile-file-info-text-color: #707070; --post-mobile-content-font-size: 11pt; - /* post form */ - --post-form-toggle-font-size: 22px; - --post-form-toggle-font-weight: 700; - --post-form-field-title-background-color: #ea8; - --post-form-field-title-color: #800; - --post-form-field-border: 1px solid #800; - --post-form-field-title-font-weight: 700; - --post-form-field-title-padding: 0 5px; - --post-form-field-title-font-size: 10pt; - --post-form-field-input-border: 1px solid #aaa; - --post-form-field-font-family: arial, helvetica, sans-serif; - --post-form-field-input-appearance: none; - --post-form-field-input-outline: none; - --post-form-field-input-focus-border: 1px solid #ea8; - --post-form-field-input-color: #000; - /* quotelink */ --post-quotelink-text-color: navy; --post-quotelink-text-color-hover: red; @@ -288,6 +295,13 @@ --post-form-field-input-focus-border: 1px solid #98e; --post-form-field-input-color: #000; + /* post menu */ + --post-menu-border-color: #b7c5d9; + --post-menu-background-color: #d6daf0; + --post-menu-item-border-color: #b7c5d9; + --post-menu-item-background-color: #d6daf0; + --post-menu-item-hover-background-color: #eef2ff; + /* post mobile */ --post-mobile-background-color: #d6daf0; --post-mobile-info-border-bottom: 1px solid #b7c5d9; @@ -427,6 +441,13 @@ --post-form-field-title-font-size: 16px; --post-form-field-input-color: #000; + /* post menu */ + --post-menu-border-color: #d9bfb7; + --post-menu-background-color: #f0e0d6; + --post-menu-item-border-color: #d9bfb7; + --post-menu-item-background-color: #f0e0d6; + --post-menu-item-hover-background-color: #ffe; + /* post mobile */ --post-mobile-background-color: #f5e9e1; --post-mobile-info-border-bottom: 1px solid #d9bfb7; @@ -576,6 +597,13 @@ --post-form-field-title-font-size: 16px; --post-form-field-input-color: #000; + /* post menu */ + --post-menu-border-color: #b7c5d9; + --post-menu-background-color: #d6daf0; + --post-menu-item-border-color: #b7c5d9; + --post-menu-item-background-color: #d6daf0; + --post-menu-item-hover-background-color: #eef2ff; + /* post mobile */ --post-mobile-background-color: #d6daf0; --post-mobile-info-border-bottom: 1px solid #b7c5d9; @@ -733,6 +761,13 @@ --post-form-field-input-appearance: none; --post-form-field-input-outline: none; + /* post menu */ + --post-menu-border-color: #000; + --post-menu-background-color: #282a2e; + --post-menu-item-border-color: #000; + --post-menu-item-background-color: #282a2e; + --post-menu-item-hover-background-color: #1d1f21; + /* post mobile */ --post-mobile-background-color: #282A2E; --post-mobile-info-border-top: 1px solid #2D2F33; @@ -908,6 +943,13 @@ --post-form-field-input-focus-border: 1px solid #ea8; --post-form-field-input-color: #000; + /* post menu */ + --post-menu-border-color: #ccc; + --post-menu-background-color: #ddd; + --post-menu-item-border-color: #ccc; + --post-menu-item-background-color: #ddd; + --post-menu-item-hover-background-color: #eee; + /* quotelink */ --post-quotelink-text-color: #f60; --post-quotelink-text-color-hover: #f30; diff --git a/src/views/post-page/post-page.module.css b/src/views/post-page/post-page.module.css index e69de29b..b4afdfd6 100644 --- a/src/views/post-page/post-page.module.css +++ b/src/views/post-page/post-page.module.css @@ -0,0 +1,3 @@ +.content { + margin-bottom: 150px; +} \ No newline at end of file