diff --git a/components/CommunityDialog/communitydialog.module.css b/components/CommunityDialog/communitydialog.module.css new file mode 100644 index 00000000..eba83ac9 --- /dev/null +++ b/components/CommunityDialog/communitydialog.module.css @@ -0,0 +1,70 @@ +.backdrop { + position: fixed; + inset: 0; + z-index: 100000; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; + background: rgba(0, 0, 0, 0.55); +} + +.dialog { + width: 100%; + max-width: 420px; + background: var(--secondary-bg-color); + color: var(--primary-text-color); + border-radius: 12px; + padding: 28px 24px 22px; + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.28); +} + +.dialog h2 { + font-size: 28px; + margin-bottom: 12px; +} + +.dialog p { + margin: 0 0 20px; + color: var(--secondary-text-color); + line-height: 1.5; +} + +.links { + display: flex; + flex-direction: column; + gap: 10px; +} + +.links a { + display: block; + padding: 12px 14px; + border: 1px solid var(--border-color); + border-radius: 10px; + color: var(--primary-text-color); + text-decoration: none; + font-weight: 500; +} + +.links a:hover { + border-color: var(--accent-color); + color: var(--accent-color); +} + +button.close { + margin-top: 18px; + width: 100%; + border-radius: 10px; + padding: 10px 16px; + border: 1px solid var(--primary-text-color); + background: transparent !important; + color: var(--primary-text-color); + font-weight: 500; + cursor: pointer; +} + +button.close:enabled:hover { + background: var(--accent-color) !important; + border-color: var(--accent-color) !important; + color: #fff; +} diff --git a/components/CommunityDialog/index.tsx b/components/CommunityDialog/index.tsx new file mode 100644 index 00000000..b79858c0 --- /dev/null +++ b/components/CommunityDialog/index.tsx @@ -0,0 +1,73 @@ +import { useEffect } from 'react' +import style from './communitydialog.module.css' + +interface CommunityDialogProps { + open: boolean + onClose: () => void +} + +const COMMUNITY_LINKS = [ + { + label: 'Telegram', + href: 'https://t.me/paybutton' + }, + { + label: 'X', + href: 'https://x.com/thepaybutton' + }, + { + label: 'GitHub', + href: 'https://github.com/paybutton' + } +] + +export default function CommunityDialog ({ open, onClose }: CommunityDialogProps): JSX.Element | null { + useEffect(() => { + if (!open) return undefined + const onKeyDown = (event: KeyboardEvent): void => { + if (event.key === 'Escape') onClose() + } + document.addEventListener('keydown', onKeyDown) + const previousOverflow = document.body.style.overflow + document.body.style.overflow = 'hidden' + return () => { + document.removeEventListener('keydown', onKeyDown) + document.body.style.overflow = previousOverflow + } + }, [open, onClose]) + + if (!open) return null + + return ( +
+
event.stopPropagation()} + > +

Community

+

+ PayButton is a community-driven open-source project. Join the + conversation, follow updates, and contribute. +

+
+ {COMMUNITY_LINKS.map((link) => ( + + {link.label} + + ))} +
+ +
+
+ ) +} diff --git a/components/LandingPage/Navbar.tsx b/components/LandingPage/Navbar.tsx index 2fe93e9e..0f28a011 100644 --- a/components/LandingPage/Navbar.tsx +++ b/components/LandingPage/Navbar.tsx @@ -1,10 +1,11 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' import Link from 'next/link' import Image from 'next/image' import style from 'styles/landing.module.css' import logoImageSource from 'assets/logo.png' import dynamic from 'next/dynamic' import LogoutButton from './LogoutButton' +import CommunityDialog from 'components/CommunityDialog' const ThemeToggle = dynamic( async () => await import('components/Sidebar/themetoggle'), @@ -19,6 +20,24 @@ interface IProps { export default function Navbar ({ userId }: IProps): JSX.Element { const [mobileMenu, setMobileMenu] = useState(false) + const [aboutOpen, setAboutOpen] = useState(false) + const [communityOpen, setCommunityOpen] = useState(false) + + useEffect(() => { + if (!aboutOpen) return undefined + const closeAbout = (event: MouseEvent): void => { + const target = event.target as HTMLElement + if (target.closest('[data-about-menu]') === null) setAboutOpen(false) + } + document.addEventListener('mousedown', closeAbout) + return () => document.removeEventListener('mousedown', closeAbout) + }, [aboutOpen]) + + const openCommunity = (): void => { + setAboutOpen(false) + setMobileMenu(false) + setCommunityOpen(true) + } return (
@@ -71,6 +90,24 @@ export default function Navbar ({ userId }: IProps): JSX.Element { > Docs +
+ + {aboutOpen && ( +
+ +
+ )} +
{userId === undefined ? ( <> @@ -96,6 +133,7 @@ export default function Navbar ({ userId }: IProps): JSX.Element { )}
+ setCommunityOpen(false)} /> ) } diff --git a/components/Sidebar/index.tsx b/components/Sidebar/index.tsx index 766d9d24..876b1204 100644 --- a/components/Sidebar/index.tsx +++ b/components/Sidebar/index.tsx @@ -18,6 +18,7 @@ import Docs from 'assets/docs.png' import Admin from 'assets/admin-icon.png' import Logout from 'assets/logout-icon.png' import { UserProfile } from '@prisma/client' +import CommunityDialog from 'components/CommunityDialog' const ThemeToggle = dynamic(async () => await import('./themetoggle'), { ssr: false }) @@ -74,6 +75,8 @@ interface IProps { const Sidebar: React.FC = ({ chart, setChart, loggedUser }: IProps) => { const [menu, setMenu] = useState(false) + const [aboutOpen, setAboutOpen] = useState(false) + const [communityOpen, setCommunityOpen] = useState(false) const useMediaQuery = (width: number): boolean => { const [targetReached, setTargetReached] = useState(false) const updateTarget = useCallback((e) => { @@ -139,6 +142,36 @@ const Sidebar: React.FC = ({ chart, setChart, loggedUser }: IProps) => { .map(item => )} +
  • + + {aboutOpen && ( + + )} +
  • @@ -162,6 +195,7 @@ const Sidebar: React.FC = ({ chart, setChart, loggedUser }: IProps) => { + setCommunityOpen(false)} /> } diff --git a/components/Sidebar/sidebar.module.css b/components/Sidebar/sidebar.module.css index c710134e..5bc57a2f 100644 --- a/components/Sidebar/sidebar.module.css +++ b/components/Sidebar/sidebar.module.css @@ -17,6 +17,40 @@ padding: 0; } +.about_group { + list-style: none; +} + +button.about_btn, +button.community_btn { + display: flex; + align-items: center; + width: 100%; + cursor: pointer; + font-weight: 500; + font-family: inherit; + font-size: inherit; + text-align: left; + padding: 8px 25px; + border: none; + border-radius: 10px; + background: transparent !important; + color: var(--primary-text-color); + box-shadow: none; +} + +button.community_btn { + padding-left: 40px; +} + +button.about_btn:enabled:hover, +button.community_btn:enabled:hover { + background: var(--primary-text-color) !important; + border-color: transparent !important; + color: var(--secondary-bg-color); + filter: none; +} + .section { padding: 0; margin: 0; @@ -144,6 +178,11 @@ body[data-theme='dark'] .socialctn .moon { } @media (max-width: 960px) { + button.about_btn, + button.community_btn { + border-radius: 0; + } + .topmenu { background-color: var(--secondary-bg-color); height: 50px; diff --git a/styles/landing.module.css b/styles/landing.module.css index f7a8a2dd..4710bcbc 100644 --- a/styles/landing.module.css +++ b/styles/landing.module.css @@ -131,6 +131,66 @@ body[data-theme="dark"] .navbar_ctn img { margin-right: 0px; } +.about_wrap { + position: relative; + margin-left: 30px; +} + +button.about_btn { + background: transparent !important; + border: none; + padding: 0; + color: var(--primary-text-color); + font-family: inherit; + font-size: inherit; + font-weight: 500; + cursor: pointer; + box-shadow: none; +} + +button.about_btn:enabled:hover, +button.about_btn:enabled:focus { + background: transparent !important; + border-color: transparent !important; + color: var(--accent-color); + filter: none; +} + +.about_dropdown { + position: absolute; + top: calc(100% + 14px); + left: 0; + min-width: 160px; + background: var(--secondary-bg-color); + border: 1px solid var(--border-color); + border-radius: 10px; + padding: 6px; + z-index: 5; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); +} + +.about_dropdown button { + display: block; + width: 100%; + text-align: left; + background: transparent !important; + border: none; + border-radius: 8px; + padding: 8px 12px; + color: var(--primary-text-color); + font-family: inherit; + font-size: 15px; + font-weight: 500; + cursor: pointer; + box-shadow: none; +} + +.about_dropdown button:enabled:hover { + background: transparent !important; + border-color: transparent !important; + color: var(--accent-color); +} + .menubtn_ctn_outer { display: none; } @@ -176,6 +236,36 @@ body[data-theme="dark"] .navbar_ctn img { order: 8; } + .about_wrap { + order: 0; + margin-left: 0; + width: 100%; + } + + button.about_btn { + font-size: 16px; + padding: 10px 0; + border-bottom: 1px solid var(--primary-text-color); + width: 100%; + text-align: left; + border-radius: 0; + } + + .about_dropdown { + position: static; + min-width: 0; + border: none; + box-shadow: none; + background: transparent; + padding: 0 0 0 12px; + } + + .about_dropdown button { + padding: 10px 0; + border-bottom: 1px solid var(--primary-text-color); + border-radius: 0; + } + .navbar_ctn img { width: 120px; }