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()}
+ >
+
+
+ PayButton is a community-driven open-source project. Join the
+ conversation, follow updates, and contribute.
+
+
+
+
+
+ )
+}
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 =>