few more updates

This commit is contained in:
Mahesh Sanikommmu 2025-12-11 13:35:40 -08:00
parent 238685a70e
commit b880f7edf9
19 changed files with 311 additions and 176 deletions

View file

@ -39,8 +39,8 @@ export default function RootLayout({
>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
defaultTheme="dark"
enableSystem={false}
disableTransitionOnChange
>
<AutumnProvider

View file

@ -4,13 +4,13 @@ import { Header } from "@/components/new/header"
import { ChatSidebar } from "@/components/chat"
import { AnimatePresence } from "motion/react"
import { MemoriesGrid } from "@/components/new/memories-grid"
import { AnimatedGradientBackground } from "@/app/onboarding/setup/page"
import { AnimatedGradientBackground } from "@/components/new/animated-gradient-background"
export default function NewPage() {
return (
<div className="min-h-screen bg-black">
<div className="h-screen overflow-hidden bg-black">
<AnimatedGradientBackground topPosition="15%" />
<Header />
<AnimatedGradientBackground />
<main className="relative">
<div className="relative z-10">
<div className="flex flex-row h-[calc(100vh-90px)] relative">

View file

@ -20,7 +20,7 @@ import { SetupHeader } from "./setup/header"
import { ChatSidebar } from "./setup/chat-sidebar"
import { Logo } from "@ui/assets/Logo"
import NovaOrb from "@/components/nova/nova-orb"
import { AnimatedGradientBackground } from "./setup/page"
import { AnimatedGradientBackground } from "@/components/new/animated-gradient-background"
function UserSupermemory({ name }: { name: string }) {
return (
@ -33,7 +33,9 @@ function UserSupermemory({ name }: { name: string }) {
>
<Logo className="h-14 text-white" />
<div className="flex flex-col items-start justify-center ml-4">
<p className="text-white text-xs font-medium leading-none">{name}'s</p>
<p className="text-white text-xs font-medium leading-none">
{name.split(" ")[0]}'s
</p>
<p className="text-white font-bold text-4xl leading-none -mt-2">
supermemory
</p>
@ -57,6 +59,7 @@ export default function OnboardingPage() {
description: string
otherLinks: string[]
} | null>(null)
const [showWelcomeContent, setShowWelcomeContent] = useState(false)
const currentFlow = flow || "welcome"
const currentStep = step || "input"
@ -68,6 +71,16 @@ export default function OnboardingPage() {
}
}, [user?.name])
useEffect(() => {
if (currentFlow === "welcome" && currentStep === "input") {
setShowWelcomeContent(false)
const timer = setTimeout(() => {
setShowWelcomeContent(true)
}, 1250)
return () => clearTimeout(timer)
}
}, [currentFlow, currentStep])
useEffect(() => {
if (currentFlow !== "welcome") return
@ -179,10 +192,14 @@ export default function OnboardingPage() {
{isSetupFlow && <AnimatedGradientBackground />}
{isWelcomeFlow && (
<div className="flex flex-col items-center justify-start h-[calc(100vh-86px)] overflow-y-auto relative">
{isWelcomeFlow && currentStep === "input" && (
<AnimatedGradientBackground animateFromBottom={true} />
)}
{isWelcomeFlow && showWelcomeContent && (
<div className="fixed inset-0 flex flex-col items-center justify-center overflow-y-auto">
<motion.div
className="fixed inset-0 bg-[url('/bg-rectangle.png')] bg-cover bg-center bg-no-repeat pointer-events-none"
className="absolute inset-0 bg-[url('/bg-rectangle.png')] bg-cover bg-center bg-no-repeat pointer-events-none"
transition={{ duration: 0.75, ease: "easeOut", bounce: 0 }}
style={{
mixBlendMode: "soft-light",
@ -191,8 +208,7 @@ export default function OnboardingPage() {
/>
<motion.div
className={cn(
"relative z-10 flex flex-col items-center justify-center",
minimizeNovaOrb ? "mt-0" : "mt-16",
"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-10 flex flex-col items-center justify-center",
)}
animate={{
gap: minimizeNovaOrb ? 0 : 16,
@ -201,12 +217,9 @@ export default function OnboardingPage() {
duration: 0.6,
ease: "easeOut",
}}
layout
>
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{
opacity: 1,
scale:
currentStep === "features"
? 0.7
@ -220,7 +233,6 @@ export default function OnboardingPage() {
ease: "easeOut",
delay: 0.2,
}}
layout
className="relative"
>
<NovaOrb size={novaSize} />

View file

@ -14,6 +14,8 @@ export function SetupHeader() {
setName(storedName)
}, [])
const userName = name ? `${name.split(" ")[0]}'s` : "My"
return (
<motion.div
className="flex p-6 justify-between items-center"
@ -25,7 +27,9 @@ export function SetupHeader() {
<Logo className="h-7" />
{name && (
<div className="flex flex-col items-start justify-center ml-2">
<p className="text-[#8B8B8B] text-xs leading-tight">{name}'s</p>
<p className="text-[#8B8B8B] text-xs leading-tight">
{userName}
</p>
<p className="text-white font-bold text-xl leading-none -mt-1">
supermemory
</p>

View file

@ -1,50 +0,0 @@
import { motion } from "motion/react"
export function AnimatedGradientBackground() {
return (
<div className="fixed inset-0 z-0 overflow-hidden">
<motion.div
className="absolute top-[40%] left-0 right-0 bottom-0 bg-[url('/onboarding/bg-gradient-0.png')] bg-[length:150%_auto] bg-top bg-no-repeat"
initial={{ y: "100%" }}
animate={{
y: 0,
opacity: [1, 0, 1],
}}
transition={{
y: { duration: 0.75, ease: "easeOut" },
opacity: {
duration: 8,
repeat: Number.POSITIVE_INFINITY,
ease: "easeInOut",
},
}}
/>
<motion.div
className="absolute top-[40%] left-0 right-0 bottom-0 bg-[url('/onboarding/bg-gradient-1.png')] bg-[length:150%_auto] bg-top bg-no-repeat"
initial={{ y: "100%" }}
animate={{
y: 0,
opacity: [0, 1, 0],
}}
transition={{
y: { duration: 0.75, ease: "easeOut" },
opacity: {
duration: 8,
repeat: Number.POSITIVE_INFINITY,
ease: "easeInOut",
},
}}
/>
<motion.div
className="absolute top-20 left-0 right-0 bottom-0 bg-[url('/bg-rectangle.png')] bg-cover bg-center bg-no-repeat"
initial={{ y: "100%" }}
animate={{ y: 0 }}
transition={{ duration: 0.75, ease: "easeOut", bounce: 0 }}
style={{
mixBlendMode: "soft-light",
opacity: 0.6,
}}
/>
</div>
)
}

View file

@ -1,7 +1,7 @@
"use client"
import { useState } from "react"
import { motion } from "motion/react"
import { motion, AnimatePresence } from "motion/react"
import { Button } from "@ui/components/button"
import { useRouter } from "next/navigation"
import { cn } from "@lib/utils"
@ -62,48 +62,71 @@ export function RelatableQuestion() {
)}
>
{relatableOptions.map((option, index) => (
<button
<div
key={option.text}
className={`
group relative rounded-lg p-2 cursor-pointer transition-all duration-300 hover:border-[#4C608B66] border border-[#0D121A] max-w-[140px] min-h-[159px]
${
className={cn(
"rounded-lg max-w-[140px] min-h-[159px] transition-all duration-300",
selectedOptions.includes(index)
? "border-[#3374FF] border bg-[url('/onboarding/bg-gradient-1.png')] bg-size-[350%_auto] bg-top bg-no-repeat"
: "bg-[#080B0F] hover:bg-no-repeat"
}
? "p-px bg-linear-to-b from-[#3374FF] to-[#1A63FF00]"
: "p-0 border border-[#0D121A] hover:border-[#4C608B66]",
)}
>
<button
className={`
group relative w-full h-full rounded-lg p-2 cursor-pointer transition-all duration-300 overflow-hidden
bg-[#080B0F] hover:bg-no-repeat
`}
onClick={() => {
setSelectedOptions((prev) =>
prev.includes(index)
? prev.filter((i) => i !== index)
: [...prev, index],
)
}}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault()
onClick={() => {
setSelectedOptions((prev) =>
prev.includes(index)
? prev.filter((i) => i !== index)
: [...prev, index],
)
}
}}
type="button"
>
<div className="flex flex-col items-start justify-between h-full">
<span className="text-2xl">{option.emoji}</span>
<p
className={`text-white text-sm leading-[135%] align-bottom text-left transition-opacity duration-300 ${
selectedOptions.includes(index)
? "opacity-100"
: "opacity-50 group-hover:opacity-100"
}`}
>
{option.text}
</p>
</div>
</button>
}}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault()
setSelectedOptions((prev) =>
prev.includes(index)
? prev.filter((i) => i !== index)
: [...prev, index],
)
}
}}
type="button"
>
<AnimatePresence>
{selectedOptions.includes(index) && (
<motion.div
className="absolute inset-0 bg-[url('/onboarding/bg-gradient-1.png')] bg-size-[550%_auto] bg-top bg-no-repeat"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
</AnimatePresence>
<div className="relative flex flex-col items-start justify-between h-full">
<span
className={`text-2xl ${
selectedOptions.includes(index)
? "opacity-100"
: "opacity-70 group-hover:opacity-100"
}`}
>
{option.emoji}
</span>
<p
className={`text-white text-sm leading-[135%] align-bottom text-left transition-opacity duration-300 ${
selectedOptions.includes(index)
? "opacity-100"
: "opacity-50 group-hover:opacity-100"
}`}
>
{option.text}
</p>
</div>
</button>
</div>
))}
</div>
<div className="flex gap-4 my-8">

View file

@ -114,7 +114,7 @@ export function MemoriesStep({ onSubmit }: MemoriesStepProps) {
Let's add your memories
</h2>
<div className="space-y-4 max-w-[329px] mx-auto overflow-visible">
<div className="space-y-4 max-w-[329px] mx-auto overflow-visible gap-4">
<div className="text-left gap-[6px] flex flex-col" id="x-twitter-field">
<label
htmlFor="twitter-handle"
@ -143,11 +143,14 @@ export function MemoriesStep({ onSubmit }: MemoriesStepProps) {
/>
{errors.twitter && (
<div className="absolute left-full ml-3">
<div className="relative shrink-0 px-3 py-2 bg-red-500/20 rounded-xl">
<div className="absolute left-0 top-1/2 -translate-x-full -translate-y-1/2 w-0 h-0 border-t-[6px] border-b-[6px] border-r-8 border-t-transparent border-b-transparent border-r-red-500/20" />
<p className="text-red-500 text-xs whitespace-nowrap">
{errors.twitter}
</p>
<div
className={cn(
"relative shrink-0 px-3 py-2 bg-[#290F0A] text-[#C73B1B] rounded-xl",
dmSansClassName(),
)}
>
<div className="absolute left-0.5 top-1/2 -translate-x-full -translate-y-1/2 w-0 h-0 border-t-[6px] border-b-[6px] border-r-8 border-t-transparent border-b-transparent border-[#290F0A]" />
<p className="text-xs whitespace-nowrap">{errors.twitter}</p>
</div>
</div>
)}
@ -184,12 +187,12 @@ export function MemoriesStep({ onSubmit }: MemoriesStepProps) {
<div className="absolute left-full ml-3">
<div
className={cn(
"relative shrink-0 px-3 py-2 bg-red-500/20 rounded-xl",
"relative shrink-0 px-3 py-2 bg-[#290F0A] text-[#C73B1B] rounded-xl",
dmSansClassName(),
)}
>
<div className="absolute left-0 top-1/2 -translate-x-full -translate-y-1/2 w-0 h-0 border-t-[6px] border-b-[6px] border-r-8 border-t-transparent border-b-transparent border-r-red-500/20" />
<p className="text-red-500 text-xs whitespace-nowrap">
<div className="absolute left-0.5 top-1/2 -translate-x-full -translate-y-1/2 w-0 h-0 border-t-[6px] border-b-[6px] border-r-8 border-t-transparent border-b-transparent border-[#290F0A]" />
<p className="text-xs whitespace-nowrap">
{errors.linkedin}
</p>
</div>
@ -211,34 +214,36 @@ export function MemoriesStep({ onSubmit }: MemoriesStepProps) {
</label>
<span className="text-onboarding text-[10px]">Upto 3</span>
</div>
{otherLinks.map((link, index) => (
<div
key={`other-link-${index}`}
className="flex items-center mb-2 relative"
>
<input
id={`other-links-${index}`}
type="text"
placeholder="Add your website, GitHub, Notion..."
value={link}
onChange={(e) => updateOtherLink(index, e.target.value)}
className="flex-1 px-4 py-2 bg-[#070E1B] border border-onboarding/20 rounded-xl text-white placeholder-onboarding focus:outline-none focus:border-[#4A4A4A] transition-colors h-[40px]"
/>
{index === otherLinks.length - 1 && otherLinks.length < 3 && (
<button
type="button"
onClick={(e) => {
e.preventDefault()
e.stopPropagation()
addOtherLink()
}}
className="size-8 m-1 absolute right-0 top-0 bg-black border border-[#161F2C] rounded-lg flex items-center justify-center text-white hover:bg-[#161F2C] transition-colors text-xl"
>
+
</button>
)}
</div>
))}
<div className="flex flex-col gap-1.5">
{otherLinks.map((link, index) => (
<div
key={`other-link-${index}`}
className="flex items-center relative"
>
<input
id={`other-links-${index}`}
type="text"
placeholder="Add your website, GitHub, Notion..."
value={link}
onChange={(e) => updateOtherLink(index, e.target.value)}
className="flex-1 px-4 py-2 bg-[#070E1B] border border-onboarding/20 rounded-xl text-white placeholder-onboarding focus:outline-none focus:border-[#4A4A4A] transition-colors h-[40px]"
/>
{index === otherLinks.length - 1 && otherLinks.length < 3 && (
<button
type="button"
onClick={(e) => {
e.preventDefault()
e.stopPropagation()
addOtherLink()
}}
className="size-8 m-1 absolute right-0 top-0 bg-black border border-[#161F2C] rounded-lg flex items-center justify-center text-white hover:bg-[#161F2C] transition-colors text-xl"
>
+
</button>
)}
</div>
))}
</div>
</div>
<div
@ -269,7 +274,7 @@ export function MemoriesStep({ onSubmit }: MemoriesStepProps) {
}}
transition={{ duration: 1, ease: "easeOut", delay: 1 }}
initial={{ opacity: 0, y: 10 }}
className="mt-[24px] pb-8"
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"

View file

@ -252,7 +252,7 @@ export function ChatSidebar() {
background: "linear-gradient(180deg, #0A0E14 0%, #05070A 100%)",
}}
>
<NovaOrb size={24} className="!blur-none z-10" />
<NovaOrb size={24} className="blur-[0.6px]! z-10" />
Chat with Nova
</motion.button>
</motion.div>
@ -268,7 +268,7 @@ export function ChatSidebar() {
exit={{ x: "100px", opacity: 0 }}
transition={{ duration: 0.3, ease: "easeOut", bounce: 0 }}
>
<div className="flex items-center justify-between pt-4 px-6 pb-3 shadow-[0_8px_16px_-4px_rgba(0,0,0,0.4)]">
<div className="flex items-center justify-between pt-4 px-4 pb-3 shadow-[0_8px_16px_-4px_rgba(0,0,0,0.4)]">
<ChatModelSelector
selectedModel={selectedModel}
onModelChange={setSelectedModel}
@ -276,7 +276,7 @@ export function ChatSidebar() {
<div className="flex items-center gap-2">
<Button
variant="headers"
className="rounded-full text-base gap-2 !h-10 border-[#73737333] bg-[#0D121A]"
className="rounded-full text-base gap-2 h-10! border-[#73737333] bg-[#0D121A]"
style={{
boxShadow: "1.5px 1.5px 4.5px 0 rgba(0, 0, 0, 0.70) inset",
}}
@ -285,7 +285,7 @@ export function ChatSidebar() {
</Button>
<Button
variant="headers"
className="rounded-full text-base gap-3 !h-10 border-[#73737333] bg-[#0D121A] cursor-pointer"
className="rounded-full text-base gap-3 h-10! border-[#73737333] bg-[#0D121A] cursor-pointer"
style={{
boxShadow: "1.5px 1.5px 4.5px 0 rgba(0, 0, 0, 0.70) inset",
}}
@ -427,9 +427,9 @@ function ChatEmptyStatePlaceholder() {
return (
<div className="flex flex-col items-center justify-center h-full">
<div className="relative">
<GradientLogo className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2" />
<LogoBgGradient className="" />
<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>
@ -443,7 +443,7 @@ function ChatEmptyStatePlaceholder() {
<Button
key={suggestion}
variant="default"
className="rounded-full text-base gap-1 !h-10 border-[#2261CA33] bg-[#0D121A] border w-fit"
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>

View file

@ -1,5 +1,5 @@
import { cn } from "@lib/utils"
import { ArrowUpIcon, SquareIcon } from "lucide-react"
import { SquareIcon } from "lucide-react"
export function SendButton({
onClick,
@ -14,13 +14,25 @@ export function SendButton({
onClick={onClick}
disabled={disabled}
className={cn(
"bg-[#000000] border-[#161F2C] border p-2 rounded-lg flex-shrink-0 transition-opacity",
"bg-[#000000] border-[#161F2C] border p-2 rounded-lg shrink-0 transition-opacity",
disabled
? "opacity-50 cursor-not-allowed"
: "cursor-pointer hover:bg-[#161F2C]",
)}
>
<ArrowUpIcon className="size-5 text-white" />
<svg
width="16"
height="16"
viewBox="0 0 12 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<title>Send Icon</title>
<path
d="M12 6L10.55 7.4L7 3.85L7 16L5 16L5 3.85L1.45 7.4L-4.37114e-07 6L6 -2.62268e-07L12 6Z"
fill="#FAFAFA"
/>
</svg>
</button>
)
}
@ -30,7 +42,7 @@ export function StopButton({ onClick }: { onClick: () => void }) {
<button
type="button"
onClick={onClick}
className="bg-[#000000] border-[#161F2C] border p-2 rounded-lg flex-shrink-0 cursor-pointer hover:bg-[#161F2C] transition-opacity"
className="bg-[#000000] border-[#161F2C] border p-2 rounded-lg shrink-0 cursor-pointer hover:bg-[#161F2C] transition-opacity"
>
<SquareIcon className="size-4 text-white fill-white" />
</button>

View file

@ -51,7 +51,7 @@ export default function ChatInput({
className={cn("bg-[#01173C] relative")}
animate={{
padding: isExpanded ? "0.5rem" : "0",
margin: isExpanded ? "0" : "0.5rem",
margin: isExpanded ? "0" : "16px",
borderRadius: isExpanded ? "0 0 12px 12px" : "12px",
}}
transition={{
@ -71,7 +71,7 @@ export default function ChatInput({
}}
>
{isExpanded && (
<div className="absolute top-0 left-0 right-0 h-10 bg-gradient-to-b from-[#01173C] via-[#01173C]/50 to-transparent pointer-events-none z-10" />
<div className="absolute top-0 left-0 right-0 h-10 bg-linear-to-b from-[#01173C] via-[#01173C]/50 to-transparent pointer-events-none z-10" />
)}
{chainOfThoughtComponent}
</div>
@ -85,8 +85,8 @@ export default function ChatInput({
setIsExpanded(!isExpanded)
}}
>
<div className="flex items-center gap-2">
<NovaOrb size={24} className="!blur-none z-10" />
<div className="flex items-center gap-3">
<NovaOrb size={24} className="blur-[1px]! z-10" />
<p className={cn("text-[#525D6E]", dmSansClassName())}>
{activeStatus || "Waiting for input..."}
</p>

View file

@ -87,7 +87,7 @@ export function RelatedMemories({
)}
</div>
{result.score && (
<div className="flex justify-center p-1">
<div className="flex justify-center p-[4px]">
<div
className={cn(
"text-[10px] inline-block bg-clip-text text-transparent font-medium",

View file

@ -21,7 +21,7 @@ export function UserMessage({
return (
<div className="flex flex-col items-end w-full">
<div className="bg-[#1B1F24] rounded-lg p-3 px-[14px] max-w-[80%]">
<div className="bg-[#1B1F24] rounded-[12px] p-3 px-[14px] max-w-[80%]">
<p className="text-sm text-white">{text}</p>
</div>
<button

View file

@ -8,13 +8,14 @@ export function InitialHeader({
showUserSupermemory?: boolean
name?: string
}) {
const userName = name ? `${name.split(" ")[0]}'s` : "My"
return (
<div className="flex p-6 justify-between items-center">
<div className="flex items-center">
<div className="flex items-center z-10!">
<Logo className="h-7" />
{showUserSupermemory && (
<div className="flex flex-col items-start justify-center ml-2">
<p className="text-[#8B8B8B] text-sm leading-tight">{name}'s</p>
<p className="text-[#8B8B8B] text-sm leading-tight">{userName}</p>
<p className="text-white font-bold text-xl leading-none -mt-1">
supermemory
</p>
@ -23,7 +24,7 @@ export function InitialHeader({
</div>
<Button
variant="newDefault"
className="rounded-2xl text-base gap-1 h-11! z-10"
className="rounded-2xl text-base gap-1 h-11! z-10!"
size={"lg"}
>
Memory API <span className="text-xs mt-[4px]"></span>

View file

@ -0,0 +1,68 @@
import { motion } from "motion/react"
export function AnimatedGradientBackground({
topPosition = "40%",
animateFromBottom = true,
}: {
topPosition?: string
animateFromBottom?: boolean
}) {
return (
<div className="fixed inset-0 z-0 overflow-hidden">
<motion.div
className="absolute top-0 left-0 right-0 bottom-0 bg-[url('/onboarding/bg-gradient-0.png')] bg-size-[150%_auto] bg-top bg-no-repeat"
style={{ top: animateFromBottom ? undefined : topPosition }}
initial={{ y: "100%" }}
animate={{
y: 0,
opacity: animateFromBottom ? 0 : [1, 0, 1],
top: animateFromBottom ? "0%" : topPosition,
}}
transition={{
y: { duration: 0.75, ease: "easeOut" },
opacity: animateFromBottom
? { duration: 2, ease: "easeOut" }
: {
duration: 8,
repeat: Number.POSITIVE_INFINITY,
ease: "easeInOut",
},
top: animateFromBottom
? { duration: 0.75, ease: "easeOut" }
: undefined,
}}
/>
<motion.div
className="absolute top-0 left-0 right-0 bottom-0 bg-[url('/onboarding/bg-gradient-1.png')] bg-size-[150%_auto] bg-top bg-no-repeat"
style={{ top: animateFromBottom ? undefined : topPosition }}
initial={{ y: "100%" }}
animate={{
y: 0,
opacity: animateFromBottom ? 0 : [0, 1, 0],
top: animateFromBottom ? "0%" : topPosition,
}}
transition={{
y: { duration: 0.75, ease: "easeOut" },
opacity: animateFromBottom
? { duration: 2, ease: "easeOut" }
: {
duration: 8,
repeat: Number.POSITIVE_INFINITY,
ease: "easeInOut",
},
top: animateFromBottom
? { duration: 0.75, ease: "easeOut" }
: undefined,
}}
/>
<motion.div
className="absolute top-0 left-0 right-0 bottom-0 bg-[url('/bg-rectangle.png')] bg-cover bg-center bg-no-repeat"
transition={{ duration: 0.75, ease: "easeOut", bounce: 0 }}
style={{
mixBlendMode: "soft-light",
opacity: 0.4,
}}
/>
</div>
)
}

View file

@ -11,6 +11,63 @@ import { FileText, Image, Video } from "lucide-react"
type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema>
type DocumentWithMemories = DocumentsResponse["documents"][0]
function PDFIcon() {
return (
<svg
width="8"
height="10"
viewBox="0 0 8 10"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<title>PDF Icon</title>
<g filter="url(#filter0_i_719_6586)">
<path
d="M1 10C0.725 10 0.489583 9.90208 0.29375 9.70625C0.0979167 9.51042 0 9.275 0 9V1C0 0.725 0.0979167 0.489583 0.29375 0.29375C0.489583 0.0979167 0.725 0 1 0H5L8 3V9C8 9.275 7.90208 9.51042 7.70625 9.70625C7.51042 9.90208 7.275 10 7 10H1ZM4.5 3.5V1H1V9H7V3.5H4.5Z"
fill="#FF7673"
/>
</g>
<defs>
<filter
id="filter0_i_719_6586"
x="0"
y="0"
width="8.25216"
height="10.2522"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"
>
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
/>
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
/>
<feOffset dx="0.252163" dy="0.252163" />
<feGaussianBlur stdDeviation="0.504325" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0.0431373 0 0 0 0 0.0588235 0 0 0 0 0.0823529 0 0 0 0.4 0"
/>
<feBlend
mode="normal"
in2="shape"
result="effect1_innerShadow_719_6586"
/>
</filter>
</defs>
</svg>
)
}
function getFileTypeInfo(document: DocumentWithMemories): {
icon: React.ReactNode
extension: string
@ -22,9 +79,9 @@ function getFileTypeInfo(document: DocumentWithMemories): {
if (mimeType) {
if (mimeType === "application/pdf") {
return {
icon: <PDF className="w-4 h-4 text-[#DC2626]" />,
icon: <PDFIcon />,
extension: ".pdf",
color: "#DC2626",
color: "#FF7673",
}
}
if (mimeType.startsWith("image/")) {
@ -113,7 +170,7 @@ export function FilePreview({ document }: { document: DocumentWithMemories }) {
<div className="flex items-center gap-1 mb-2">
{icon}
<p
className={cn(dmSansClassName(), "text-[12px] font-semibold")}
className={cn(dmSansClassName(), "text-[10px] font-semibold")}
style={{ color: color }}
>
{extension}

View file

@ -19,7 +19,7 @@ export function McpPreview({ document }: { document: DocumentWithMemories }) {
</p>
<MCPIcon className="size-6" />
</div>
<div>
<div className="space-y-[6px]">
{document.title && (
<p className={cn(dmSansClassName(), "text-[12px] font-semibold")}>
{document.title}

View file

@ -63,6 +63,8 @@ export function Header() {
localStorage.getItem("username") || localStorage.getItem("userName") || ""
setName(storedName)
}, [])
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">
@ -70,14 +72,14 @@ export function Header() {
<Logo className="h-7" />
{name && (
<div className="flex flex-col items-start justify-center ml-2">
<p className="text-[#8B8B8B] text-sm leading-tight">{name}'s</p>
<p className="text-[#8B8B8B] text-sm leading-tight">{userName}</p>
<p className="text-white font-bold text-xl leading-none -mt-1">
supermemory
</p>
</div>
)}
</div>
<div className="self-stretch w-[1px] bg-[#FFFFFF33]" />
<div className="self-stretch w-px bg-[#FFFFFF33]" />
<div className="flex items-center gap-2">
<p>📁 {projectName}</p>
<DropdownMenu>
@ -121,7 +123,7 @@ 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!">
<TabsTrigger
value="grid"
className={cn(

View file

@ -15,7 +15,7 @@ function NovaOrb({ size = 200, className = "" }: NovaOrbProps) {
style={{ width: `${size}px`, height: `${size}px` }}
>
<div
className="rounded-full relative overflow-hidden border-[black] border-[1px]"
className="rounded-full relative overflow-hidden"
style={{
width: size,
height: size,

View file

@ -22,7 +22,7 @@ function AnimatedGradientBackground() {
return (
<div className="fixed inset-0 z-0 overflow-hidden">
<motion.div
className="absolute top-[40%] left-0 right-0 bottom-0 bg-[url('/onboarding/bg-gradient-0.png')] bg-size-[150%_auto] bg-top bg-no-repeat"
className="absolute top-[20%] left-0 right-0 bottom-0 bg-[url('/onboarding/bg-gradient-0.png')] bg-size-[150%_auto] bg-top bg-no-repeat"
initial={{ y: "100%" }}
animate={{
y: 0,
@ -34,7 +34,7 @@ function AnimatedGradientBackground() {
}}
/>
<motion.div
className="absolute top-[40%] left-0 right-0 bottom-0 bg-[url('/onboarding/bg-gradient-1.png')] bg-size-[150%_auto] bg-top bg-no-repeat"
className="absolute top-[20%] left-0 right-0 bottom-0 bg-[url('/onboarding/bg-gradient-1.png')] bg-size-[150%_auto] bg-top bg-no-repeat"
initial={{ y: "100%" }}
animate={{
y: 0,
@ -47,8 +47,6 @@ function AnimatedGradientBackground() {
/>
<motion.div
className="absolute top-0 left-0 right-0 bottom-0 bg-[url('/bg-rectangle.png')] bg-cover bg-center bg-no-repeat"
initial={{ y: "100%" }}
animate={{ y: 0 }}
transition={{ duration: 0.75, ease: "easeOut", bounce: 0 }}
style={{
mixBlendMode: "soft-light",
@ -62,7 +60,7 @@ function AnimatedGradientBackground() {
function LoginCard({ children }: { children: React.ReactNode }) {
return (
<motion.div
className="flex max-w-[360px] p-8 flex-col items-start gap-2 rounded-[22px] bg-linear-to-b from-[#06101F] to-[#030912] shadow-[1.5px_1.5px_20px_0_rgba(0,0,0,0.65),1px_1.5px_2px_0_rgba(128,189,255,0.07)_inset,-0.5px_-1.5px_4px_0_rgba(0,35,73,0.40)_inset]"
className="flex py-8 px-11 flex-col items-start gap-2 rounded-[22px] bg-linear-to-b from-[#06101F] to-[#030912] shadow-[1.5px_1.5px_20px_0_rgba(0,0,0,0.65),1px_1.5px_2px_0_rgba(128,189,255,0.07)_inset,-0.5px_-1.5px_4px_0_rgba(0,35,73,0.40)_inset]"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.75, ease: "easeOut" }}
@ -225,7 +223,7 @@ export function LoginPage() {
</div>
{submittedEmail ? (
<LoginCard>
<div className="w-full flex flex-col gap-4 lg:gap-6 min-h-2/3">
<div className="w-[360px] flex flex-col gap-4 lg:gap-6 min-h-2/3">
<div className="flex flex-col gap-2 text-center lg:text-left">
<Title1Bold className="text-foreground">
Almost there!
@ -262,7 +260,10 @@ export function LoginPage() {
</LoginCard>
) : (
<LoginCard>
<div className="w-full flex flex-col" style={{ gap: "12px" }}>
<div
className="w-[360px] flex flex-col"
style={{ gap: "12px" }}
>
{params.get("error") && (
<div className="text-red-500">
Error: {params.get("error")}. Please try again!