aboutsummaryrefslogtreecommitdiff
path: root/apps/web
diff options
context:
space:
mode:
authorcodetorso <[email protected]>2024-06-08 06:25:25 +0530
committercodetorso <[email protected]>2024-06-08 06:25:25 +0530
commit004c952dc323ef481ae0b1532bab78b244841dbc (patch)
tree07973184e11daeae0d3fd0663fd01cdbf499a8ce /apps/web
parentadded top bar nav (diff)
downloadsupermemory-004c952dc323ef481ae0b1532bab78b244841dbc.tar.xz
supermemory-004c952dc323ef481ae0b1532bab78b244841dbc.zip
Add Dynamic Island
Diffstat (limited to 'apps/web')
-rw-r--r--apps/web/app/(dash)/dynamicisland.tsx194
-rw-r--r--apps/web/app/(dash)/header.tsx40
-rw-r--r--apps/web/app/(dash)/home/page.tsx2
-rw-r--r--apps/web/app/(dash)/home/queryinput.tsx2
-rw-r--r--apps/web/app/(dash)/menu.tsx2
5 files changed, 205 insertions, 35 deletions
diff --git a/apps/web/app/(dash)/dynamicisland.tsx b/apps/web/app/(dash)/dynamicisland.tsx
new file mode 100644
index 00000000..a30ec8cf
--- /dev/null
+++ b/apps/web/app/(dash)/dynamicisland.tsx
@@ -0,0 +1,194 @@
+"use client";
+
+import { AddIcon } from "@repo/ui/icons";
+import Image from "next/image";
+
+import { AnimatePresence, useMotionValueEvent, useScroll } from "framer-motion";
+import { useState } from "react";
+import { motion } from "framer-motion";
+import { Label } from "@repo/ui/shadcn/label";
+import { Input } from "@repo/ui/shadcn/input";
+import { Textarea } from "@repo/ui/shadcn/textarea";
+
+export function DynamicIsland() {
+ const { scrollYProgress } = useScroll();
+ const [visible, setVisible] = useState(true);
+
+ useMotionValueEvent(scrollYProgress, "change", (current) => {
+ // Check if current is not undefined and is a number
+ if (typeof current === "number") {
+ let direction = current! - scrollYProgress.getPrevious()!;
+
+ if (direction < 0 || direction === 1) {
+ setVisible(true);
+ } else {
+ setVisible(false);
+ }
+ }
+ });
+
+ return (
+ <div className="fixed z-40 left-1/2 -translate-x-1/2 top-12">
+ <AnimatePresence mode="wait">
+ <motion.div
+ initial={{
+ opacity: 1,
+ y: -150,
+ }}
+ animate={{
+ y: visible ? 0 : -150,
+ opacity: visible ? 1 : 0,
+ }}
+ transition={{
+ duration: 0.2,
+ }}
+ className="flex flex-col items-center"
+ >
+ <DynamicIslandContent />
+ </motion.div>
+ </AnimatePresence>
+ </div>
+ );
+}
+
+export default DynamicIsland;
+
+function DynamicIslandContent() {
+ const [show, setshow] = useState(true);
+ function cancelfn(){
+ setshow(true);
+ }
+ return (
+ <>
+ {show ? (
+ <div
+ onClick={() => setshow(!show)}
+ className="bg-[#1F2428] p-2 rounded-3xl"
+ >
+ <Image src={AddIcon} alt="Add icon" />
+ </div>
+ ) : (
+ <div>
+ <ToolBar cancelfn={cancelfn} />
+ </div>
+ )}
+ </>
+ );
+}
+
+const fakeitems = ["spaces", "page", "note"];
+
+function ToolBar({cancelfn}: {cancelfn: ()=> void}) {
+ const [index, setIndex] = useState(0);
+ return (
+ <div className="flex flex-col items-center">
+ <div className="bg-[#1F2428] py-[.35rem] px-[.6rem] rounded-2xl">
+ <HoverEffect
+ items={fakeitems}
+ index={index}
+ indexFn={(i) => setIndex(i)}
+ />
+ </div>
+ { index === 0 ?
+ <SpaceForm cancelfn={cancelfn} /> :
+ index === 1 ?
+ <PageForm cancelfn={cancelfn} /> :
+ <NoteForm cancelfn={cancelfn} />
+ }
+ </div>
+ );
+}
+
+export const HoverEffect = ({
+ items,
+ index,
+ indexFn,
+}: {
+ items: string[];
+ index: number;
+ indexFn: (i: number) => void;
+}) => {
+ return (
+ <div className={"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3"}>
+ {items.map((item, idx) => (
+ <button
+ key={idx}
+ className="relative block h-full w-full px-2 py-1"
+ onClick={() => indexFn(idx)}
+ >
+ <AnimatePresence>
+ {index === idx && (
+ <motion.span
+ className="absolute inset-0 block h-full w-full rounded-xl bg-[#2B3237]"
+ layoutId="hoverBackground"
+ initial={{ opacity: 0 }}
+ animate={{
+ opacity: 1,
+ transition: { duration: 0.15 },
+ }}
+ exit={{
+ opacity: 0,
+ transition: { duration: 0.15, delay: 0.2 },
+ }}
+ />
+ )}
+ </AnimatePresence>
+ <h3 className="text-[#858B92] z-50 relative">{item}</h3>
+ </button>
+ ))}
+ </div>
+ );
+};
+
+function SpaceForm({cancelfn}: {cancelfn: ()=> void}) {
+ return (
+ <div className="bg-[#1F2428] px-4 py-3 rounded-2xl mt-2 flex flex-col gap-3">
+ <div >
+ <Label className="text-[#858B92]" htmlFor="name">Name</Label>
+ <Input className="bg-[#2B3237] outline-none border-none focus:border-none focus:outline-none" id="name"/>
+ </div>
+ <div className="flex justify-between">
+ <a className="text-blue-500" href="">
+ pull from store
+ </a>
+ <div onClick={cancelfn} className="bg-[#2B3237] px-2 py-1 rounded-xl cursor-pointer">cancel</div>
+ </div>
+ </div>
+ );
+}
+
+function PageForm({cancelfn}: {cancelfn: ()=> void}) {
+ return (
+ <div className="bg-[#1F2428] px-4 py-3 rounded-2xl mt-2 flex flex-col gap-3">
+ <div >
+ <Label className="text-[#858B92]" htmlFor="name">Space</Label>
+ <Input className="bg-[#2B3237] outline-none border-none focus:border-none focus:outline-none" id="name"/>
+ </div>
+ <div >
+ <Label className="text-[#858B92]" htmlFor="name">Page Url</Label>
+ <Input className="bg-[#2B3237] outline-none border-none focus:border-none focus:outline-none" id="name"/>
+ </div>
+ <div className="flex justify-end">
+ <div onClick={cancelfn} className="bg-[#2B3237] px-2 py-1 rounded-xl cursor-pointer">cancel</div>
+ </div>
+ </div>
+ );
+}
+
+function NoteForm({cancelfn}: {cancelfn: ()=> void}) {
+ return (
+ <div className="bg-[#1F2428] px-4 py-3 rounded-2xl mt-2 flex flex-col gap-3">
+ <div >
+ <Label className="text-[#858B92]" htmlFor="name">Space</Label>
+ <Input className="bg-[#2B3237] outline-none border-none focus:border-none focus:outline-none" id="name"/>
+ </div>
+ <div >
+ <Label className="text-[#858B92]" htmlFor="name">Note</Label>
+ <Textarea cols={4} className="bg-[#2B3237] outline-none border-none resize-none" id="name"/>
+ </div>
+ <div className="flex justify-end">
+ <div onClick={cancelfn} className="bg-[#2B3237] px-2 py-1 rounded-xl cursor-pointer">cancel</div>
+ </div>
+ </div>
+ );
+} \ No newline at end of file
diff --git a/apps/web/app/(dash)/header.tsx b/apps/web/app/(dash)/header.tsx
index 104c63bc..c5aeca3b 100644
--- a/apps/web/app/(dash)/header.tsx
+++ b/apps/web/app/(dash)/header.tsx
@@ -2,49 +2,25 @@ import React from "react";
import Image from "next/image";
import Link from "next/link";
import Logo from "../../public/logo.svg";
-import { AddIcon, ChatIcon } from "@repo/ui/icons";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@repo/ui/shadcn/tabs";
+import { ChatIcon } from "@repo/ui/icons";
+
+import DynamicIsland from "./dynamicisland";
function Header() {
return (
<div>
- <div className="flex items-center justify-between relative z-10">
- <Link href="/">
+ <div className="absolute left-0 w-full flex items-center justify-between z-10">
+ <Link className="px-5" href="/home">
<Image
src={Logo}
alt="SuperMemory logo"
- className="hover:brightness-125 duration-200"
+ className="hover:brightness-75 brightness-50 duration-200"
/>
</Link>
- <Tabs
- className="absolute flex flex-col justify-center items-center w-full -z-10 group top-0 transition-transform duration-1000 ease-out"
- defaultValue="account"
- >
- <div className="bg-secondary all-center h-11 rounded-full p-2 min-w-14">
- <button className="p-2 group-hover:hidden transition duration-500 ease-in-out">
- <Image src={AddIcon} alt="Add icon" />
- </button>
-
- <div className="hidden group-hover:flex inset-0 transition-opacity duration-500 ease-in-out">
- <TabsList className="p-2">
- <TabsTrigger value="account">Account</TabsTrigger>
- <TabsTrigger value="password">Password</TabsTrigger>
- </TabsList>
- </div>
- </div>
-
- <div className="bg-secondary all-center rounded-full p-2 mt-4 min-w-14 hidden group-hover:block">
- <TabsContent value="account">
- Make changes to your account here.
- </TabsContent>
- <TabsContent value="password">
- Change your password here.
- </TabsContent>
- </div>
- </Tabs>
+ <DynamicIsland />
- <button className="flex shrink-0 duration-200 items-center gap-2 px-2 py-1.5 rounded-xl hover:bg-secondary">
+ <button className="flex shrink-0 duration-200 items-center gap-2 px-5 py-1.5 rounded-xl hover:bg-secondary">
<Image src={ChatIcon} alt="Chat icon" />
Start new chat
</button>
diff --git a/apps/web/app/(dash)/home/page.tsx b/apps/web/app/(dash)/home/page.tsx
index 7a6bb94f..0c75e457 100644
--- a/apps/web/app/(dash)/home/page.tsx
+++ b/apps/web/app/(dash)/home/page.tsx
@@ -16,7 +16,7 @@ async function Page({
const spaces = await getSpaces();
return (
- <div className="max-w-3xl flex mx-auto w-full flex-col">
+ <div className="max-w-3xl h-full justify-center flex mx-auto w-full flex-col">
{/* all content goes here */}
{/* <div className="">hi {firstTime ? 'first time' : ''}</div> */}
diff --git a/apps/web/app/(dash)/home/queryinput.tsx b/apps/web/app/(dash)/home/queryinput.tsx
index d098fda8..4cb1fdb2 100644
--- a/apps/web/app/(dash)/home/queryinput.tsx
+++ b/apps/web/app/(dash)/home/queryinput.tsx
@@ -48,7 +48,7 @@ function QueryInput({
return (
<div>
- <div className="bg-secondary rounded-t-[24px] w-full mt-40">
+ <div className="bg-secondary rounded-t-[24px]">
{/* input and action button */}
<form action={async () => push(parseQ())} className="flex gap-4 p-3">
<textarea
diff --git a/apps/web/app/(dash)/menu.tsx b/apps/web/app/(dash)/menu.tsx
index 1177bca6..fad4a036 100644
--- a/apps/web/app/(dash)/menu.tsx
+++ b/apps/web/app/(dash)/menu.tsx
@@ -24,7 +24,7 @@ function Menu() {
return (
<div className="absolute h-full p-4 flex items-center top-0 left-0">
<div className="">
- <div className="hover:rounded-2x group inline-flex w-14 text-foreground-menu text-[15px] font-medium flex-col items-start gap-6 overflow-hidden rounded-[28px] bg-secondary px-3 py-4 duration-200 hover:w-40">
+ <div className="group inline-flex w-14 text-foreground-menu text-[15px] font-medium flex-col items-start gap-6 overflow-hidden rounded-[28px] bg-secondary px-3 py-4 duration-200 hover:w-40">
{menuItems.map((item) => (
<div
key={item.url}