From 0bc77796fc102f97f63ec2dbd5a241ea514fb4fc Mon Sep 17 00:00:00 2001 From: Mahesh Sanikommmu Date: Thu, 27 Nov 2025 19:00:49 -0800 Subject: [PATCH] added few more fixes --- apps/memory-graph-playground/next-env.d.ts | 6 + apps/web/app/onboarding/page.tsx | 8 +- .../onboarding/setup/relatable-question.tsx | 6 +- .../app/onboarding/welcome/memories-step.tsx | 154 ++++++++++++++++-- apps/web/components/mcp-detail-view.tsx | 34 +++- apps/web/globals.css | 12 ++ packages/ui/assets/Logo.tsx | 44 ++--- packages/ui/assets/icons.tsx | 18 +- 8 files changed, 221 insertions(+), 61 deletions(-) create mode 100644 apps/memory-graph-playground/next-env.d.ts diff --git a/apps/memory-graph-playground/next-env.d.ts b/apps/memory-graph-playground/next-env.d.ts new file mode 100644 index 00000000..c4b7818f --- /dev/null +++ b/apps/memory-graph-playground/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +import "./.next/dev/types/routes.d.ts"; + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/web/app/onboarding/page.tsx b/apps/web/app/onboarding/page.tsx index 0e8ee034..147bbfb6 100644 --- a/apps/web/app/onboarding/page.tsx +++ b/apps/web/app/onboarding/page.tsx @@ -169,7 +169,9 @@ export default function OnboardingPage() {
{isWelcomeFlow && ( )} @@ -178,9 +180,9 @@ export default function OnboardingPage() { {isSetupFlow && } {isWelcomeFlow && ( -
+
{ diff --git a/apps/web/app/onboarding/welcome/memories-step.tsx b/apps/web/app/onboarding/welcome/memories-step.tsx index a2309902..260b61d2 100644 --- a/apps/web/app/onboarding/welcome/memories-step.tsx +++ b/apps/web/app/onboarding/welcome/memories-step.tsx @@ -2,6 +2,8 @@ import { motion } from "motion/react" import { Button } from "@ui/components/button" import { useState } from "react" import { useRouter } from "next/navigation" +import { cn } from "@lib/utils" +import { dmSansClassName } from "@/utils/fonts" interface MemoriesStepProps { onSubmit: (data: { @@ -12,6 +14,11 @@ interface MemoriesStepProps { }) => void } +type ValidationError = { + twitter: string | null + linkedin: string | null +} + export function MemoriesStep({ onSubmit }: MemoriesStepProps) { const router = useRouter() const [otherLinks, setOtherLinks] = useState([""]) @@ -19,6 +26,10 @@ export function MemoriesStep({ onSubmit }: MemoriesStepProps) { const [linkedinProfile, setLinkedinProfile] = useState("") const [description, setDescription] = useState("") const [isSubmitting] = useState(false) + const [errors, setErrors] = useState({ + twitter: null, + linkedin: null, + }) const addOtherLink = () => { if (otherLinks.length < 3) { @@ -32,6 +43,66 @@ export function MemoriesStep({ onSubmit }: MemoriesStepProps) { setOtherLinks(updated) } + const validateTwitterLink = (value: string): string | null => { + if (!value.trim()) return null + + const normalized = value.trim().toLowerCase() + const isXDomain = + normalized.includes("x.com") || normalized.includes("twitter.com") + + if (!isXDomain) { + return "share your X profile link" + } + + // Check if it's a profile link (not a status/tweet link) + const profilePattern = + /^(https?:\/\/)?(www\.)?(x\.com|twitter\.com)\/[^\/]+$/ + const statusPattern = /\/status\//i + + if (statusPattern.test(normalized) || !profilePattern.test(normalized)) { + return "share your X profile link" + } + + // Note: 404 validation would require a backend API endpoint + // Format validation is handled above + return null + } + + const validateLinkedInLink = (value: string): string | null => { + if (!value.trim()) return null + + const normalized = value.trim().toLowerCase() + const isLinkedInDomain = normalized.includes("linkedin.com") + + if (!isLinkedInDomain) { + return "share your Linkedin profile link" + } + + // Check if it's a profile link (should have /in/ or /pub/) + const profilePattern = + /^(https?:\/\/)?(www\.)?linkedin\.com\/(in|pub)\/[^\/]+/ + + if (!profilePattern.test(normalized)) { + return "share your Linkedin profile link" + } + + // Note: 404 validation would require a backend API endpoint + // Format validation is handled above + return null + } + + const handleTwitterChange = (value: string) => { + setTwitterHandle(value) + const error = validateTwitterLink(value) + setErrors((prev) => ({ ...prev, twitter: error })) + } + + const handleLinkedInChange = (value: string) => { + setLinkedinProfile(value) + const error = validateLinkedInLink(value) + setErrors((prev) => ({ ...prev, linkedin: error })) + } + return ( -
+
- setTwitterHandle(e.target.value)} - className="w-full px-4 py-2 bg-[#070E1B] border border-[#525966]/20 rounded-xl text-white placeholder-onboarding focus:outline-none focus:border-[#4A4A4A] transition-colors h-[40px]" - /> +
+ handleTwitterChange(e.target.value)} + onBlur={() => { + if (twitterHandle.trim()) { + const error = validateTwitterLink(twitterHandle) + setErrors((prev) => ({ ...prev, twitter: error })) + } + }} + className={`w-full px-4 py-2 bg-[#070E1B] border rounded-xl text-white placeholder-onboarding focus:outline-none transition-colors h-[40px] ${ + errors.twitter + ? "border-[#52596633] bg-[#290F0A]" + : "border-[#525966]/20" + }`} + /> + {errors.twitter && ( +
+
+
+

+ {errors.twitter} +

+
+
+ )} +
@@ -69,14 +162,41 @@ export function MemoriesStep({ onSubmit }: MemoriesStepProps) { > LinkedIn - setLinkedinProfile(e.target.value)} - className="w-full px-4 py-2 bg-[#070E1B] border border-[#525966]/20 rounded-xl text-white placeholder-onboarding focus:outline-none focus:border-[#4A4A4A] transition-colors h-[40px]" - /> +
+ handleLinkedInChange(e.target.value)} + onBlur={() => { + if (linkedinProfile.trim()) { + const error = validateLinkedInLink(linkedinProfile) + setErrors((prev) => ({ ...prev, linkedin: error })) + } + }} + className={`w-full px-4 py-2 bg-[#070E1B] border rounded-xl text-white placeholder-onboarding focus:outline-none transition-colors h-[40px] ${ + errors.linkedin + ? "border-[#52596633] bg-[#290F0A]" + : "border-[#525966]/20" + }`} + /> + {errors.linkedin && ( +
+
+
+

+ {errors.linkedin} +

+
+
+ )} +
-
+

MCP connects your AI apps to create and use memories directly

-
+

Auto-fetch the right context from anything you've saved

-
+

One-time setup, seamless integration across your workflow @@ -229,10 +244,10 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) { setSelectedClient(key as keyof typeof clients) setActiveStep(2) }} - className={`px-3 py-1 rounded-full border-1 transition-colors cursor-pointer duration-200 ${ + className={`mcp-client-button-group px-3 py-1 rounded-full border-1 transition-colors cursor-pointer duration-200 ${ selectedClient === key ? "border-blue-500 bg-blue-500/10" - : "border-[#0D121A] bg-[#080B0F] hover:border-gray-600" + : "border-[#242A33] bg-[#080B0F] hover:border-[#3273FC4D] hover:bg-[#08142D]" }`} >

@@ -267,7 +282,7 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) { width={20} />
- + {clientName}
@@ -275,7 +290,12 @@ export function MCPDetailView({ onBack }: MCPDetailViewProps) { ))}
{!selectedClient && ( -

+

*You can connect to all of these, setup is different for each one

diff --git a/apps/web/globals.css b/apps/web/globals.css index 0f6fbd1a..c71ee39d 100644 --- a/apps/web/globals.css +++ b/apps/web/globals.css @@ -54,3 +54,15 @@ letter-spacing: -0.01em; line-height: 135%; } + +.mcp-client-button-group:hover .mcp-client-gradient-text { + background: linear-gradient( + 94deg, + #369bfd 4.8%, + #36fdfd 77.04%, + #36fdb5 143.99% + ); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} diff --git a/packages/ui/assets/Logo.tsx b/packages/ui/assets/Logo.tsx index 9d4a70e4..6741acf9 100644 --- a/packages/ui/assets/Logo.tsx +++ b/packages/ui/assets/Logo.tsx @@ -50,7 +50,7 @@ export const LogoFull = ({ ); }; -export const GradientLogo = ({ className = ""} : { className?: string }) => { +export const GradientLogo = ({ className = "" }: { className?: string }) => { return ( { className={className} > Gradient supermemory logo - + { y2="9.51098" gradientUnits="userSpaceOnUse" > - - - + + + { y2="9.51098" gradientUnits="userSpaceOnUse" > - - - + + + { ); -} +}; export const LogoBgGradient = ({ className = "" }: { className?: string }) => { return ( @@ -190,9 +190,9 @@ export const LogoBgGradient = ({ className = "" }: { className?: string }) => { width="161.006" height="181.977" filterUnits="userSpaceOnUse" - color-interpolation-filters="sRGB" + colorInterpolationFilters="sRGB" > - + { width="161.006" height="181.977" filterUnits="userSpaceOnUse" - color-interpolation-filters="sRGB" + colorInterpolationFilters="sRGB" > - + { width="145.315" height="124.713" filterUnits="userSpaceOnUse" - color-interpolation-filters="sRGB" + colorInterpolationFilters="sRGB" > - + { width="100.311" height="100.602" filterUnits="userSpaceOnUse" - color-interpolation-filters="sRGB" + colorInterpolationFilters="sRGB" > - + { width="100.311" height="100.602" filterUnits="userSpaceOnUse" - color-interpolation-filters="sRGB" + colorInterpolationFilters="sRGB" > - + { width="120.737" height="110.105" filterUnits="userSpaceOnUse" - color-interpolation-filters="sRGB" + colorInterpolationFilters="sRGB" > - + { ); -} \ No newline at end of file +}; diff --git a/packages/ui/assets/icons.tsx b/packages/ui/assets/icons.tsx index c8c8dcc5..c2ae59fc 100644 --- a/packages/ui/assets/icons.tsx +++ b/packages/ui/assets/icons.tsx @@ -293,9 +293,9 @@ export const MCPIcon = ({ className }: { className?: string }) => { y2="7.53871" gradientUnits="userSpaceOnUse" > - - - + + + { y2="7.53871" gradientUnits="userSpaceOnUse" > - - - + + + { y2="7.53871" gradientUnits="userSpaceOnUse" > - - - + + +