mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-05-13 15:31:49 +00:00
i dont even know
This commit is contained in:
commit
222ef82230
11 changed files with 356 additions and 165 deletions
|
|
@ -22,7 +22,7 @@
|
|||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.0",
|
||||
"cmdk": "^1.0.0",
|
||||
"cmdk": "latest",
|
||||
"framer-motion": "^11.0.24",
|
||||
"lucide-react": "^0.338.0",
|
||||
"next": "14.1.0",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { Roboto } from 'next/font/google';
|
||||
import './globals.css';
|
||||
import type { Metadata } from "next";
|
||||
import { Roboto } from "next/font/google";
|
||||
import "./globals.css";
|
||||
|
||||
const roboto = Roboto({ weight: ['300', '400', '500'], subsets: ['latin'] });
|
||||
const roboto = Roboto({ weight: ["300", "400", "500"], subsets: ["latin"] });
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Create Next App',
|
||||
description: 'Generated by create next app',
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
|
@ -15,9 +15,8 @@ export default function RootLayout({
|
|||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<html lang="en" className="dark">
|
||||
<body className={roboto.className}>
|
||||
<div id="d" className="fixed left-0 top-0 h-[5px] w-screen"></div>
|
||||
<div vaul-drawer-wrapper="" className="min-w-screen overflow-x-hidden">
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { Textarea2 } from "./ui/textarea";
|
|||
import { ArrowRight } from "lucide-react";
|
||||
import { MemoryDrawer } from "./MemoryDrawer";
|
||||
import useViewport from "@/hooks/useViewport";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
||||
const [value, setValue] = useState("");
|
||||
|
|
@ -24,10 +25,13 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<main
|
||||
<motion.main
|
||||
data-sidebar-open={sidebarOpen}
|
||||
className="flex h-screen max-h-screen w-full items-end justify-center px-5 pb-[20vh] pt-5 md:items-center md:px-60 md:[&[data-sidebar-open='true']]:px-20"
|
||||
className="flex h-screen max-h-screen w-full flex-col items-end justify-center gap-5 px-5 pb-[20vh] pt-5 transition-[padding] delay-200 duration-200 md:items-center md:px-72 [&[data-sidebar-open='true']]:pl-[calc(2.5rem+30vw)] [&[data-sidebar-open='true']]:pr-10 [&[data-sidebar-open='true']]:delay-0 "
|
||||
>
|
||||
<h1 className="text-rgray-11 text-center text-3xl">
|
||||
Ask your Second brain
|
||||
</h1>
|
||||
<Textarea2
|
||||
ref={textArea}
|
||||
className="h-max max-h-[30em] min-h-[3em] resize-y flex-row items-start justify-center overflow-auto py-5 md:h-[20vh] md:resize-none md:flex-col md:items-center md:justify-center md:p-2 md:pb-2 md:pt-2"
|
||||
|
|
@ -51,6 +55,6 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
|||
</div>
|
||||
</Textarea2>
|
||||
{width <= 768 && <MemoryDrawer />}
|
||||
</main>
|
||||
</motion.main>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {
|
|||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { SpaceIcon } from "@/assets/Memories";
|
||||
import { AnimatePresence, LayoutGroup, motion } from "framer-motion";
|
||||
|
||||
const spaces = [
|
||||
{
|
||||
|
|
@ -33,6 +34,118 @@ const spaces = [
|
|||
value: "3",
|
||||
label: "Cool Libraries",
|
||||
},
|
||||
{
|
||||
value: "4",
|
||||
label: "Cool People",
|
||||
},
|
||||
{
|
||||
value: "5",
|
||||
label: "Cool Projects",
|
||||
},
|
||||
{
|
||||
value: "6",
|
||||
label: "Cool Tools",
|
||||
},
|
||||
{
|
||||
value: "7",
|
||||
label: "Cool Websites",
|
||||
},
|
||||
{
|
||||
value: "8",
|
||||
label: "Cool Books",
|
||||
},
|
||||
{
|
||||
value: "9",
|
||||
label: "Cool Videos",
|
||||
},
|
||||
{
|
||||
value: "10",
|
||||
label: "Cool Podcasts",
|
||||
},
|
||||
{
|
||||
value: "11",
|
||||
label: "Cool Articles",
|
||||
},
|
||||
{
|
||||
value: "12",
|
||||
label: "Cool Blogs",
|
||||
},
|
||||
{
|
||||
value: "13",
|
||||
label: "Cool News",
|
||||
},
|
||||
{
|
||||
value: "14",
|
||||
label: "Cool Forums",
|
||||
},
|
||||
{
|
||||
value: "15",
|
||||
label: "Cool Communities",
|
||||
},
|
||||
{
|
||||
value: "16",
|
||||
label: "Cool Events",
|
||||
},
|
||||
{
|
||||
value: "17",
|
||||
label: "Cool Jobs",
|
||||
},
|
||||
{
|
||||
value: "18",
|
||||
label: "Cool Companies",
|
||||
},
|
||||
{
|
||||
value: "19",
|
||||
label: "Cool Startups",
|
||||
},
|
||||
{
|
||||
value: "20",
|
||||
label: "Cool Investors",
|
||||
},
|
||||
{
|
||||
value: "21",
|
||||
label: "Cool Funds",
|
||||
},
|
||||
{
|
||||
value: "22",
|
||||
label: "Cool Incubators",
|
||||
},
|
||||
{
|
||||
value: "23",
|
||||
label: "Cool Accelerators",
|
||||
},
|
||||
{
|
||||
value: "24",
|
||||
label: "Cool Hackathons",
|
||||
},
|
||||
{
|
||||
value: "25",
|
||||
label: "Cool Conferences",
|
||||
},
|
||||
{
|
||||
value: "26",
|
||||
label: "Cool Workshops",
|
||||
},
|
||||
{
|
||||
value: "27",
|
||||
label: "Cool Seminars",
|
||||
},
|
||||
{
|
||||
value: "28",
|
||||
label: "Cool Webinars",
|
||||
},
|
||||
{
|
||||
value: "29",
|
||||
label: "Cool Courses",
|
||||
},
|
||||
{
|
||||
value: "30",
|
||||
label: "Cool Bootcamps",
|
||||
},
|
||||
{
|
||||
value: "31",
|
||||
label: "Cool Certifications",
|
||||
},
|
||||
];
|
||||
|
||||
export interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
|
||||
|
|
@ -41,69 +154,96 @@ export function FilterCombobox({ className, ...props }: Props) {
|
|||
const [open, setOpen] = React.useState(false);
|
||||
const [values, setValues] = React.useState<string[]>([]);
|
||||
|
||||
const sortedSpaces = spaces.sort(({ value: a }, { value: b }) =>
|
||||
values.includes(a) && !values.includes(b)
|
||||
? -1
|
||||
: values.includes(b) && !values.includes(a)
|
||||
? 1
|
||||
: 0,
|
||||
);
|
||||
|
||||
console.log(sortedSpaces, values);
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
data-state-on={open}
|
||||
className={cn(
|
||||
"text-rgray-11/70 on:bg-rgray-3 focus-visible:ring-rgray-8 hover:bg-rgray-3 relative flex items-center justify-center gap-1 rounded-md px-3 py-1.5 ring-2 ring-transparent focus-visible:outline-none",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<SpaceIcon className="mr-1 h-5 w-5" />
|
||||
Filter
|
||||
<ChevronsUpDown className="h-4 w-4" />
|
||||
<div
|
||||
data-state-on={values.length > 0}
|
||||
className="on:flex text-rgray-11 border-rgray-6 bg-rgray-2 absolute left-0 top-0 hidden aspect-[1] h-4 w-4 -translate-x-1/3 -translate-y-1/3 items-center justify-center rounded-full border text-center text-[9px]"
|
||||
>
|
||||
{values.length}
|
||||
</div>
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[200px] p-0">
|
||||
<Command
|
||||
filter={(val, search) =>
|
||||
spaces
|
||||
.find((s) => s.value === val)
|
||||
?.label.toLowerCase()
|
||||
.includes(search.toLowerCase().trim())
|
||||
? 1
|
||||
: 0
|
||||
}
|
||||
>
|
||||
<CommandInput placeholder="Filter spaces..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>Nothing found</CommandEmpty>
|
||||
{/* bug: doesn't work on clicking with mouse only keyboard, weird */}
|
||||
<CommandGroup>
|
||||
{spaces.map((space) => (
|
||||
<CommandItem
|
||||
key={space.value}
|
||||
value={space.value}
|
||||
onSelect={(val) => {
|
||||
setValues((prev) =>
|
||||
prev.includes(val)
|
||||
? prev.filter((v) => v !== val)
|
||||
: [...prev, val],
|
||||
);
|
||||
}}
|
||||
>
|
||||
<SpaceIcon className="mr-2 h-4 w-4" />
|
||||
{space.label}
|
||||
{values.includes(space.value)}
|
||||
<Check
|
||||
data-state-on={values.includes(space.value)}
|
||||
className={cn("on:opacity-100 ml-auto h-4 w-4 opacity-0")}
|
||||
/>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<AnimatePresence mode="popLayout">
|
||||
<LayoutGroup>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
data-state-on={open}
|
||||
className={cn(
|
||||
"text-rgray-11/70 on:bg-rgray-3 focus-visible:ring-rgray-8 hover:bg-rgray-3 relative flex items-center justify-center gap-1 rounded-md px-3 py-1.5 ring-2 ring-transparent focus-visible:outline-none",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<SpaceIcon className="mr-1 h-5 w-5" />
|
||||
Filter
|
||||
<ChevronsUpDown className="h-4 w-4" />
|
||||
<div
|
||||
data-state-on={values.length > 0}
|
||||
className="on:flex text-rgray-11 border-rgray-6 bg-rgray-2 absolute left-0 top-0 hidden aspect-[1] h-4 w-4 -translate-x-1/3 -translate-y-1/3 items-center justify-center rounded-full border text-center text-[9px]"
|
||||
>
|
||||
{values.length}
|
||||
</div>
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[200px] p-0">
|
||||
<Command
|
||||
filter={(val, search) =>
|
||||
spaces
|
||||
.find((s) => s.value === val)
|
||||
?.label.toLowerCase()
|
||||
.includes(search.toLowerCase().trim())
|
||||
? 1
|
||||
: 0
|
||||
}
|
||||
>
|
||||
<CommandInput placeholder="Filter spaces..." />
|
||||
<CommandList asChild>
|
||||
<motion.div layoutScroll>
|
||||
<CommandEmpty>Nothing found</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{sortedSpaces.map((space) => (
|
||||
<CommandItem
|
||||
key={space.value}
|
||||
value={space.value}
|
||||
onSelect={(val) => {
|
||||
setValues((prev) =>
|
||||
prev.includes(val)
|
||||
? prev.filter((v) => v !== val)
|
||||
: [...prev, val],
|
||||
);
|
||||
}}
|
||||
asChild
|
||||
>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1, transition: { delay: 0.05 } }}
|
||||
transition={{ duration: 0.15 }}
|
||||
layout
|
||||
layoutId={`space-combobox-${space.value}`}
|
||||
className="text-rgray-11"
|
||||
>
|
||||
<SpaceIcon className="mr-2 h-4 w-4" />
|
||||
{space.label}
|
||||
{values.includes(space.value)}
|
||||
<Check
|
||||
data-state-on={values.includes(space.value)}
|
||||
className={cn(
|
||||
"on:opacity-100 ml-auto h-4 w-4 opacity-0",
|
||||
)}
|
||||
/>
|
||||
</motion.div>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</motion.div>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</LayoutGroup>
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,98 +2,98 @@ import {
|
|||
MemoryWithImage,
|
||||
MemoryWithImages3,
|
||||
MemoryWithImages2,
|
||||
} from '@/assets/MemoryWithImages';
|
||||
import { type Space } from '../../../types/memory';
|
||||
import { InputWithIcon } from '../ui/input';
|
||||
import { Search } from 'lucide-react';
|
||||
} from "@/assets/MemoryWithImages";
|
||||
import { type Space } from "../../../types/memory";
|
||||
import { InputWithIcon } from "../ui/input";
|
||||
import { MoreHorizontal, Search } from "lucide-react";
|
||||
|
||||
export function MemoriesBar() {
|
||||
const spaces: Space[] = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Cool Tech',
|
||||
description: 'Really cool mind blowing tech',
|
||||
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',
|
||||
title: "Perplexity",
|
||||
description: "A good ui",
|
||||
content: "",
|
||||
image: "https://perplexity.ai/favicon.ico",
|
||||
url: "https://perplexity.ai",
|
||||
savedAt: new Date(),
|
||||
baseUrl: 'https://perplexity.ai',
|
||||
space: 'Cool tech',
|
||||
baseUrl: "https://perplexity.ai",
|
||||
space: "Cool tech",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Pi.ai',
|
||||
description: 'A good ui',
|
||||
content: '',
|
||||
image: 'https://pi.ai/pi-logo-192.png?v=2',
|
||||
url: 'https://pi.ai',
|
||||
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',
|
||||
space: 'Cool tech',
|
||||
baseUrl: "https://pi.ai",
|
||||
space: "Cool tech",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Visual Studio Code',
|
||||
description: 'A good ui',
|
||||
content: '',
|
||||
image: 'https://code.visualstudio.com/favicon.ico',
|
||||
url: 'https://code.visualstudio.com',
|
||||
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',
|
||||
space: 'Cool tech',
|
||||
baseUrl: "https://code.visualstudio.com",
|
||||
space: "Cool tech",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Cool Courses',
|
||||
description: 'Amazng',
|
||||
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',
|
||||
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',
|
||||
space: 'Cool courses',
|
||||
baseUrl: "https://animations.dev",
|
||||
space: "Cool courses",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Tailwind Course',
|
||||
description: 'A good ui',
|
||||
content: '',
|
||||
title: "Tailwind Course",
|
||||
description: "A good ui",
|
||||
content: "",
|
||||
image:
|
||||
'https://tailwindcss.com/_next/static/media/tailwindcss-mark.3c5441fc7a190fb1800d4a5c7f07ba4b1345a9c8.svg',
|
||||
url: 'https://tailwindcss.com',
|
||||
"https://tailwindcss.com/_next/static/media/tailwindcss-mark.3c5441fc7a190fb1800d4a5c7f07ba4b1345a9c8.svg",
|
||||
url: "https://tailwindcss.com",
|
||||
savedAt: new Date(),
|
||||
baseUrl: 'https://tailwindcss.com',
|
||||
space: 'Cool courses',
|
||||
baseUrl: "https://tailwindcss.com",
|
||||
space: "Cool courses",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Cool Libraries',
|
||||
description: 'Really cool mind blowing tech',
|
||||
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',
|
||||
title: "Perplexity",
|
||||
description: "A good ui",
|
||||
content: "",
|
||||
image: "https://yashverma.me/logo.jpg",
|
||||
url: "https://perplexity.ai",
|
||||
savedAt: new Date(),
|
||||
baseUrl: 'https://perplexity.ai',
|
||||
space: 'Cool libraries',
|
||||
baseUrl: "https://perplexity.ai",
|
||||
space: "Cool libraries",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -121,7 +121,16 @@ export function MemoriesBar() {
|
|||
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">
|
||||
<div className="hover:bg-rgray-2 has-[[data-space-text]:focus-visible]:bg-rgray-2 has-[[data-space-text]:focus-visible]:ring-rgray-7 [&:has-[[data-space-text]:focus-visible]>[data-more-button]]:opacity-100 relative flex flex-col-reverse items-center justify-center rounded-md p-2 pb-4 text-center font-normal ring-transparent transition has-[[data-space-text]:focus-visible]:outline-none has-[[data-space-text]:focus-visible]:ring-2 [&:hover>[data-more-button]]:opacity-100">
|
||||
<button data-space-text className="focus-visible:outline-none">
|
||||
{title}
|
||||
</button>
|
||||
<button
|
||||
data-more-button
|
||||
className="hover:bg-rgray-3 focus-visible:bg-rgray-3 focus-visible:ring-rgray-7 absolute right-2 top-2 rounded-md p-1 opacity-0 ring-transparent transition focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2"
|
||||
>
|
||||
<MoreHorizontal className="text-rgray-11 h-5 w-5" />
|
||||
</button>
|
||||
{content.length > 2 ? (
|
||||
<MemoryWithImages3
|
||||
className="h-24 w-24"
|
||||
|
|
@ -141,7 +150,6 @@ export function Space({ title, description, content, id }: Space) {
|
|||
images={content.map((c) => c.image).reverse() as string[]}
|
||||
/>
|
||||
)}
|
||||
<span>{title}</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { MemoryIcon } from "../../assets/Memories";
|
|||
import { Trash2, User2 } from "lucide-react";
|
||||
import React, { useState } from "react";
|
||||
import { MemoriesBar } from "./MemoriesBar";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
|
||||
export type MenuItem = {
|
||||
icon: React.ReactNode | React.ReactNode[];
|
||||
|
|
@ -47,30 +48,34 @@ export default function Sidebar({
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="bg-rgray-2 border-r-rgray-6 hidden h-screen max-h-screen w-max flex-col items-center border-r px-2 py-5 text-sm font-light md:flex">
|
||||
{menuItemsTop.map((item, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
item={item}
|
||||
selectedItem={selectedItem}
|
||||
setSelectedItem={setSelectedItem}
|
||||
/>
|
||||
))}
|
||||
<div className="mt-auto" />
|
||||
{menuItemsBottom.map((item, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
item={item}
|
||||
selectedItem={selectedItem}
|
||||
setSelectedItem={setSelectedItem}
|
||||
/>
|
||||
))}
|
||||
<div className="relative hidden h-screen max-h-screen w-max flex-col items-center text-sm font-light md:flex">
|
||||
<div className="bg-rgray-2 border-r-rgray-6 relative z-[10000] flex h-full w-full flex-col items-center justify-center border-r px-2 py-5 ">
|
||||
{menuItemsTop.map((item, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
item={item}
|
||||
selectedItem={selectedItem}
|
||||
setSelectedItem={setSelectedItem}
|
||||
/>
|
||||
))}
|
||||
<div className="mt-auto" />
|
||||
{menuItemsBottom.map((item, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
item={item}
|
||||
selectedItem={selectedItem}
|
||||
setSelectedItem={setSelectedItem}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<AnimatePresence>
|
||||
{selectedItem && (
|
||||
<SubSidebar>
|
||||
<Subbar />
|
||||
</SubSidebar>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
{selectedItem && (
|
||||
<SubSidebar>
|
||||
<Subbar />
|
||||
</SubSidebar>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -87,7 +92,7 @@ const MenuItem = ({
|
|||
<button
|
||||
data-state-on={selectedItem === label}
|
||||
onClick={() => setSelectedItem((prev) => (prev === label ? null : label))}
|
||||
className="on:opacity-100 on:bg-rgray-4 focus-visible:ring-rgray-7 flex w-full flex-col items-center justify-center rounded-md px-3 py-3 opacity-80 ring-2 ring-transparent transition hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-none"
|
||||
className="on:opacity-100 on:bg-rgray-4 focus-visible:ring-rgray-7 relative z-[100] flex w-full flex-col items-center justify-center rounded-md px-3 py-3 opacity-80 ring-2 ring-transparent transition hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-none"
|
||||
>
|
||||
{icon}
|
||||
<span className="">{label}</span>
|
||||
|
|
@ -96,8 +101,30 @@ const MenuItem = ({
|
|||
|
||||
export function SubSidebar({ children }: { children?: React.ReactNode }) {
|
||||
return (
|
||||
<div className="bg-rgray-3 border-r-rgray-6 hidden h-screen w-[50vw] flex-col items-center border-r font-light md:flex">
|
||||
{children}
|
||||
</div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: "-100%" }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
x: "-100%",
|
||||
transition: { delay: 0.2 },
|
||||
}}
|
||||
transition={{
|
||||
duration: 0.2,
|
||||
}}
|
||||
className="bg-rgray-3 border-r-rgray-6 absolute left-[100%] top-0 z-[10] hidden h-screen w-[30vw] items-start justify-center overflow-x-hidden border-r font-light md:flex"
|
||||
>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0, transition: { delay: 0 } }}
|
||||
transition={{
|
||||
delay: 0.2,
|
||||
}}
|
||||
className="z-[10] flex h-full w-full min-w-full flex-col items-center opacity-0"
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const Command = React.forwardRef<
|
|||
<CommandPrimitive
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-rgray-3 text-rgray-11 flex h-full w-full flex-col overflow-hidden rounded-md",
|
||||
"bg-rgray-3 text-rgray-11 flex h-full w-full flex-col overflow-hidden rounded-md focus-visible:outline-none [&>[cmdk-list-sizer]]:max-h-[250px] [&>[cmdk-list-sizer]]:overflow-y-scroll",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -120,7 +120,7 @@ const CommandItem = React.forwardRef<
|
|||
<CommandPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"aria-selected:bg-rgray-5 aria-selected:text-rgray-12 relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
"aria-selected:bg-rgray-5 aria-selected:text-rgray-12 relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm opacity-70 outline-none data-[disabled='true']:pointer-events-none data-[disabled='true']:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"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 ",
|
||||
"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 font-normal 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-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 ",
|
||||
"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 font-normal transition focus-within:outline-none focus-within:ring-2 ",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
|
|
@ -39,7 +39,7 @@ const InputWithIcon = React.forwardRef<HTMLInputElement, InputWithIconProps>(
|
|||
<input
|
||||
type={type}
|
||||
className={
|
||||
"placeholder:text-rgray-11/50 w-full bg-transparent file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
||||
"placeholder:text-rgray-11/50 w-full bg-transparent font-normal file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
||||
}
|
||||
ref={ref}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -32,14 +32,14 @@ const Textarea2 = React.forwardRef<HTMLTextAreaElement, Textarea2Props>(
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"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",
|
||||
"border-rgray-6 text-rgray-11 has-[textarea:focus-visible]: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 has-[textarea:focus-visible]:ring-2",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<textarea
|
||||
className={cn(
|
||||
"placeholder:text-rgray-11/70 h-full w-full resize-none bg-transparent focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"text-rgray-11 h-full w-full resize-none bg-transparent placeholder:text-white/50 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
textAreaClassName,
|
||||
)}
|
||||
ref={ref}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { useState, useEffect } from "react";
|
||||
|
||||
function getViewport() {
|
||||
const { innerWidth: width, innerHeight: height } = window;
|
||||
const { innerWidth: width, innerHeight: height } = window ?? {
|
||||
innerWidth: 0,
|
||||
innerHeight: 0,
|
||||
};
|
||||
return {
|
||||
width,
|
||||
height,
|
||||
|
|
|
|||
|
|
@ -30,10 +30,19 @@ const config: Config = {
|
|||
transformOrigin: "var(--radix-popover-content-transform-origin)",
|
||||
},
|
||||
},
|
||||
"fade-in": {
|
||||
"0%": {
|
||||
opacity: "0",
|
||||
},
|
||||
"100%": {
|
||||
opacity: "1",
|
||||
},
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
"scale-in": "scale-in 0.2s cubic-bezier(0.16, 1, 0.3, 1)",
|
||||
"scale-out": "scale-out 0.2s cubic-bezier(0.16, 1, 0.3, 1)",
|
||||
"fade-in": "fade-in 0.2s 0.5s forwards cubic-bezier(0.16, 1, 0.3, 1)",
|
||||
},
|
||||
backgroundImage: {
|
||||
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
||||
|
|
@ -58,6 +67,7 @@ const config: Config = {
|
|||
},
|
||||
},
|
||||
},
|
||||
safelist: ["text-rgray-11/70"],
|
||||
darkMode: "class",
|
||||
plugins: [
|
||||
require("tailwindcss-animate"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue