diff options
| author | MaheshtheDev <[email protected]> | 2025-10-04 21:38:13 +0000 |
|---|---|---|
| committer | MaheshtheDev <[email protected]> | 2025-10-04 21:38:13 +0000 |
| commit | 583c2651b68ad29f4c335bd004fa0c7dfa8f25b3 (patch) | |
| tree | 0ad62a692edc4de562a38819ab874d8f7cc88009 /apps/web/components | |
| parent | fix: model names (diff) | |
| download | supermemory-583c2651b68ad29f4c335bd004fa0c7dfa8f25b3.tar.xz supermemory-583c2651b68ad29f4c335bd004fa0c7dfa8f25b3.zip | |
feat: url cards as content preview with rich details (#452)
Improved memory detail UI with better document icons and layout and Added dark mode support to the Chrome extension button
### What changed?
- Enhanced the WebsiteCard component with an `onOpenDetails` prop
- Improved the MemoryDetail component with:
- Better layout for document headers and source links
- Enhanced content scrolling with proper height constraints
- Improved spacing and padding in various sections
- Added favicon support to document icons, showing website favicons for webpage documents
- Fixed document type detection for webpages and URLs
- Added dark mode support to the Chrome extension button component with appropriate color classes
[Screen Recording 2025-10-03 at 11.34.01 PM.mov <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.dev/user-attachments/thumbnails/2f6ceef2-43a2-4e11-bafa-0f3ce614696b.mov" />](https://app.graphite.dev/user-attachments/video/2f6ceef2-43a2-4e11-bafa-0f3ce614696b.mov)
Diffstat (limited to 'apps/web/components')
| -rw-r--r-- | apps/web/components/chrome-extension-button.tsx | 28 | ||||
| -rw-r--r-- | apps/web/components/content-cards/website.tsx | 4 | ||||
| -rw-r--r-- | apps/web/components/header.tsx | 6 | ||||
| -rw-r--r-- | apps/web/components/masonry-memory-list.tsx | 1 | ||||
| -rw-r--r-- | apps/web/components/memories-utils/memory-detail.tsx | 52 | ||||
| -rw-r--r-- | apps/web/components/memory-list-view.tsx | 5 |
6 files changed, 50 insertions, 46 deletions
diff --git a/apps/web/components/chrome-extension-button.tsx b/apps/web/components/chrome-extension-button.tsx index 5fd58cac..2b2ca713 100644 --- a/apps/web/components/chrome-extension-button.tsx +++ b/apps/web/components/chrome-extension-button.tsx @@ -130,42 +130,42 @@ export function ChromeExtensionButton() { <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 className="w-10 h-10 bg-blue-50 dark:bg-blue-950 border border-blue-200 dark:border-blue-800 rounded-lg flex items-center justify-center flex-shrink-0"> + <TwitterIcon className="fill-blue-500 dark:fill-blue-400 text-blue-500 dark:text-blue-400" /> </div> <div> - <h3 className="font-semibold text-sm text-gray-800"> + <h3 className="font-semibold text-sm text-foreground"> Twitter Imports </h3> - <p className="text-xs text-gray-600"> + <p className="text-xs text-muted-foreground"> 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 className="w-10 h-10 bg-orange-50 dark:bg-orange-950 border border-orange-200 dark:border-orange-800 rounded-lg flex items-center justify-center flex-shrink-0"> + <Bookmark className="w-5 h-5 text-orange-600 dark:text-orange-400" /> </div> <div> - <h3 className="font-semibold text-sm text-gray-800"> + <h3 className="font-semibold text-sm text-foreground"> Save All Bookmarks </h3> - <p className="text-xs text-gray-600"> + <p className="text-xs text-muted-foreground"> 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 className="w-10 h-10 bg-green-50 dark:bg-green-950 border border-green-200 dark:border-green-800 rounded-lg flex items-center justify-center flex-shrink-0"> + <Zap className="w-5 h-5 text-green-600 dark:text-green-400" /> </div> <div> - <h3 className="font-semibold text-sm text-gray-800"> + <h3 className="font-semibold text-sm text-foreground"> Charge Empty Memory </h3> - <p className="text-xs text-gray-600"> + <p className="text-xs text-muted-foreground"> Automatically capture & organize your browsing history. </p> </div> @@ -175,7 +175,7 @@ export function ChromeExtensionButton() { <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" + className="w-full bg-background border border-primary text-foreground hover:bg-accent 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 @@ -189,7 +189,7 @@ export function ChromeExtensionButton() { </Button> </div> - <div className="px-6 pb-4 flex items-center justify-center gap-6 text-xs text-gray-500"> + <div className="px-6 pb-4 flex items-center justify-center gap-6 text-xs text-muted-foreground"> <div className="flex items-center gap-1"> <Users className="w-3 h-3" /> <span>4K+ users</span> diff --git a/apps/web/components/content-cards/website.tsx b/apps/web/components/content-cards/website.tsx index b3ee7df6..f0e614c9 100644 --- a/apps/web/components/content-cards/website.tsx +++ b/apps/web/components/content-cards/website.tsx @@ -25,6 +25,7 @@ interface WebsiteCardProps { description?: string className?: string onClick?: () => void + onOpenDetails?: () => void onDelete?: () => void showExternalLink?: boolean } @@ -36,6 +37,7 @@ export const WebsiteCard = ({ description, className, onClick, + onOpenDetails, onDelete, showExternalLink = true, }: WebsiteCardProps) => { @@ -44,6 +46,8 @@ export const WebsiteCard = ({ const handleCardClick = () => { if (onClick) { onClick() + } else if (onOpenDetails) { + onOpenDetails() } else { window.open(url, "_blank", "noopener,noreferrer") } diff --git a/apps/web/components/header.tsx b/apps/web/components/header.tsx index c055e94d..2ea075d1 100644 --- a/apps/web/components/header.tsx +++ b/apps/web/components/header.tsx @@ -142,7 +142,7 @@ export function Header({ onAddMemory }: { onAddMemory?: () => void }) { <MonitorIcon className={cn( theme === "system" - ? "text-primay-foreground" + ? "text-primary-foreground" : "text-muted-foreground", "h-3 w-3 group-hover:text-foreground", )} @@ -160,7 +160,7 @@ export function Header({ onAddMemory }: { onAddMemory?: () => void }) { <SunIcon className={cn( theme === "light" - ? "text-primay-foreground" + ? "text-primary-foreground" : "text-muted-foreground", "h-3 w-3 group-hover:text-foreground", )} @@ -178,7 +178,7 @@ export function Header({ onAddMemory }: { onAddMemory?: () => void }) { <MoonIcon className={cn( theme === "dark" - ? "text-primay-foreground" + ? "text-primary-foreground" : "text-muted-foreground", "h-3 w-3 group-hover:text-foreground", )} diff --git a/apps/web/components/masonry-memory-list.tsx b/apps/web/components/masonry-memory-list.tsx index 93326e49..0511a061 100644 --- a/apps/web/components/masonry-memory-list.tsx +++ b/apps/web/components/masonry-memory-list.tsx @@ -89,6 +89,7 @@ const DocumentCard = memo( url={document.url} title={document.title || "Untitled Document"} image={document.ogImage} + onOpenDetails={() => onOpenDetails(document)} onDelete={() => onDelete(document)} /> ) diff --git a/apps/web/components/memories-utils/memory-detail.tsx b/apps/web/components/memories-utils/memory-detail.tsx index 8f238731..378d3f79 100644 --- a/apps/web/components/memories-utils/memory-detail.tsx +++ b/apps/web/components/memories-utils/memory-detail.tsx @@ -28,6 +28,7 @@ import type { z } from "zod" import { formatDate, getSourceUrl } from "." import { Label1Regular } from "@ui/text/label/label-1-regular" import { HTMLContentRenderer } from "./html-content-renderer" +import { Button } from "@ui/components/button" type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema> type DocumentWithMemories = DocumentsResponse["documents"][0] @@ -141,11 +142,13 @@ export const MemoryDetail = memo( TitleComponent: typeof DialogTitle | typeof DrawerTitle }) => ( <div className="flex items-start justify-between gap-2"> - <div className="flex items-start gap-2 md:gap-3 flex-1 min-w-0"> + <div className="flex items-end gap-2 md:gap-3 flex-1 min-w-0"> <div className="p-1.5 md:p-2 rounded-lg bg-muted/10 flex-shrink-0"> {getDocumentIcon( document.type, "w-4 h-4 md:w-5 md:h-5 text-foreground", + document.source ?? undefined, + document.url ?? undefined, )} </div> <div className="flex-1 min-w-0"> @@ -156,25 +159,24 @@ export const MemoryDetail = memo( <span>{formatDocumentType(document.type)}</span> <span>•</span> <span>{formatDate(document.createdAt)}</span> - {document.url && ( - <> - <span>•</span> - <button - className="flex items-center gap-0.5 md:gap-1 transition-all hover:gap-1 md:hover:gap-2 text-primary hover:text-primary/80 whitespace-nowrap" - onClick={() => { - const sourceUrl = getSourceUrl(document) - window.open(sourceUrl ?? undefined, "_blank") - }} - type="button" - > - <span className="hidden sm:inline">View source</span> - <span className="sm:hidden">Source</span> - <ExternalLink className="w-2.5 h-2.5 md:w-3 md:h-3" /> - </button> - </> - )} </div> </div> + {document.url && ( + <div className="flex items-end"> + <Button + onClick={() => { + const sourceUrl = getSourceUrl(document) + window.open(sourceUrl ?? undefined, "_blank") + }} + variant="secondary" + size="sm" + > + <span className="hidden sm:inline">visit source</span> + <span className="sm:hidden">Source</span> + <ExternalLink className="w-2.5 h-2.5 md:w-3 md:h-3" /> + </Button> + </div> + )} </div> </div> ) @@ -227,10 +229,10 @@ export const MemoryDetail = memo( <div className="space-y-6"> {activeMemories.length > 0 && ( <div> - <div className="text-sm font-medium mb-2 flex items-start gap-2 py-2 text-muted-foreground"> + <div className="text-sm font-medium flex items-start gap-2 pb-2 text-muted-foreground"> Active Memories ({activeMemories.length}) </div> - <div className="space-y-3"> + <div className="space-y-3 max-h-[80vh] overflow-y-auto custom-scrollbar"> {activeMemories.map((memory) => ( <div key={memory.id}> <MemoryDetailItem memory={memory} /> @@ -281,7 +283,7 @@ export const MemoryDetail = memo( Content </h4> </div> - <div className="p-3 md:p-4"> + <div className="p-3 md:p-4 m-4"> <ContentDisplaySection /> </div> </div> @@ -324,8 +326,8 @@ export const MemoryDetail = memo( <div className="flex-1 flex flex-col lg:flex-row overflow-hidden"> <div className="flex-1 flex flex-col h-full justify-between min-w-0"> - <div className="p-2 px-3 md:px-4 overflow-y-auto custom-scrollbar transition-all duration-300"> - <h3 className="font-medium text-[10px] md:text-xs text-muted-foreground uppercase pb-1 px-1"> + <div className="p-2 px-3 md:pl-4 overflow-y-auto custom-scrollbar transition-all duration-300"> + <h3 className="font-medium text-[10px] md:text-sm text-muted-foreground pb-2 px-1"> Content </h3> <ContentDisplaySection /> @@ -370,9 +372,9 @@ export const MemoryDetail = memo( </div> </div> - <div className="w-full lg:w-96 flex flex-col border-t lg:border-t-0 lg:border-l border-border"> + <div className="w-full lg:w-96 flex flex-col border-t lg:border-t-0 border-border"> <div className="flex-1 flex flex-col"> - <div className="flex-1 memory-dialog-scroll overflow-y-auto p-3 md:p-4"> + <div className="flex-1 memory-dialog-scroll overflow-y-auto p-2 md:p-3"> <MemoryContent /> </div> </div> diff --git a/apps/web/components/memory-list-view.tsx b/apps/web/components/memory-list-view.tsx index c2b4b0c8..02667147 100644 --- a/apps/web/components/memory-list-view.tsx +++ b/apps/web/components/memory-list-view.tsx @@ -294,10 +294,7 @@ export const MemoryListView = ({ // Always render with consistent structure return ( <> - <div - className="h-full overflow-hidden relative pb-20" - ref={containerRef} - > + <div className="h-full overflow-hidden relative pb-20" ref={containerRef}> {error ? ( <div className="h-full flex items-center justify-center p-4"> <div className="rounded-xl overflow-hidden"> |