aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMaheshtheDev <[email protected]>2025-10-03 07:55:08 +0000
committerMaheshtheDev <[email protected]>2025-10-03 07:55:08 +0000
commit050b241fb6f0a5d3c9b0c9b0b77d52640c0091cf (patch)
tree5c678e1901f933d24d525463ccb0e5901e9763bb /apps
parentfix: billing metrics display for pro users (#450) (diff)
downloadsupermemory-050b241fb6f0a5d3c9b0c9b0b77d52640c0091cf.tar.xz
supermemory-050b241fb6f0a5d3c9b0c9b0b77d52640c0091cf.zip
ui: update the chrome extension visibilty (#448)10-01-ui_update_the_chrome_extension_visibilty
ui: update the chrome extension visibilty fix the ui for the chrome extension icon remove bun lock ![image.png](https://app.graphite.dev/user-attachments/assets/e5da1528-95dd-455a-bd35-6d93a3c369b9.png) ![image.png](https://app.graphite.dev/user-attachments/assets/ecc6ed96-6a87-4569-8220-adef56ab185e.png)
Diffstat (limited to 'apps')
-rw-r--r--apps/web/app/(navigation)/page.tsx2
-rw-r--r--apps/web/components/chrome-extension-button.tsx234
-rw-r--r--apps/web/components/header.tsx27
-rw-r--r--apps/web/public/icons/chrome-transparent.svg13
-rw-r--r--apps/web/public/images/extension-bg.pngbin0 -> 39989 bytes
-rw-r--r--apps/web/public/images/extension-logo.pngbin0 -> 33814 bytes
6 files changed, 275 insertions, 1 deletions
diff --git a/apps/web/app/(navigation)/page.tsx b/apps/web/app/(navigation)/page.tsx
index b8c81985..d2be1ad8 100644
--- a/apps/web/app/(navigation)/page.tsx
+++ b/apps/web/app/(navigation)/page.tsx
@@ -6,6 +6,7 @@ import { ChevronsDown, LoaderIcon } from "lucide-react"
import { useRouter } from "next/navigation"
import { useEffect } from "react"
import { InstallPrompt } from "@/components/install-prompt"
+import { ChromeExtensionButton } from "@/components/chrome-extension-button"
import { ChatInput } from "@/components/chat-input"
import { BackgroundPlus } from "@ui/components/grid-plus"
import { Memories } from "@/components/memories"
@@ -76,6 +77,7 @@ export default function Page() {
<Memories />
<InstallPrompt />
+ <ChromeExtensionButton />
</div>
)
}
diff --git a/apps/web/components/chrome-extension-button.tsx b/apps/web/components/chrome-extension-button.tsx
new file mode 100644
index 00000000..5fd58cac
--- /dev/null
+++ b/apps/web/components/chrome-extension-button.tsx
@@ -0,0 +1,234 @@
+"use client"
+
+import { Button } from "@ui/components/button"
+import {
+ Bookmark,
+ Zap,
+ CircleX,
+ Users,
+ Lock,
+ ChromeIcon,
+ TwitterIcon,
+} from "lucide-react"
+import { useEffect, useState } from "react"
+import { motion } from "framer-motion"
+import Image from "next/image"
+import { analytics } from "@/lib/analytics"
+
+export function ChromeExtensionButton() {
+ const [isExtensionInstalled, setIsExtensionInstalled] = useState(false)
+ const [isChecking, setIsChecking] = useState(true)
+ const [isDismissed, setIsDismissed] = useState(false)
+ const [isMinimized, setIsMinimized] = useState(false)
+
+ useEffect(() => {
+ const dismissed =
+ localStorage.getItem("chrome-extension-dismissed") === "true"
+ setIsDismissed(dismissed)
+
+ const checkExtension = () => {
+ const message = { action: "check-extension" }
+
+ const timeout = setTimeout(() => {
+ setIsExtensionInstalled(false)
+ setIsChecking(false)
+ // Auto-minimize after 3 seconds if extension is not installed and not dismissed
+ if (!dismissed) {
+ setTimeout(() => {
+ setIsMinimized(true)
+ }, 3000)
+ }
+ }, 1000)
+
+ const handleMessage = (event: MessageEvent) => {
+ if (event.data?.action === "extension-detected") {
+ clearTimeout(timeout)
+ setIsExtensionInstalled(true)
+ setIsChecking(false)
+ window.removeEventListener("message", handleMessage)
+ }
+ }
+
+ window.addEventListener("message", handleMessage)
+
+ window.postMessage(message, "*")
+
+ return () => {
+ clearTimeout(timeout)
+ window.removeEventListener("message", handleMessage)
+ }
+ }
+
+ if (!dismissed) {
+ checkExtension()
+ } else {
+ setIsChecking(false)
+ }
+ }, [])
+
+ const handleInstall = () => {
+ analytics.extensionInstallClicked()
+ window.open(
+ "https://chromewebstore.google.com/detail/supermemory/afpgkkipfdpeaflnpoaffkcankadgjfc",
+ "_blank",
+ "noopener,noreferrer",
+ )
+ }
+
+ const handleDismiss = () => {
+ localStorage.setItem("chrome-extension-dismissed", "true")
+ setIsDismissed(true)
+ }
+
+ // Don't show if extension is installed, checking, or dismissed
+ if (isExtensionInstalled || isChecking || isDismissed) {
+ return null
+ }
+
+ return (
+ <motion.div
+ className="fixed bottom-4 right-4 z-50"
+ initial={{ opacity: 0, y: 20, scale: 0.9 }}
+ animate={{ opacity: 1, y: 0, scale: 1 }}
+ transition={{ duration: 0.3, ease: "easeOut" }}
+ >
+ <div
+ className={`bg-background/95 backdrop-blur-md shadow-xl ${
+ isMinimized
+ ? "flex items-center gap-1 rounded-full"
+ : "max-w-md w-90 rounded-2xl"
+ }`}
+ >
+ {!isMinimized && (
+ <motion.div
+ initial={{ opacity: 0, y: 10 }}
+ animate={{ opacity: 1, y: 0 }}
+ exit={{ opacity: 0, y: -10 }}
+ transition={{ duration: 0.3, ease: [0.4, 0, 0.2, 1] }}
+ className="overflow-hidden"
+ >
+ <div className="p-4 text-white bg-cover bg-center">
+ <div
+ className="p-4 rounded-lg"
+ style={{
+ backgroundImage: "url('/images/extension-bg.png')",
+ backgroundSize: "cover",
+ backgroundPosition: "center",
+ backgroundRepeat: "no-repeat",
+ }}
+ >
+ <div className="relative">
+ <h1 className="text-2xl font-bold mb-1">
+ supermemory extension
+ </h1>
+ <p className="text-sm opacity-90">
+ your second brain for the web.
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <div className="px-6 py-2 pb-4 space-y-4">
+ <div className="flex items-start gap-3">
+ <div className="w-10 h-10 bg-blue-50 border border-blue-200 rounded-lg flex items-center justify-center flex-shrink-0">
+ <TwitterIcon className="fill-blue-500 text-blue-500" />
+ </div>
+ <div>
+ <h3 className="font-semibold text-sm text-gray-800">
+ Twitter Imports
+ </h3>
+ <p className="text-xs text-gray-600">
+ Import your twitter timeline & save tweets.
+ </p>
+ </div>
+ </div>
+
+ <div className="flex items-start gap-3">
+ <div className="w-10 h-10 bg-orange-50 border border-orange-200 rounded-lg flex items-center justify-center flex-shrink-0">
+ <Bookmark className="w-5 h-5 text-orange-600" />
+ </div>
+ <div>
+ <h3 className="font-semibold text-sm text-gray-800">
+ Save All Bookmarks
+ </h3>
+ <p className="text-xs text-gray-600">
+ Instantly save any webpage to your memory.
+ </p>
+ </div>
+ </div>
+
+ <div className="flex items-start gap-3">
+ <div className="w-10 h-10 bg-green-50 border border-green-200 rounded-lg flex items-center justify-center flex-shrink-0">
+ <Zap className="w-5 h-5 text-green-600" />
+ </div>
+ <div>
+ <h3 className="font-semibold text-sm text-gray-800">
+ Charge Empty Memory
+ </h3>
+ <p className="text-xs text-gray-600">
+ Automatically capture & organize your browsing history.
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <div className="px-6 pb-4">
+ <Button
+ onClick={handleInstall}
+ className="w-full bg-white border border-[#686CFD] text-gray-800 hover:bg-gray-50 font-semibold rounded-lg h-10 flex items-center justify-center gap-3"
+ >
+ <div className="w-6 h-6 bg-[#686CFD] rounded-full flex items-center justify-center">
+ <Image
+ src="/images/extension-logo.png"
+ alt="Extension Logo"
+ width={24}
+ height={24}
+ />
+ </div>
+ Add to Chrome - It's Free
+ </Button>
+ </div>
+
+ <div className="px-6 pb-4 flex items-center justify-center gap-6 text-xs text-gray-500">
+ <div className="flex items-center gap-1">
+ <Users className="w-3 h-3" />
+ <span>4K+ users</span>
+ </div>
+ <div className="flex items-center gap-1">
+ <Lock className="w-3 h-3" />
+ <span>Privacy first</span>
+ </div>
+ </div>
+ </motion.div>
+ )}
+
+ {isMinimized && (
+ <div className="relative flex items-center w-full group">
+ <Button
+ size={"lg"}
+ onClick={handleInstall}
+ className="text-xs rounded-full"
+ style={{
+ backgroundImage: "url('/images/extension-bg.png')",
+ backgroundSize: "cover",
+ backgroundPosition: "center",
+ backgroundRepeat: "no-repeat",
+ }}
+ >
+ <ChromeIcon className="h-3 w-3 mr-1" />
+ Get Extension
+ </Button>
+ <Button
+ variant="ghost"
+ size="sm"
+ onClick={handleDismiss}
+ className="absolute top-[-16px] right-[-12px] h-6 w-6 p-0 text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-75 transition-opacity duration-200"
+ >
+ <CircleX className="w-4 h-4" />
+ </Button>
+ </div>
+ )}
+ </div>
+ </motion.div>
+ )
+}
diff --git a/apps/web/components/header.tsx b/apps/web/components/header.tsx
index b51b4b84..c055e94d 100644
--- a/apps/web/components/header.tsx
+++ b/apps/web/components/header.tsx
@@ -1,7 +1,17 @@
import { Button } from "@ui/components/button"
import { Logo, LogoFull } from "@ui/assets/Logo"
import Link from "next/link"
-import { MoonIcon, Plus, SunIcon, MonitorIcon, Network } from "lucide-react"
+import {
+ MoonIcon,
+ Plus,
+ SunIcon,
+ MonitorIcon,
+ Network,
+ User,
+ CreditCard,
+ Chrome,
+ LogOut,
+} from "lucide-react"
import {
DropdownMenuContent,
DropdownMenuTrigger,
@@ -93,14 +103,28 @@ export function Header({ onAddMemory }: { onAddMemory?: () => void }) {
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => router.push("/settings")}>
+ <User className="h-4 w-4 mr-2" />
Profile
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => router.push("/settings/billing")}
>
+ <CreditCard className="h-4 w-4 mr-2" />
Billing
</DropdownMenuItem>
<DropdownMenuItem
+ onClick={() => {
+ window.open(
+ "https://chromewebstore.google.com/detail/supermemory/afpgkkipfdpeaflnpoaffkcankadgjfc",
+ "_blank",
+ "noopener,noreferrer",
+ )
+ }}
+ >
+ <Chrome className="h-4 w-4 mr-2" />
+ Chrome Extension
+ </DropdownMenuItem>
+ <DropdownMenuItem
className="flex items-center justify-between p-2 cursor-default hover:bg-transparent focus:bg-transparent data-[highlighted]:bg-transparent"
onSelect={(e) => e.preventDefault()}
>
@@ -164,6 +188,7 @@ export function Header({ onAddMemory }: { onAddMemory?: () => void }) {
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => handleSignOut()}>
+ <LogOut className="h-4 w-4 mr-2" />
Logout
</DropdownMenuItem>
</DropdownMenuContent>
diff --git a/apps/web/public/icons/chrome-transparent.svg b/apps/web/public/icons/chrome-transparent.svg
new file mode 100644
index 00000000..a4bb01b7
--- /dev/null
+++ b/apps/web/public/icons/chrome-transparent.svg
@@ -0,0 +1,13 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_5502_15741)">
+<path d="M13.44 17.3199C13.12 17.3999 12.64 17.5599 12.04 17.5599C10.96 17.5599 9.92002 17.2799 9.04 16.6799C8.15998 16.0799 7.48002 15.3199 6.99998 14.3599L1.87999 5.3999L1.51999 5.99989C0.519977 7.79992 0 9.7999 0 11.9999C0 14.9999 1.00002 17.6399 2.91999 19.8799C4.84001 22.0799 7.31999 23.4399 10.2 23.8799L10.48 23.9199L14.52 16.9999L13.44 17.3199ZM10.04 22.9999C7.47998 22.5599 5.27997 21.3199 3.51998 19.3199C1.71996 17.2399 0.800005 14.7999 0.800005 11.9999C0.800005 10.1999 1.16 8.51991 1.87999 7.0399L6.19998 14.7199C6.71995 15.7599 7.47998 16.6399 8.51998 17.3199C9.55998 17.9599 10.72 18.3199 11.96 18.3199C12.28 18.3199 12.56 18.2799 12.8 18.2399L10.04 22.9999Z" fill="white"/>
+<path d="M6.59935 10.52C6.87933 9.32003 7.55933 8.32001 8.59934 7.52001C9.55932 6.75999 10.6793 6.39999 11.9993 6.39999H22.6393L22.2793 5.8C21.2793 4.07999 19.8793 2.71998 17.9593 1.60001C16.1593 0.519977 14.1593 0 11.9993 0C10.1593 0 8.35934 0.399979 6.75933 1.19998C5.03932 2.03997 3.55931 3.24 2.51936 4.64L2.35938 4.84001L6.35935 11.4L6.59935 10.52ZM3.31936 4.91998C4.27935 3.67996 5.55935 2.67999 7.11937 1.91997C8.59938 1.15995 10.2394 0.799957 11.9994 0.799957C13.9994 0.799957 15.8793 1.31993 17.5193 2.31995C19.1193 3.23995 20.2793 4.31994 21.1994 5.63997H11.9593C10.4793 5.63997 9.19933 6.03995 8.07936 6.91997C7.15936 7.63996 6.47935 8.47995 6.07937 9.47996L3.31936 4.91998Z" fill="white"/>
+<path d="M23.1175 7.48023L22.9975 7.24023H15.0375L15.7175 7.92024C16.9175 9.12022 17.5575 10.5603 17.5575 12.0002C17.5575 13.1602 17.2375 14.2402 16.5575 15.2003L11.4375 24.0003H12.1175C15.3975 23.9603 18.1975 22.7602 20.5175 20.4402C22.8375 18.1202 23.9975 15.2803 23.9975 12.0002C23.9975 10.8002 23.8375 9.08024 23.1175 7.48023ZM19.9575 19.8802C17.9575 21.8802 15.5975 22.9603 12.8375 23.1602L17.1976 15.6402C17.9576 14.5202 18.3176 13.3202 18.3176 12.0002C18.3176 10.6002 17.8376 9.24022 16.8776 8.04024H22.4776C23.0776 9.44024 23.1976 10.9602 23.1976 12.0002C23.1975 15.0402 22.1175 17.6802 19.9575 19.8802Z" fill="white"/>
+<path d="M7.19531 11.9997C7.19531 14.5997 9.39531 16.7997 11.9953 16.7997C14.5953 16.7997 16.7953 14.5997 16.7953 11.9997C16.7953 9.39971 14.5953 7.19971 11.9953 7.19971C9.39531 7.19971 7.19531 9.39971 7.19531 11.9997ZM11.9953 7.99971C14.1553 7.99971 15.9953 9.83972 15.9953 11.9997C15.9953 14.1597 14.1553 15.9997 11.9953 15.9997C9.83532 15.9997 7.99532 14.1597 7.99532 11.9997C7.99532 9.83972 9.83532 7.99971 11.9953 7.99971Z" fill="white"/>
+</g>
+<defs>
+<clipPath id="clip0_5502_15741">
+<rect width="24" height="24" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/apps/web/public/images/extension-bg.png b/apps/web/public/images/extension-bg.png
new file mode 100644
index 00000000..c414d088
--- /dev/null
+++ b/apps/web/public/images/extension-bg.png
Binary files differ
diff --git a/apps/web/public/images/extension-logo.png b/apps/web/public/images/extension-logo.png
new file mode 100644
index 00000000..549d267d
--- /dev/null
+++ b/apps/web/public/images/extension-logo.png
Binary files differ