From f091ea57f2ce87e27ff81acb54411445cca1b994 Mon Sep 17 00:00:00 2001 From: AnitusA Date: Wed, 17 Jun 2026 02:15:43 +0530 Subject: [PATCH 1/4] feat: add ShareButton component and sonner(snackbar for notify users) --- www/app/layout.tsx | 2 + www/components/ProfileSection.tsx | 2 + www/components/ShareButton.tsx | 69 +++++++++++++++++++++++++++++++ www/package.json | 1 + www/pnpm-lock.yaml | 14 +++++++ 5 files changed, 88 insertions(+) create mode 100644 www/components/ShareButton.tsx diff --git a/www/app/layout.tsx b/www/app/layout.tsx index e60f87e0..c5b01b2b 100644 --- a/www/app/layout.tsx +++ b/www/app/layout.tsx @@ -4,6 +4,7 @@ import "./globals.css"; import { QueryClientProvider } from "@/providers/CustomQueryClientProvider"; import Script from "next/script"; import { Banner } from "@/components/banner"; +import { Toaster } from "sonner"; const outfit = Outfit({ subsets: ["latin"], @@ -72,6 +73,7 @@ export default function RootLayout({ className={`${outfit.variable} ${spaceGrotesk.variable} font-outfit`} > + {children} diff --git a/www/components/ProfileSection.tsx b/www/components/ProfileSection.tsx index 50c6d797..8cd71d3d 100644 --- a/www/components/ProfileSection.tsx +++ b/www/components/ProfileSection.tsx @@ -3,6 +3,7 @@ import { Github, Globe, Linkedin, Twitter, User, BookOpen, Instagram } from "luc import { ProfileSkeleton } from "@/components/skeletons/profile-skeleton"; import { addUserToSupabase, getUserProfile } from "@/lib/api"; import ClientResumeButton from "@/components/ClientResumeButton"; +import ShareButton from "@/components/ShareButton"; import { Tooltip, TooltipContent, @@ -173,6 +174,7 @@ export async function ProfileSection({ ); })} + diff --git a/www/components/ShareButton.tsx b/www/components/ShareButton.tsx new file mode 100644 index 00000000..26c76351 --- /dev/null +++ b/www/components/ShareButton.tsx @@ -0,0 +1,69 @@ +"use client"; + +import { useState } from "react"; +import { Share2, Check } from "lucide-react"; +import { toast } from "sonner"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; + +export default function ShareButton({ username }: { username: string }) { + const [copied, setCopied] = useState(false); + + const handleShare = async () => { + const shareData = { + title: `${username}'s Portfolio`, + text: `Check out ${username}'s professional developer portfolio on devb.io!`, + url: window.location.href, + }; + + if (navigator.share && navigator.canShare(shareData)) { + try { + await navigator.share(shareData); + } catch (err) { + console.error("Error sharing:", err); + } + } else { + // Fallback: Copy to clipboard + try { + await navigator.clipboard.writeText(window.location.href); + setCopied(true); + toast.success("Link copied to clipboard!", { + style: { + backgroundColor: "#B9FF66", + color: "black", + border: "1px solid black", + fontWeight: "bold", + }, + }); + setTimeout(() => setCopied(false), 2000); + } catch (err) { + console.error("Failed to copy:", err); + } + } + }; + + return ( + + + + + + {copied ? "Link Copied!" : "Share Portfolio"} + + + ); +} diff --git a/www/package.json b/www/package.json index 8edbdb1b..2d23f76a 100644 --- a/www/package.json +++ b/www/package.json @@ -29,6 +29,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "react-intersection-observer": "^9.15.1", + "sonner": "^2.0.7", "tailwind-merge": "^3.0.2", "tailwindcss-animate": "^1.0.7", "xml2js": "^0.6.2", diff --git a/www/pnpm-lock.yaml b/www/pnpm-lock.yaml index 9d2e3975..e8803d3b 100644 --- a/www/pnpm-lock.yaml +++ b/www/pnpm-lock.yaml @@ -68,6 +68,9 @@ importers: react-intersection-observer: specifier: ^9.15.1 version: 9.15.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + sonner: #for snackbar + specifier: ^2.0.7 + version: 2.0.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0) tailwind-merge: specifier: ^3.0.2 version: 3.0.2 @@ -2172,6 +2175,12 @@ packages: simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + sonner@2.0.7: + resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -4695,6 +4704,11 @@ snapshots: dependencies: is-arrayish: 0.3.2 + sonner@2.0.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + source-map-js@1.2.1: {} stable-hash@0.0.4: {} From 6a5a4fa5ffcc42fe2c463625fce44f9c3a4998f4 Mon Sep 17 00:00:00 2001 From: Anitus A Date: Wed, 17 Jun 2026 02:32:07 +0530 Subject: [PATCH 2/4] Update www/components/ShareButton.tsx Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- www/components/ShareButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/components/ShareButton.tsx b/www/components/ShareButton.tsx index 26c76351..47b14667 100644 --- a/www/components/ShareButton.tsx +++ b/www/components/ShareButton.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import { Share2, Check } from "lucide-react"; import { toast } from "sonner"; import { From 0c5fec80c2f2b3e69d8a14def09687f01bdf1224 Mon Sep 17 00:00:00 2001 From: Anitus A Date: Wed, 17 Jun 2026 02:32:59 +0530 Subject: [PATCH 3/4] Update www/components/ShareButton.tsx Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- www/components/ShareButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/components/ShareButton.tsx b/www/components/ShareButton.tsx index 47b14667..c9ab935c 100644 --- a/www/components/ShareButton.tsx +++ b/www/components/ShareButton.tsx @@ -19,7 +19,7 @@ export default function ShareButton({ username }: { username: string }) { url: window.location.href, }; - if (navigator.share && navigator.canShare(shareData)) { + if (navigator.share) { try { await navigator.share(shareData); } catch (err) { From 3ff85c2d97c6e8645ac1e17809f0ed5d0048a8b5 Mon Sep 17 00:00:00 2001 From: Anitus A Date: Wed, 17 Jun 2026 02:34:19 +0530 Subject: [PATCH 4/4] Update www/components/ShareButton.tsx Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- www/components/ShareButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/components/ShareButton.tsx b/www/components/ShareButton.tsx index c9ab935c..38089bd0 100644 --- a/www/components/ShareButton.tsx +++ b/www/components/ShareButton.tsx @@ -50,7 +50,7 @@ export default function ShareButton({ username }: { username: string }) {