memory bar

This commit is contained in:
Yash 2024-04-02 15:44:50 +00:00
parent 13d0a10d7f
commit e950b84df5
9 changed files with 696 additions and 21 deletions

View file

@ -1,3 +1,5 @@
import { svgId } from "@/lib/utils";
export const MemoryIcon: React.FC<React.SVGAttributes<SVGElement>> = (
props,
) => (

View file

@ -0,0 +1,528 @@
import { svgId } from "@/lib/utils";
export const MemoryWithImage: React.FC<
{ image: string; id: string } & React.SVGAttributes<SVGElement>
> = ({ image, id: _id, ...props }) => {
const id = "space-1-" + _id;
return (
<svg
viewBox="0 0 137 137"
fill="none"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
{...props}
>
<g filter={`url(#${svgId(id, "filter0_d_83_72")})`}>
<rect
x="33"
y="33"
width="72.207"
height="72.207"
rx="10"
fill="var(--gray-4)"
/>
</g>
<rect
x="47.0637"
y="46.9976"
width="45"
height="45"
fill={`url(#${svgId(id, "pattern0")})`}
/>
<defs>
<filter
id={svgId(id, "filter0_d_83_72")}
x="21"
y="21"
width="96.207"
height="96.207"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<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"
/>
<feMorphology
radius="2"
operator="dilate"
in="SourceAlpha"
result="effect1_dropShadow_83_72"
/>
<feOffset />
<feGaussianBlur stdDeviation="5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
/>
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_83_72"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_83_72"
result="shape"
/>
</filter>
<pattern
id={svgId(id, "pattern0")}
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<use
xlinkHref={`#${svgId(id, "image0_83_72")}`}
transform="scale(0.00520833)"
/>
</pattern>
<image
id={svgId(id, "image0_83_72")}
width="192"
height="192"
xlinkHref={image}
/>
</defs>
</svg>
);
};
export const MemoryWithImages2: React.FC<
{ images: string[]; id: string } & React.SVGAttributes<SVGElement>
> = ({ images, id: _id, ...props }) => {
const id = "space-2-" + _id;
return (
<svg
viewBox="0 0 137 137"
fill="none"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
{...props}
>
<g clipPath={`url(#${svgId(id, "clip0_80_62")})`}>
<g filter={`url(#${svgId(id, "filter0_d_80_62")})`}>
<rect
x="7"
y="51.5427"
width="72.207"
height="72.207"
rx="10"
transform="rotate(-24.1922 7 51.5427)"
fill="var(--gray-4)"
/>
</g>
<rect
x="26.2664"
y="58.9253"
width="45"
height="45"
transform="rotate(-24.2 26.2664 58.9253)"
fill={`url(#${svgId(id, "pattern0")})`}
/>
<g filter={`url(#${svgId(id, "filter1_d_80_62")})`}>
<rect
x="59.9409"
y="42.2124"
width="72.207"
height="72.207"
rx="10"
transform="rotate(10.2301 59.9409 42.2124)"
fill="var(--gray-4)"
/>
</g>
<rect
x="71.2952"
y="58.4851"
width="45"
height="45"
transform="rotate(10.23 71.2952 58.4851)"
fill={`url(#${svgId(id, "pattern1")})`}
/>
</g>
<defs>
<filter
id={svgId(id, "filter0_d_80_62")}
x="-1.78271"
y="13.1697"
width="113.021"
height="113.021"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<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"
/>
<feMorphology
radius="2"
operator="dilate"
in="SourceAlpha"
result="effect1_dropShadow_80_62"
/>
<feOffset />
<feGaussianBlur stdDeviation="5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
/>
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_80_62"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_80_62"
result="shape"
/>
</filter>
<pattern
id={svgId(id, "pattern0")}
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<use
xlinkHref={`#${svgId(id, "image0_80_62")}`}
transform="scale(0.0111111)"
/>
</pattern>
<filter
id={svgId(id, "filter1_d_80_62")}
x="36.7322"
y="31.8276"
width="104.652"
height="104.653"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<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"
/>
<feMorphology
radius="2"
operator="dilate"
in="SourceAlpha"
result="effect1_dropShadow_80_62"
/>
<feOffset />
<feGaussianBlur stdDeviation="5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
/>
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_80_62"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_80_62"
result="shape"
/>
</filter>
<pattern
id={svgId(id, "pattern1")}
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<use
xlinkHref={`#${svgId(id, "image1_80_62")}`}
transform="scale(0.00520833)"
/>
</pattern>
<clipPath id={svgId(id, "clip0_80_62")}>
<rect width="137" height="137" fill="white" />
</clipPath>
<image
id={svgId(id, "image0_80_62")}
width="90"
height="90"
xlinkHref={images[0]}
/>
<image
id={svgId(id, "image1_80_62")}
width="192"
height="192"
xlinkHref={images[1]}
/>
</defs>
</svg>
);
};
export const MemoryWithImages3: React.FC<
{ images: string[]; id: string } & React.SVGAttributes<SVGElement>
> = ({ images, id: _id, ...props }) => {
const id = "space-3-" + _id;
return (
<svg
viewBox="0 0 137 137"
fill="none"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
{...props}
>
<g clipPath={`url(#${svgId(id, "clip0_79_36")})`}>
<g filter={`url(#${svgId(id, "filter0_d_79_36")})`}>
<rect
x="53.5242"
y="12"
width="72.207"
height="72.207"
rx="10"
transform="rotate(14.9009 53.5242 12)"
fill="var(--gray-4)"
/>
</g>
<rect
x="63.3663"
y="27.3052"
width="45"
height="45"
transform="rotate(14.9 63.3663 27.3052)"
fill={`url(#${svgId(id, "pattern0")})`}
/>
<g filter={`url(#${svgId(id, "filter1_d_79_36")})`}>
<rect
x="7"
y="51.5427"
width="72.207"
height="72.207"
rx="10"
transform="rotate(-24.1922 7 51.5427)"
fill="var(--gray-4)"
/>
</g>
<rect
x="26.2664"
y="58.9253"
width="45"
height="45"
transform="rotate(-24.2 26.2664 58.9253)"
fill={`url(#${svgId(id, "pattern1")})`}
/>
<g filter={`url(#${svgId(id, "filter2_d_79_36")})`}>
<rect
x="59.9409"
y="42.2124"
width="72.207"
height="72.207"
rx="10"
transform="rotate(10.2301 59.9409 42.2124)"
fill="var(--gray-4)"
/>
</g>
<rect
x="71.2952"
y="58.4851"
width="45"
height="45"
transform="rotate(10.23 71.2952 58.4851)"
fill={`url(#${svgId(id, "pattern2")})`}
/>
</g>
<defs>
<filter
id={svgId(id, "filter0_d_79_36")}
x="25.189"
y="2.23267"
width="107.881"
height="107.881"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<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"
/>
<feMorphology
radius="2"
operator="dilate"
in="SourceAlpha"
result="effect1_dropShadow_79_36"
/>
<feOffset />
<feGaussianBlur stdDeviation="5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
/>
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_79_36"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_79_36"
result="shape"
/>
</filter>
<pattern
id={svgId(id, "pattern0")}
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<use
xlinkHref={`#${svgId(id, "image0_79_36")}`}
transform="scale(0.0111111)"
/>
</pattern>
<filter
id={svgId(id, "filter1_d_79_36")}
x="-1.78271"
y="13.1697"
width="113.021"
height="113.021"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<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"
/>
<feMorphology
radius="2"
operator="dilate"
in="SourceAlpha"
result="effect1_dropShadow_79_36"
/>
<feOffset />
<feGaussianBlur stdDeviation="5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
/>
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_79_36"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_79_36"
result="shape"
/>
</filter>
<pattern
id={svgId(id, "pattern1")}
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<use
xlinkHref={`#${svgId(id, "image1_79_36")}`}
transform="scale(0.0111111)"
/>
</pattern>
<filter
id={svgId(id, "filter2_d_79_36")}
x="36.7322"
y="31.8276"
width="104.652"
height="104.653"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<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"
/>
<feMorphology
radius="2"
operator="dilate"
in="SourceAlpha"
result="effect1_dropShadow_79_36"
/>
<feOffset />
<feGaussianBlur stdDeviation="5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
/>
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_79_36"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_79_36"
result="shape"
/>
</filter>
<pattern
id={svgId(id, "pattern2")}
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<use
xlinkHref={`#${svgId(id, "image2_79_36")}`}
transform="scale(0.00520833)"
/>
</pattern>
<clipPath id={svgId(id, "clip0_79_36")}>
<rect width="137" height="137" fill="white" />
</clipPath>
<image
id={svgId(id, "image0_79_36")}
width="90"
height="90"
xlinkHref={images[0]}
/>
<image
id={svgId(id, "image1_79_36")}
width="90"
height="90"
xlinkHref={images[1]}
/>
<image
id={svgId(id, "image2_79_36")}
width="192"
height="192"
xlinkHref={images[2]}
/>
</defs>
</svg>
);
};

View file

@ -18,6 +18,7 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
placeholder: "Ask your SuperMemory...",
className: "text-lg p-2 text-rgray-11",
value,
autoFocus: true,
onChange: (e) => setValue(e.target.value),
}}
>

View file

@ -0,0 +1,141 @@
import {
MemoryWithImage,
MemoryWithImages3,
MemoryWithImages2,
} from "@/assets/MemoryWithImages";
import { type Space } from "../../../types/memory";
import { InputWithIcon } from "../ui/input";
import { Search } from "lucide-react";
export function MemoriesBar() {
const spaces: Space[] = [
{
id: 1,
title: "Cool Tech",
description: "Really cool mind blowing tech",
content: [
{
id: 1,
title: "Perplexity",
description: "A good ui",
content: "",
image: "https://perplexity.ai/favicon.ico",
url: "https://perplexity.ai",
savedAt: new Date(),
baseUrl: "https://perplexity.ai",
},
{
id: 2,
title: "Pi.ai",
description: "A good ui",
content: "",
image: "https://pi.ai/pi-logo-192.png?v=2",
url: "https://pi.ai",
savedAt: new Date(),
baseUrl: "https://pi.ai",
},
{
id: 3,
title: "Visual Studio Code",
description: "A good ui",
content: "",
image: "https://code.visualstudio.com/favicon.ico",
url: "https://code.visualstudio.com",
savedAt: new Date(),
baseUrl: "https://code.visualstudio.com",
},
],
},
{
id: 2,
title: "Cool Courses",
description: "Amazng",
content: [
{
id: 1,
title: "Animation on the web",
description: "A good ui",
content: "",
image: "https://animations.dev/favicon.ico",
url: "https://animations.dev",
savedAt: new Date(),
baseUrl: "https://animations.dev",
},
{
id: 2,
title: "Tailwind Course",
description: "A good ui",
content: "",
image:
"https://tailwindcss.com/_next/static/media/tailwindcss-mark.3c5441fc7a190fb1800d4a5c7f07ba4b1345a9c8.svg",
url: "https://tailwindcss.com",
savedAt: new Date(),
baseUrl: "https://tailwindcss.com",
},
],
},
{
id: 3,
title: "Cool Libraries",
description: "Really cool mind blowing tech",
content: [
{
id: 1,
title: "Perplexity",
description: "A good ui",
content: "",
image: "https://yashverma.me/logo.jpg",
url: "https://perplexity.ai",
savedAt: new Date(),
baseUrl: "https://perplexity.ai",
},
],
},
];
return (
<div className="text-rgray-11 flex w-full flex-col items-start py-8 text-left">
<div className="w-full px-8">
<h1 className="w-full text-2xl">Your Memories</h1>
<InputWithIcon
placeholder="Search"
icon={<Search className="text-rgray-11 h-5 w-5 opacity-50" />}
className="bg-rgray-4 mt-2 w-full"
/>
</div>
<div className="grid w-full grid-flow-row grid-cols-3 gap-1 px-2 py-5">
{spaces.map((space) => (
<Space key={space.id} {...space} />
))}
</div>
</div>
);
}
export function Space({ title, description, content, id }: Space) {
console.log(title, content.map((c) => c.image).reverse());
return (
<button className="hover:bg-rgray-2 focus-visible:bg-rgray-2 focus-visible:ring-rgray-7 flex flex-col items-center justify-center rounded-md p-2 text-center ring-transparent transition focus-visible:outline-none focus-visible:ring-2">
{content.length > 2 ? (
<MemoryWithImages3
className="h-24 w-24"
id={id.toString()}
images={content.map((c) => c.image).reverse() as string[]}
/>
) : content.length === 1 ? (
<MemoryWithImage
className="h-24 w-24"
id={id.toString()}
image={content[0].image!}
/>
) : (
<MemoryWithImages2
className="h-24 w-24"
id={id.toString()}
images={content.map((c) => c.image).reverse() as string[]}
/>
)}
<span>{title}</span>
</button>
);
}

View file

@ -1,9 +1,9 @@
"use client";
import { StoredContent } from "@/server/db/schema";
import { MemoryIcon } from "../../assets/Memories";
import { Search, Trash2, User2 } from "lucide-react";
import { Trash2, User2 } from "lucide-react";
import React, { useState } from "react";
import { InputWithIcon } from "../ui/input";
import { MemoriesBar } from "./MemoriesBar";
export type MenuItem = {
icon: React.ReactNode | React.ReactNode[];
@ -96,21 +96,8 @@ const MenuItem = ({
export function SubSidebar({ children }: { children?: React.ReactNode }) {
return (
<div className="bg-rgray-3 border-r-rgray-6 flex h-screen w-[50vw] flex-col items-center border-r p-8 font-light">
<div className="bg-rgray-3 border-r-rgray-6 flex h-screen w-[50vw] flex-col items-center border-r font-light">
{children}
</div>
);
}
export function MemoriesBar() {
return (
<div className="text-rgray-11 flex w-full flex-col items-start text-left">
<h1 className="text-2xl">Your Memories</h1>
<InputWithIcon
placeholder="Search"
icon={<Search className="h-5 w-5" />}
className="mt-2"
/>
</div>
);
}

View file

@ -11,7 +11,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
type={type}
className={cn(
"border-rgray-6 text-rgray-12 ring-offset-rgray-2 placeholder:text-rgray-11 focus-visible:ring-rgray-7 flex h-10 w-full rounded-md border bg-transparent px-3 py-2 text-sm transition file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50 ",
"border-rgray-6 text-rgray-11 placeholder:text-rgray-11 focus-visible:ring-rgray-7 flex h-10 w-full rounded-md border bg-transparent px-3 py-2 text-sm transition file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50 ",
className,
)}
ref={ref}
@ -31,7 +31,7 @@ const InputWithIcon = React.forwardRef<HTMLInputElement, InputWithIconProps>(
return (
<div
className={cn(
"border-rgray-6 text-rgray-12 ring-offset-rgray-2 focus-within:ring-rgray-7 flex h-10 w-full items-center justify-center gap-2 rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-1 ",
"border-rgray-6 text-rgray-11 focus-within:ring-rgray-7 flex h-10 w-full items-center justify-center gap-2 rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2 ",
className,
)}
>

View file

@ -10,7 +10,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
return (
<textarea
className={cn(
"border-rgray-6 ring-offset-rgray-2 placeholder:text-rgray-11/70 focus-within:ring-rgray-7 flex min-h-[80px] w-full rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
"border-rgray-6 text-rgray-11 placeholder:text-rgray-11/70 focus-within:ring-rgray-7 flex min-h-[80px] w-full rounded-md border bg-transparent px-3 py-2 text-sm font-normal transition focus-within:outline-none focus-within:ring-2 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
@ -32,14 +32,14 @@ const Textarea2 = React.forwardRef<HTMLTextAreaElement, Textarea2Props>(
return (
<div
className={cn(
"border-rgray-6 ring-offset-rgray-2 focus-within:ring-rgray-7 flex h-auto min-h-[80px] w-full flex-col items-start justify-center rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2",
"border-rgray-6 text-rgray-11 focus-within:ring-rgray-7 flex h-auto min-h-[80px] w-full flex-col items-start justify-center rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2",
className,
)}
{...props}
>
<textarea
className={cn(
"placeholder:text-rgray-11/70 h-full w-full resize-none bg-transparent font-normal focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
"placeholder:text-rgray-11/70 h-full w-full resize-none bg-transparent focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
textAreaClassName,
)}
ref={ref}

View file

@ -16,3 +16,11 @@ export function cleanUrl(url: string) {
? url.slice(7)
: url;
}
export function generateId() {
return Math.random().toString(36).slice(2, 9);
}
export function svgId(prefix: string, id: string) {
return `${prefix}-${id}`;
}

View file

@ -0,0 +1,8 @@
import { StoredContent } from "@/server/db/schema";
export type Space = {
id: number;
title: string;
description: string;
content: StoredContent[];
};