few more improvements

This commit is contained in:
Mahesh Sanikommmu 2025-12-13 16:43:40 -08:00
parent b880f7edf9
commit 5e4afbd317
24 changed files with 146 additions and 108 deletions

View file

@ -1,7 +1,7 @@
"use client"
import { Header } from "@/components/new/header"
import { ChatSidebar } from "@/components/chat"
import { ChatSidebar } from "@/components/new/chat"
import { AnimatePresence } from "motion/react"
import { MemoriesGrid } from "@/components/new/memories-grid"
import { AnimatedGradientBackground } from "@/components/new/animated-gradient-background"
@ -9,7 +9,7 @@ import { AnimatedGradientBackground } from "@/components/new/animated-gradient-b
export default function NewPage() {
return (
<div className="h-screen overflow-hidden bg-black">
<AnimatedGradientBackground topPosition="15%" />
<AnimatedGradientBackground topPosition="15%" animateFromBottom={false} />
<Header />
<main className="relative">
<div className="relative z-10">

View file

@ -190,7 +190,7 @@ export default function OnboardingPage() {
)}
{isSetupFlow && <SetupHeader />}
{isSetupFlow && <AnimatedGradientBackground />}
{isSetupFlow && <AnimatedGradientBackground animateFromBottom={false} />}
{isWelcomeFlow && currentStep === "input" && (
<AnimatedGradientBackground animateFromBottom={true} />

View file

@ -23,11 +23,11 @@ export function SetupHeader() {
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, ease: "easeOut" }}
>
<div className="flex items-center">
<div className="flex items-center z-10!">
<Logo className="h-7" />
{name && (
<div className="flex flex-col items-start justify-center ml-2">
<p className="text-[#8B8B8B] text-xs leading-tight">
<p className="text-[#8B8B8B] text-[11px] leading-tight">
{userName}
</p>
<p className="text-white font-bold text-xl leading-none -mt-1">
@ -37,7 +37,7 @@ export function SetupHeader() {
)}
</div>
{user && (
<Avatar className="border border-border h-8 w-8 md:h-10 md:w-10">
<Avatar className="border border-border h-8 w-8 md:h-10 md:w-10 z-10!">
<AvatarImage src={user?.image ?? ""} />
<AvatarFallback>{user?.name?.charAt(0)}</AvatarFallback>
</Avatar>

View file

@ -3,7 +3,7 @@
import { useState } from "react"
import { Button } from "@ui/components/button"
import { MCPDetailView } from "@/components/mcp-detail-view"
import { ChromeExtensionDetailView } from "@/components/chrome-extension-detail-view"
import { XBookmarksDetailView } from "@/components/x-bookmarks-detail-view"
import { useRouter } from "next/navigation"
import { cn } from "@lib/utils"
import { dmSansClassName } from "@/utils/fonts"
@ -70,8 +70,8 @@ export function IntegrationsStep() {
if (selectedCard === "Connect to AI") {
return <MCPDetailView onBack={() => setSelectedCard(null)} />
}
if (selectedCard === "Capture") {
return <ChromeExtensionDetailView onBack={() => setSelectedCard(null)} />
if (selectedCard === "Import") {
return <XBookmarksDetailView onBack={() => setSelectedCard(null)} />
}
return (
<div className="flex flex-col items-center justify-center h-full p-8">
@ -93,7 +93,9 @@ export function IntegrationsStep() {
<div className="grid grid-cols-2 gap-3 max-w-lg w-full mb-12">
{integrationCards.map((card) => {
const isClickable =
card.title === "Connect to AI" || card.title === "Capture"
card.title === "Connect to AI" ||
card.title === "Capture" ||
card.title === "Import"
if (isClickable) {
return (
@ -104,7 +106,16 @@ export function IntegrationsStep() {
"bg-[#080B0F] relative rounded-lg p-3 hover:border-[#3374FF] hover:border-[0.1px] transition-colors duration-300 border-[0.1px] border-[#0D121A] cursor-pointer text-left w-full hover:bg-[url('/onboarding/bg-gradient-1.png')] hover:bg-[length:175%_auto] hover:bg-[center_top_2rem] hover:bg-no-repeat",
"hover:border-b-0 border-b-0",
)}
onClick={() => setSelectedCard(card.title)}
onClick={() => {
if (card.title === "Capture") {
window.open(
"https://chromewebstore.google.com/detail/supermemory/afpgkkipfdpeaflnpoaffkcankadgjfc",
"_blank",
)
} else {
setSelectedCard(card.title)
}
}}
>
<div className="flex-1 mt-10">
<h3 className="text-white text-sm font-medium">
@ -127,7 +138,10 @@ export function IntegrationsStep() {
return (
<div
key={card.title}
className="bg-[#080B0F] relative rounded-lg p-3 hover:border-[#3374FF] hover:border-[0.1px] transition-colors duration-300 border-[0.1px] border-[#0D121A] hover:bg-[url('/onboarding/bg-gradient-1.png')] hover:bg-[length:175%_auto] hover:bg-[center_top_2rem] hover:bg-no-repeat"
className={cn(
"bg-[#080B0F] relative rounded-lg p-3 hover:border-[#3374FF] hover:border-[0.1px] transition-colors duration-300 border-[0.1px] border-[#0D121A] hover:bg-[url('/onboarding/bg-gradient-1.png')] hover:bg-[length:175%_auto] hover:bg-[center_top_2rem] hover:bg-no-repeat",
"hover:border-b-0 border-b-0",
)}
>
<div className="flex-1 mt-10">
<h3 className="text-white text-sm font-medium">{card.title}</h3>
@ -149,14 +163,14 @@ export function IntegrationsStep() {
<div className="flex justify-between w-full max-w-4xl">
<Button
variant="link"
className="text-white hover:text-gray-300"
className="text-white hover:text-gray-300 hover:no-underline cursor-pointer"
onClick={() => router.push("/onboarding?flow=setup&step=relatable")}
>
Back
</Button>
<Button
variant="link"
className="text-white hover:text-gray-300"
className="text-white hover:text-gray-300 hover:no-underline cursor-pointer"
onClick={handleContinue}
>
Continue

View file

@ -133,7 +133,7 @@ export function RelatableQuestion() {
<div key={selectedOptions.length === 0 ? "skip" : "continue"}>
<Button
className={cn(
"font-medium text-white hover:no-underline",
"font-medium text-white hover:no-underline cursor-pointer",
selectedOptions.length !== 0 ? "rounded-xl" : "",
)}
variant={selectedOptions.length !== 0 ? "onboarding" : "link"}

View file

@ -33,7 +33,7 @@ export function FeaturesStep() {
</div>
<div className="text-left">
<p className="text-white font-light">Remember every context</p>
<p className="text-[#8A8A8A]">
<p className="text-[#8A8A8A] text-[14px]">
I keep track of what you've saved and shared with your
supermemory.
</p>
@ -50,7 +50,7 @@ export function FeaturesStep() {
</div>
<div className="text-left">
<p className="text-white font-light">Find when you need it</p>
<p className="text-[#8A8A8A]">
<p className="text-[#8A8A8A] text-[14px]">
I surface the right memories inside <br /> your supermemory,
superfast.
</p>
@ -67,7 +67,7 @@ export function FeaturesStep() {
</div>
<div className="text-left">
<p className="text-white font-light">Grow with your supermemory</p>
<p className="text-[#8A8A8A]">
<p className="text-[#8A8A8A] text-[14px]">
I learn and personalize over time, so every interaction feels
natural.
</p>

View file

@ -5,6 +5,7 @@ interface GreetingStepProps {
}
export function GreetingStep({ name }: GreetingStepProps) {
const userName = name ? `${name.split(" ")[0]}` : ""
return (
<motion.div
className="text-center"
@ -15,7 +16,7 @@ export function GreetingStep({ name }: GreetingStepProps) {
layout
>
<h2 className="text-white text-[32px] font-medium mb-2">
Hi {name}, I'm Nova
Hi {userName}, I'm Nova
</h2>
</motion.div>
)

View file

@ -277,7 +277,7 @@ export function MemoriesStep({ onSubmit }: MemoriesStepProps) {
className="mt-[24px] pb-30"
>
<Button
className="rounded-xl px-6 py-3 border border-onboarding/20 max-w-48 text-white disabled:opacity-50 disabled:cursor-not-allowed h-[40px] cursor-pointer"
variant="onboarding"
disabled={isSubmitting}
style={{
background: "linear-gradient(180deg, #0D121A -26.14%, #000 100%)",

View file

@ -15,7 +15,7 @@ export function InitialHeader({
<Logo className="h-7" />
{showUserSupermemory && (
<div className="flex flex-col items-start justify-center ml-2">
<p className="text-[#8B8B8B] text-sm leading-tight">{userName}</p>
<p className="text-[#8B8B8B] text-[11px] leading-tight">{userName}</p>
<p className="text-white font-bold text-xl leading-none -mt-1">
supermemory
</p>

View file

@ -72,7 +72,7 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) {
<div className="mb-6">
<Button
variant="link"
className="text-white hover:text-gray-300 p-0"
className="text-white hover:text-gray-300 p-0 hover:no-underline cursor-pointer"
onClick={onBack}
>
Back
@ -91,7 +91,7 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) {
dmSansClassName(),
)}
>
<CircleCheckIcon className="size-4 text-green-500 flex-shrink-0 mt-0.5" />
<CircleCheckIcon className="size-4 text-green-500 shrink-0 mt-0.5" />
<p className="text-[#8B8B8B] text-sm">
MCP connects your AI apps to create and use memories directly
</p>
@ -128,7 +128,10 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) {
<div className="flex items-start space-x-4 z-20">
<div
className={cn(
"rounded-full w-8 h-8 flex items-center justify-center text-sm font-medium shrink-0 z-20 bg-[#161F2B] text-white",
"rounded-full w-8 h-8 flex items-center justify-center text-sm font-medium shrink-0 z-20 text-white",
activeStep === 1
? "border border-[#15233C] bg-[#08142D]"
: "bg-[#161F2B] ",
)}
>
<span
@ -199,14 +202,14 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) {
<SelectValue placeholder="Select a client" />
)}
</SelectTrigger>
<SelectContent className="bg-black border-none">
<SelectContent className="bg-black border-none pl-3 pr-2">
{Object.entries(clients)
.slice(0, 7)
.map(([key, clientName]) => (
<SelectItem
key={key}
value={key}
className="text-white hover:bg-[#080B0F]"
className="text-white hover:bg-[#080B0F] p-0"
>
<div className="flex items-center gap-2">
<Image
@ -244,13 +247,13 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) {
setSelectedClient(key as keyof typeof clients)
setActiveStep(2)
}}
className={`mcp-client-button-group px-3 py-1 rounded-full border transition-colors cursor-pointer duration-200 ${
className={`mcp-client-button-group py-[6px] pl-2 pr-3 rounded-full border transition-colors cursor-pointer duration-200 ${
selectedClient === key
? "border-blue-500 bg-blue-500/10"
: "border-[#242A33] bg-[#080B0F] hover:border-[#3273FC4D] hover:bg-[#08142D]"
}`}
>
<div className="flex items-center space-x-2">
<div className="flex items-center space-x-1">
<div className="w-5 h-5 flex items-center justify-center">
<Image
alt={clientName}
@ -306,8 +309,10 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) {
<div className="flex items-start space-x-4">
<div
className={cn(
"rounded-full w-8 h-8 flex items-center justify-center text-sm font-medium shrink-0 z-20 text-white bg-[#161F2B]",
"",
"rounded-full w-8 h-8 flex items-center justify-center text-sm font-medium shrink-0 z-20 text-white",
activeStep === 2
? "border border-[#15233C] bg-[#08142D]"
: "bg-[#161F2B]",
)}
>
<span
@ -463,9 +468,15 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) {
<div className="space-y-3">
<div className="relative">
<input
className="font-mono text-xs w-full pr-10 p-4 px-2 bg-[#0D121A] rounded-xl text-white pl-3"
className={cn(
"text-xs w-full pr-24 py-4 bg-[#0D121A] rounded-xl text-white pl-3",
dmMonoClassName(),
)}
style={{
border: "1px solid rgba(61, 67, 77, 0.10)",
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "nowrap",
}}
readOnly
value={generateInstallCommand()}
@ -473,7 +484,7 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) {
<button
type="button"
className={cn(
"absolute top-1.5 right-1 cursor-pointer p-1 flex items-center rounded-[10px] px-3 py-2 gap-2",
"absolute top-[5px] right-1 cursor-pointer p-1 flex items-center rounded-[10px] px-3 py-2 gap-2",
dmSansClassName(),
)}
style={{
@ -506,8 +517,10 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) {
<div className="flex items-start space-x-4">
<div
className={cn(
"rounded-full w-8 h-8 flex items-center justify-center text-sm font-medium shrink-0 z-20",
"bg-[#161F2B] text-white",
"rounded-full w-8 h-8 flex items-center justify-center text-sm font-medium shrink-0 z-20 text-white",
activeStep === 3
? "border border-[#15233C] bg-[#08142D]"
: "bg-[#161F2B] ",
)}
>
<span

View file

@ -19,18 +19,55 @@ import ChatModelSelector from "./model-selector"
import { GradientLogo, LogoBgGradient } from "@ui/assets/Logo"
import { useProject, usePersistentChat } from "@/stores"
import type { ModelId } from "@/lib/models"
import { SuperLoader } from "../superloader"
import { SuperLoader } from "../../superloader"
import { UserMessage } from "./message/user-message"
import { AgentMessage } from "./message/agent-message"
import { ChainOfThought } from "./input/chain-of-thought"
function ChatEmptyStatePlaceholder() {
const suggestions = [
"Show me all content related to Supermemory.",
"Summarize the key ideas from My Gita.",
"Which memories connect design and AI?",
"What are the main themes across my memories?",
]
return (
<div className="flex flex-col items-center justify-center h-full">
<div className="relative w-32 h-32">
<GradientLogo className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-16 h-16" />
<LogoBgGradient className="w-full h-full" />
</div>
<div className="gap-3 flex flex-col items-center justify-center">
<p>Ask me anything about your memories...</p>
<div
className={cn(
dmSansClassName(),
"flex flex-col gap-2 justify-center items-center",
)}
>
{suggestions.map((suggestion) => (
<Button
key={suggestion}
variant="default"
className="rounded-full text-base gap-1 h-10! border-[#2261CA33] bg-[#041127] border w-fit py-[4px] pl-[8px] pr-[12px]"
>
<SearchIcon className="size-4 text-[#267BF1]" />
<span className="text-[#267BF1] text-[12px]">{suggestion}</span>
</Button>
))}
</div>
</div>
</div>
)
}
export function ChatSidebar() {
const [input, setInput] = useState("")
const [isChatOpen, setIsChatOpen] = useState(true)
const [selectedModel, setSelectedModel] = useState<ModelId>("gemini-2.5-pro")
const [copiedMessageId, setCopiedMessageId] = useState<string | null>(null)
const [hoveredMessageId, setHoveredMessageId] = useState<string | null>(null)
const [chainOfThought, setChainOfThought] = useState<any[] | null>(null)
const [messageFeedback, setMessageFeedback] = useState<
Record<string, "like" | "dislike" | null>
>({})
@ -416,41 +453,3 @@ export function ChatSidebar() {
</AnimatePresence>
)
}
function ChatEmptyStatePlaceholder() {
const suggestions = [
"Show me all content related to Supermemory.",
"Summarize the key ideas from My Gita.",
"Which memories connect design and AI?",
"What are the main themes across my memories?",
]
return (
<div className="flex flex-col items-center justify-center h-full">
<div className="relative w-32 h-32">
<GradientLogo className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-16 h-16" />
<LogoBgGradient className="w-full h-full" />
</div>
<div className="gap-3 flex flex-col items-center justify-center">
<p>Ask me anything about your memories...</p>
<div
className={cn(
dmSansClassName(),
"flex flex-col gap-2 justify-center items-center",
)}
>
{suggestions.map((suggestion) => (
<Button
key={suggestion}
variant="default"
className="rounded-full text-base gap-1 h-10! border-[#2261CA33] bg-[#041127] border w-fit py-[4px] pl-[8px] pr-[12px]"
>
<SearchIcon className="size-4 text-[#267BF1]" />
<span className="text-[#267BF1] text-[12px]">{suggestion}</span>
</Button>
))}
</div>
</div>
</div>
)
}

View file

@ -36,7 +36,7 @@ export default function ChatModelSelector({
<Button
variant="headers"
className={cn(
"rounded-full text-base gap-1 !h-10 border-[#73737333] bg-[#0D121A]",
"rounded-full text-base gap-1 h-10! border-[#73737333] bg-[#0D121A]",
dmSansClassName(),
)}
style={{

View file

@ -67,12 +67,14 @@ export function Header() {
const userName = name ? `${name.split(" ")[0]}'s` : "My"
return (
<div className="flex p-4 justify-between items-center">
<div className="flex items-center justify-center gap-4">
<div className="flex items-center justify-center gap-4 z-10!">
<div className="flex items-center">
<Logo className="h-7" />
{name && (
<div className="flex flex-col items-start justify-center ml-2">
<p className="text-[#8B8B8B] text-sm leading-tight">{userName}</p>
<p className="text-[#8B8B8B] text-[11px] leading-tight">
{userName}
</p>
<p className="text-white font-bold text-xl leading-none -mt-1">
supermemory
</p>
@ -123,11 +125,11 @@ export function Header() {
</div>
</div>
<Tabs defaultValue="grid">
<TabsList className="rounded-full border border-[#161F2C] h-11!">
<TabsList className="rounded-full border border-[#161F2C] h-11! z-10!">
<TabsTrigger
value="grid"
className={cn(
"rounded-full data-[state=active]:!bg-[#00173C] dark:data-[state=active]:!border-[#2261CA33] px-4 py-4",
"rounded-full data-[state=active]:bg-[#00173C]! dark:data-[state=active]:border-[#2261CA33]! px-4 py-4",
dmSansClassName(),
)}
>
@ -137,7 +139,7 @@ export function Header() {
<TabsTrigger
value="graph"
className={cn(
"rounded-full dark:data-[state=active]:!bg-[#00173C] dark:data-[state=active]:!border-[#2261CA33] px-4 py-4",
"rounded-full dark:data-[state=active]:bg-[#00173C]! dark:data-[state=active]:border-[#2261CA33]! px-4 py-4",
dmSansClassName(),
)}
>
@ -146,7 +148,7 @@ export function Header() {
</TabsTrigger>
</TabsList>
</Tabs>
<div className="flex items-center gap-2">
<div className="flex items-center gap-2 z-10!">
<Button
variant="headers"
className="rounded-full text-base gap-2 !h-10"

View file

@ -266,24 +266,33 @@ const DocumentCard = memo(
<DocumentUrlDisplay url={document.url} />
</div>
)}
<div className="flex items-center justify-between px-3">
<p
className={cn(
dmSansClassName(),
"text-[10px] text-[#369BFD] line-clamp-1 font-semibold flex items-center gap-1",
)}
style={{
background:
"linear-gradient(94deg, #369BFD 4.8%, #36FDFD 77.04%, #36FDB5 143.99%)",
backgroundClip: "text",
WebkitBackgroundClip: "text",
WebkitTextFillColor: "transparent",
}}
>
<SyncLogoIcon className="w-[12.33px] h-[10px]" />
{document.memoryEntries.length}{" "}
{document.memoryEntries.length === 1 ? "memory" : "memories"}
</p>
<div
className={cn(
"flex items-center px-3",
document.memoryEntries.length > 0
? "justify-between"
: "justify-end",
)}
>
{document.memoryEntries.length > 0 && (
<p
className={cn(
dmSansClassName(),
"text-[10px] text-[#369BFD] line-clamp-1 font-semibold flex items-center gap-1",
)}
style={{
background:
"linear-gradient(94deg, #369BFD 4.8%, #36FDFD 77.04%, #36FDB5 143.99%)",
backgroundClip: "text",
WebkitBackgroundClip: "text",
WebkitTextFillColor: "transparent",
}}
>
<SyncLogoIcon className="w-[12.33px] h-[10px]" />
{document.memoryEntries.length}{" "}
{document.memoryEntries.length === 1 ? "memory" : "memories"}
</p>
)}
<p
className={cn(
dmSansClassName(),

View file

@ -5,7 +5,7 @@ import { cn } from "@lib/utils"
import { dmSansClassName } from "@/utils/fonts"
import Image from "next/image"
interface ChromeExtensionDetailViewProps {
interface XBookmarksDetailViewProps {
onBack: () => void
}
@ -27,9 +27,9 @@ const steps = [
},
]
export function ChromeExtensionDetailView({
export function XBookmarksDetailView({
onBack,
}: ChromeExtensionDetailViewProps) {
}: XBookmarksDetailViewProps) {
const handleInstall = () => {
window.open(
"https://chromewebstore.google.com/detail/supermemory/afpgkkipfdpeaflnangednailhoegogi",
@ -42,7 +42,7 @@ export function ChromeExtensionDetailView({
<div className="mb-6">
<Button
variant="link"
className="text-white hover:text-gray-300 p-0"
className="text-white hover:text-gray-300 p-0 hover:no-underline cursor-pointer"
onClick={onBack}
>
Back
@ -72,7 +72,7 @@ export function ChromeExtensionDetailView({
key={step.number}
className="flex flex-col items-center text-center bg-[#080B0F] p-3 rounded-[10px]"
>
<div className="rounded-2xl p-6 mb-4 w-full aspect-[4/4] flex items-center justify-center relative overflow-hidden">
<div className="rounded-2xl p-6 mb-3 w-full aspect-4/4 flex items-center justify-center relative overflow-hidden">
<Image
src={step.image}
alt={`Step ${step.number}`}
@ -83,7 +83,7 @@ export function ChromeExtensionDetailView({
</div>
<div className="flex flex-col items-start justify-start">
<div className="mb-2">
<span className="text-white font-medium">
<span className="text-white text-sm font-medium">
Step {step.number}
</span>
</div>
@ -102,7 +102,7 @@ export function ChromeExtensionDetailView({
</div>
<Button
className="rounded-xl px-6 py-3 text-white h-[44px] cursor-pointer mx-auto bg-black"
className="rounded-xl px-4 py-2 text-white h-10 cursor-pointer mx-auto bg-black"
onClick={handleInstall}
>
Install Chrome Extension

View file

@ -90,7 +90,7 @@
--shadow-offset-x: 0;
--shadow-offset-y: 1px;
--letter-spacing: -0.01em;
--spacing: 0.24rem;
--spacing: 0.25rem;
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.02);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.02);
--shadow-sm:
@ -151,7 +151,7 @@
--shadow-offset-x: 0;
--shadow-offset-y: 1px;
--letter-spacing: -0.01em;
--spacing: 0.24rem;
--spacing: 0.25rem;
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.02);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.02);
--shadow-sm: