mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
add profile and fix drawer scroll
This commit is contained in:
parent
496849c9cf
commit
0ce7c916ff
9 changed files with 241 additions and 63 deletions
|
|
@ -69,39 +69,43 @@ export async function POST(req: NextRequest) {
|
|||
});
|
||||
}
|
||||
|
||||
const resp = await fetch(
|
||||
`https://cf-ai-backend.dhravya.workers.dev/chat?q=${query}&user=${session.user.email ?? session.user.name}&sourcesOnly=${sourcesOnly}&spaces=${spaces}`,
|
||||
{
|
||||
headers: {
|
||||
"X-Custom-Auth-Key": env.BACKEND_SECURITY_KEY,
|
||||
},
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
chatHistory: chatHistory.chatHistory ?? [],
|
||||
}),
|
||||
},
|
||||
);
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`https://cf-ai-backend.dhravya.workers.dev/chat?q=${query}&user=${session.user.email ?? session.user.name}&sourcesOnly=${sourcesOnly}&spaces=${spaces}`,
|
||||
{
|
||||
headers: {
|
||||
"X-Custom-Auth-Key": env.BACKEND_SECURITY_KEY,
|
||||
},
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
chatHistory: chatHistory.chatHistory ?? [],
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
console.log("sourcesOnly", sourcesOnly);
|
||||
console.log("sourcesOnly", sourcesOnly);
|
||||
|
||||
if (sourcesOnly == "true") {
|
||||
const data = await resp.json();
|
||||
console.log("data", data);
|
||||
return new Response(JSON.stringify(data), { status: 200 });
|
||||
}
|
||||
if (sourcesOnly == "true") {
|
||||
const data = await resp.json();
|
||||
console.log("data", data);
|
||||
return new Response(JSON.stringify(data), { status: 200 });
|
||||
}
|
||||
|
||||
if (resp.status !== 200 || !resp.ok) {
|
||||
const errorData = await resp.json();
|
||||
console.log(errorData);
|
||||
return new Response(
|
||||
JSON.stringify({ message: "Error in CF function", error: errorData }),
|
||||
{ status: resp.status },
|
||||
);
|
||||
}
|
||||
if (resp.status !== 200 || !resp.ok) {
|
||||
const errorData = await resp.json();
|
||||
console.log(errorData);
|
||||
return new Response(
|
||||
JSON.stringify({ message: "Error in CF function", error: errorData }),
|
||||
{ status: resp.status },
|
||||
);
|
||||
}
|
||||
|
||||
// Stream the response back to the client
|
||||
const { readable, writable } = new TransformStream();
|
||||
resp && resp.body!.pipeTo(writable);
|
||||
// Stream the response back to the client
|
||||
const { readable, writable } = new TransformStream();
|
||||
resp && resp.body!.pipeTo(writable);
|
||||
|
||||
return new Response(readable, { status: 200 });
|
||||
} catch {
|
||||
}
|
||||
|
||||
return new Response(readable, { status: 200 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { db } from "@/server/db";
|
||||
import { and, eq, sql } from "drizzle-orm";
|
||||
import { and, eq, ne, sql } from "drizzle-orm";
|
||||
import { sessions, storedContent, users } from "@/server/db/schema";
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ export async function GET(req: NextRequest) {
|
|||
.where(
|
||||
and(
|
||||
eq(storedContent.user, session.user.id),
|
||||
eq(storedContent.type, "page"),
|
||||
ne(storedContent.type, "twitter-bookmark"),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,17 @@ body {
|
|||
padding-bottom: 15dvh;
|
||||
}
|
||||
|
||||
.bottom-padding {
|
||||
bottom: 20vh;
|
||||
bottom: 20dvh;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.bottom-padding {
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-answer code {
|
||||
@apply bg-rgray-3 text-wrap rounded-md border border-rgray-5 p-1 text-sm text-rgray-11;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import type { Metadata } from "next";
|
|||
import { Roboto, Inter } from "next/font/google";
|
||||
import "./globals.css";
|
||||
|
||||
const roboto = Roboto({ weight: ["300", "400", "500"], subsets: ["latin"] });
|
||||
const inter = Inter({ weight: ["300", "400", "500"], subsets: ["latin"] });
|
||||
|
||||
export const metadata: Metadata = {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
|||
|
||||
const [selectedSpaces, setSelectedSpaces] = useState<number[]>([]);
|
||||
|
||||
const [isStreaming, setIsStreaming] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const search = searchParams.get("q");
|
||||
if (search && search.trim().length > 0) {
|
||||
|
|
@ -241,6 +243,8 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
|||
return;
|
||||
}
|
||||
|
||||
setIsStreaming(true)
|
||||
|
||||
if (response.body) {
|
||||
let reader = response.body?.getReader();
|
||||
let decoder = new TextDecoder("utf-8");
|
||||
|
|
@ -259,14 +263,24 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
|||
|
||||
return reader?.read().then(processText);
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const onSend = async () => {
|
||||
const onSend = () => {
|
||||
if (value.trim().length < 1) return
|
||||
setLayout("chat");
|
||||
await getSearchResults();
|
||||
getSearchResults();
|
||||
};
|
||||
|
||||
function onValueChange(e: React.ChangeEvent<HTMLTextAreaElement>) {
|
||||
const value = e.target.value;
|
||||
setValue(value);
|
||||
const lines = countLines(e.target);
|
||||
e.target.rows = Math.min(5, lines);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<AnimatePresence mode="wait">
|
||||
|
|
@ -284,6 +298,7 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
|||
/>
|
||||
) : (
|
||||
<main
|
||||
key='intial'
|
||||
data-sidebar-open={sidebarOpen}
|
||||
ref={main}
|
||||
className={cn(
|
||||
|
|
@ -302,7 +317,57 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
|||
Ask your second brain
|
||||
</h1>
|
||||
|
||||
<Textarea2
|
||||
<FilterSpaces
|
||||
name={"Filter"}
|
||||
onClose={() => {
|
||||
textArea.current?.querySelector("textarea")?.focus();
|
||||
}}
|
||||
side="top"
|
||||
align="start"
|
||||
className="bg-[#252525] mr-auto md:hidden"
|
||||
selectedSpaces={selectedSpaces}
|
||||
setSelectedSpaces={setSelectedSpaces}
|
||||
/>
|
||||
<Textarea2
|
||||
ref={textArea}
|
||||
className="bg-rgray-2 md:hidden h-auto w-full flex-row items-start justify-center overflow-auto px-3 md:items-center md:justify-center"
|
||||
textAreaProps={{
|
||||
placeholder: "Ask your SuperMemory...",
|
||||
className:
|
||||
"overflow-auto h-auto p-3 md:resize-none text-lg w-auto resize-y text-rgray-11 w-full",
|
||||
value,
|
||||
rows: 1,
|
||||
autoFocus: true,
|
||||
onChange: onValueChange,
|
||||
onKeyDown: (e) => {
|
||||
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
onSend();
|
||||
}
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div className="md:hidden text-rgray-11/70 ml-auto mt-auto flex h-full w-min items-center justify-center pb-3 pr-2">
|
||||
|
||||
<FilterSpaces
|
||||
name={"Filter"}
|
||||
onClose={() => {
|
||||
textArea.current?.querySelector("textarea")?.focus();
|
||||
}}
|
||||
className="hidden md:flex"
|
||||
selectedSpaces={selectedSpaces}
|
||||
setSelectedSpaces={setSelectedSpaces}
|
||||
/>
|
||||
<button
|
||||
onClick={onSend}
|
||||
disabled={value.trim().length < 1}
|
||||
className="text-rgray-11/70 bg-rgray-3 focus-visible:ring-rgray-8 hover:bg-rgray-4 mt-auto flex items-center justify-center rounded-full p-2 ring-2 ring-transparent transition-[filter] focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
||||
>
|
||||
<ArrowUp className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
</Textarea2>
|
||||
|
||||
<Textarea2
|
||||
ref={textArea}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
|
|
@ -325,6 +390,7 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
|||
}
|
||||
},
|
||||
}}
|
||||
className="hidden md:flex"
|
||||
>
|
||||
<div className="text-rgray-11/70 flex h-full w-fit items-center justify-center pl-0 md:w-full md:p-2">
|
||||
<FilterSpaces
|
||||
|
|
@ -344,10 +410,10 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) {
|
|||
<ArrowRight className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
</Textarea2>
|
||||
{width <= 768 && <MemoryDrawer hide={hide} />}
|
||||
</main>
|
||||
</Textarea2>
|
||||
</main>
|
||||
)}
|
||||
{width <= 768 && <MemoryDrawer hide={hide} />}
|
||||
</AnimatePresence>
|
||||
</>
|
||||
);
|
||||
|
|
@ -388,7 +454,7 @@ export function Chat({
|
|||
"sidebar relative flex w-full flex-col items-end gap-5 px-5 pt-5 transition-[padding-left,padding-top,padding-right] delay-200 duration-200 md:items-center md:gap-10 md:px-72 [&[data-sidebar-open='true']]:pr-10 [&[data-sidebar-open='true']]:delay-0 md:[&[data-sidebar-open='true']]:pl-[calc(2.5rem+30vw)]",
|
||||
)}
|
||||
>
|
||||
<div className="scrollbar-none h-screen w-full overflow-y-auto px-2 md:px-5">
|
||||
<div className="scrollbar-none h-[70vh] md:h-screen w-full overflow-y-auto px-2 md:px-5">
|
||||
{chatHistory.map((msg, i) => (
|
||||
<ChatMessage index={i} key={i} isLast={i === chatHistory.length - 1}>
|
||||
<ChatQuestion>{msg.question}</ChatQuestion>
|
||||
|
|
@ -404,12 +470,12 @@ export function Chat({
|
|||
</ChatMessage>
|
||||
))}
|
||||
</div>
|
||||
<div className="from-rgray-2 via-rgray-2 to-rgray-2/0 absolute bottom-0 left-0 h-[30%] w-full bg-gradient-to-t" />
|
||||
<div className="from-rgray-2 via-rgray-2 to-rgray-2/0 absolute bottom-0 left-0 w-full bg-gradient-to-t" />
|
||||
<div
|
||||
data-sidebar-open={sidebarOpen}
|
||||
className="absolute flex w-full items-center justify-center"
|
||||
>
|
||||
<div className="animate-from-top fixed bottom-10 left-1/2 md:left-[auto] md:translate-x-0 -translate-x-1/2 mt-auto flex w-[90%] md:w-[50%] flex-col items-center justify-center gap-2">
|
||||
<div className="animate-from-top fixed bottom-padding md:bottom-10 left-1/2 md:left-[auto] md:translate-x-0 -translate-x-1/2 mt-auto flex w-[90%] md:w-[50%] flex-col items-center justify-center gap-2">
|
||||
<FilterSpaces
|
||||
name={"Filter"}
|
||||
onClose={() => {
|
||||
|
|
|
|||
|
|
@ -32,16 +32,18 @@ export function MemoryDrawer({ className, hide = false, ...props }: Props) {
|
|||
)}
|
||||
handle={false}
|
||||
>
|
||||
<button
|
||||
onClick={() =>
|
||||
setActiveSnapPoint((prev) => (prev === 0.9 ? 0.1 : 0.9))
|
||||
}
|
||||
className="bg-rgray-4 border-rgray-6 text-rgray-11 absolute left-1/2 top-0 flex w-fit -translate-x-1/2 -translate-y-1/2 items-center justify-center gap-2 rounded-md border px-3 py-2"
|
||||
>
|
||||
<MemoryIcon className="h-7 w-7" />
|
||||
Memories
|
||||
</button>
|
||||
<MemoriesBar />
|
||||
<button
|
||||
onClick={() =>
|
||||
setActiveSnapPoint((prev) => (prev === 0.9 ? 0.1 : 0.9))
|
||||
}
|
||||
className="bg-rgray-4 border-rgray-6 text-rgray-11 absolute left-1/2 top-0 flex w-fit -translate-x-1/2 -translate-y-1/2 items-center justify-center gap-2 rounded-md border px-3 py-2"
|
||||
>
|
||||
<MemoryIcon className="h-7 w-7" />
|
||||
Memories
|
||||
</button>
|
||||
<div className="w-full h-full overflow-y-auto">
|
||||
<MemoriesBar isOpen={true} />
|
||||
</div>
|
||||
</DrawerContent>
|
||||
<DrawerOverlay className="relative bg-transparent" />
|
||||
</Drawer>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export function AddMemoryPage({ closeDialog, defaultSpaces, onAdd }: { closeDial
|
|||
const [selectedSpacesId, setSelectedSpacesId] = useState<number[]>(defaultSpaces ?? []);
|
||||
|
||||
return (
|
||||
<div className="md:w-[40vw]">
|
||||
<div className="max-w-[80vw] w-[80vw] md:w-[40vw]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add a web page to memory</DialogTitle>
|
||||
<DialogDescription>
|
||||
|
|
@ -133,7 +133,7 @@ export function NoteAddPage({ closeDialog, defaultSpaces, onAdd }: { closeDialog
|
|||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="w-[80vw] md:w-auto">
|
||||
<Input
|
||||
ref={inputRef}
|
||||
data-error="false"
|
||||
|
|
@ -152,7 +152,7 @@ export function NoteAddPage({ closeDialog, defaultSpaces, onAdd }: { closeDialog
|
|||
setContent(editor.storage.markdown.getMarkdown());
|
||||
}}
|
||||
extensions={[Markdown]}
|
||||
className="novel-editor bg-rgray-4 border-rgray-7 dark mt-5 max-h-[60vh] min-h-[40vh] w-[50vw] overflow-y-auto rounded-lg border [&>div>div]:p-5"
|
||||
className="novel-editor w-full bg-rgray-4 border-rgray-7 dark mt-5 max-h-[60vh] min-h-[40vh] md:w-[50vw] overflow-y-auto rounded-lg border [&>div>div]:p-5"
|
||||
/>
|
||||
<DialogFooter>
|
||||
<FilterSpaces
|
||||
|
|
@ -243,7 +243,7 @@ export function SpaceAddPage({ closeDialog, onAdd }: { closeDialog: () => void,
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="md:w-[40vw]">
|
||||
<div className="w-[80vw] md:w-[40vw]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add a space</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
|
@ -376,7 +376,7 @@ export function AddExistingMemoryToSpace({
|
|||
const [selected, setSelected] = useState<StoredContent[]>([]);
|
||||
|
||||
return (
|
||||
<div className="md:w-[40vw]">
|
||||
<div className="w-[80vw] md:w-[40vw]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add an existing memory to {space.title}</DialogTitle>
|
||||
<DialogDescription>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
"use client";
|
||||
import { MemoryIcon } from "../../assets/Memories";
|
||||
import { Trash2, User2 } from "lucide-react";
|
||||
import { Box, LogOut, Trash2, User2 } from "lucide-react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { MemoriesBar } from "./MemoriesBar";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { Bin } from "@/assets/Bin";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@radix-ui/react-avatar";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { signOut, useSession } from "next-auth/react";
|
||||
import MessagePoster from "@/app/MessagePoster";
|
||||
|
||||
export type MenuItem = {
|
||||
|
|
@ -61,6 +61,7 @@ export default function Sidebar({
|
|||
</div>
|
||||
),
|
||||
label: "Profile",
|
||||
content: <ProfileTab open={selectedItem !== null} />
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -88,6 +89,7 @@ export default function Sidebar({
|
|||
setSelectedItem={setSelectedItem}
|
||||
/>
|
||||
<div className="mt-auto" />
|
||||
{/*
|
||||
<MenuItem
|
||||
item={{
|
||||
label: "Trash",
|
||||
|
|
@ -97,6 +99,7 @@ export default function Sidebar({
|
|||
id="trash-button"
|
||||
setSelectedItem={setSelectedItem}
|
||||
/>
|
||||
*/}
|
||||
<MenuItem
|
||||
item={{
|
||||
label: "Profile",
|
||||
|
|
@ -118,11 +121,12 @@ export default function Sidebar({
|
|||
</Avatar>
|
||||
</div>
|
||||
),
|
||||
content: <ProfileTab open={selectedItem !== null} />
|
||||
}}
|
||||
selectedItem={selectedItem}
|
||||
setSelectedItem={setSelectedItem}
|
||||
/>
|
||||
<MessagePoster jwt={jwt} />
|
||||
{/* <MessagePoster jwt={jwt} /> */}
|
||||
</div>
|
||||
<AnimatePresence>
|
||||
{selectedItem && <SubSidebar>{Subbar}</SubSidebar>}
|
||||
|
|
@ -184,3 +188,95 @@ export function SubSidebar({ children }: { children?: React.ReactNode }) {
|
|||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ProfileTab({ open }: { open: boolean }) {
|
||||
|
||||
const { data: session } = useSession()
|
||||
|
||||
const [tweetStat, setTweetStat] = useState<[number, number] | null>();
|
||||
const [memoryStat, setMemoryStat] = useState<[number, number] | null>();
|
||||
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
fetch("/api/getCount").then(async resp => {
|
||||
const data = await resp.json() as any;
|
||||
setTweetStat([data.tweetsCount, data.tweetsLimit])
|
||||
setMemoryStat([data.pageCount, data.pageLimit])
|
||||
setLoading(false)
|
||||
})
|
||||
}, [open])
|
||||
|
||||
return (
|
||||
<div className="text-rgray-11 h-full flex w-full font-normal flex-col items-start py-8 text-left">
|
||||
<div className="w-full px-8">
|
||||
<h1 className="w-full text-2xl font-medium">Profile</h1>
|
||||
<div className="w-full mt-5 grid grid-cols-3">
|
||||
<img
|
||||
className="rounded-full"
|
||||
src={session?.user?.image ?? "/icons/white_without_bg.png"}
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).src = "/icons/white_without_bg.png"
|
||||
}}
|
||||
/>
|
||||
<div className="col-span-2 flex flex-col justify-center items-start">
|
||||
<h1 className="text-xl font-medium">{session?.user?.name}</h1>
|
||||
<span>
|
||||
{session?.user?.email}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => signOut()}
|
||||
className="flex justify-center mt-auto gap-2 items-center bg-rgray-4 hover:bg-rgray-5 focus-visible:bg-rgray-5 focus-visible:ring-rgray-7 relative rounded-md px-4 py-2 ring-transparent transition focus-visible:outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-70"
|
||||
>
|
||||
<LogOut className="w-4 h-4" />
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full mt-auto pt-8 px-8 border-t border-rgray-5">
|
||||
<h1 className="w-full text-xl flex items-center gap-2">
|
||||
<Box className="w-6 h-6" />
|
||||
Storage
|
||||
</h1>
|
||||
{loading ? (
|
||||
<div className="flex w-full my-5 gap-5 flex-col justify-center items-center">
|
||||
<div className="bg-rgray-5 h-6 w-full animate-pulse rounded-md text-lg"></div>
|
||||
<div className="bg-rgray-5 h-6 w-full animate-pulse rounded-md text-lg"></div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="my-5">
|
||||
<h2 className="w-full text-md flex justify-between items-center">
|
||||
Memories
|
||||
<div className="flex rounded-md bg-rgray-4 px-2 py-2 text-white/50 text-xs">
|
||||
{memoryStat?.join("/")}
|
||||
</div>
|
||||
</h2>
|
||||
<div className="rounded-full overflow-hidden w-full h-5 bg-rgray-2 mt-2">
|
||||
<div style={{
|
||||
width: `${((memoryStat?.[0] ?? 0) / (memoryStat?.[1] ?? 100))*100}%`,
|
||||
minWidth: memoryStat?.[0] ?? 0 > 0 ? '5%' : '0%'
|
||||
}} className="rounded-full h-full bg-rgray-5" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="my-5">
|
||||
<h2 className="w-full text-md flex justify-between items-center">
|
||||
Tweets
|
||||
<div className="flex rounded-md bg-rgray-4 px-2 py-2 text-white/50 text-xs">
|
||||
{tweetStat?.join("/")}
|
||||
</div>
|
||||
</h2>
|
||||
<div className="rounded-full overflow-hidden w-full h-5 bg-rgray-2 mt-2">
|
||||
<div style={{
|
||||
width: `${((tweetStat?.[0] ?? 0) / (tweetStat?.[1] ?? 100))*100}%` ,
|
||||
minWidth: tweetStat?.[0] ?? 0 > 0 ? '5%' : '0%'
|
||||
}} className="rounded-full h-full bg-rgray-5" />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const DialogContent = React.forwardRef<
|
|||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] border-rgray-6 bg-rgray-3 fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] border p-6 shadow-lg duration-200 sm:rounded-lg",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] border-rgray-6 bg-rgray-3 fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] border p-6 shadow-lg duration-200 rounded-lg",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -59,7 +59,7 @@ const DialogHeader = ({
|
|||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-1.5 text-center sm:text-left",
|
||||
"flex flex-col space-y-1.5 text-left",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -73,7 +73,7 @@ const DialogFooter = ({
|
|||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"mt-5 flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||
"mt-5 flex flex-row sm:flex-row sm:justify-end sm:space-x-2",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue