aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorAman pandit <[email protected]>2025-12-08 11:01:30 +0530
committerGitHub <[email protected]>2025-12-07 21:31:30 -0800
commit08267ffa218fdc77e3b10920e5c40fec99e9d325 (patch)
treef05802225f42091fcfa9b5e3671a04714b806543 /apps
parentadd(docs): connections configure, fetch resources (#611) (diff)
downloadsupermemory-08267ffa218fdc77e3b10920e5c40fec99e9d325.tar.xz
supermemory-08267ffa218fdc77e3b10920e5c40fec99e9d325.zip
fix: resolve UI accessibility, hydration, and semantic HTML issues (#520)
Co-authored-by: Mahesh Sanikommu <[email protected]>
Diffstat (limited to 'apps')
-rw-r--r--apps/web/app/global-error.tsx38
-rw-r--r--apps/web/app/layout.tsx5
-rw-r--r--apps/web/components/graph-dialog.tsx3
-rw-r--r--apps/web/components/text-effect.tsx500
-rw-r--r--apps/web/components/views/add-memory/index.tsx21
-rw-r--r--apps/web/components/views/chat/index.tsx67
-rw-r--r--apps/web/globals.css1
-rw-r--r--apps/web/middleware.ts1
8 files changed, 322 insertions, 314 deletions
diff --git a/apps/web/app/global-error.tsx b/apps/web/app/global-error.tsx
index 9bda5fee..e586eac7 100644
--- a/apps/web/app/global-error.tsx
+++ b/apps/web/app/global-error.tsx
@@ -1,23 +1,27 @@
-"use client";
+"use client"
-import * as Sentry from "@sentry/nextjs";
-import NextError from "next/error";
-import { useEffect } from "react";
+import * as Sentry from "@sentry/nextjs"
+import NextError from "next/error"
+import { useEffect } from "react"
-export default function GlobalError({ error }: { error: Error & { digest?: string } }) {
- useEffect(() => {
- Sentry.captureException(error);
- }, [error]);
+export default function GlobalError({
+ error,
+}: {
+ error: Error & { digest?: string }
+}) {
+ useEffect(() => {
+ Sentry.captureException(error)
+ }, [error])
- return (
- <html>
- <body>
- {/* `NextError` is the default Next.js error page component. Its type
+ return (
+ <html lang="en">
+ <body>
+ {/* `NextError` is the default Next.js error page component. Its type
definition requires a `statusCode` prop. However, since the App Router
does not expose status codes for errors, we simply pass 0 to render a
generic error message. */}
- <NextError statusCode={0} />
- </body>
- </html>
- );
-} \ No newline at end of file
+ <NextError statusCode={0} />
+ </body>
+ </html>
+ )
+}
diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
index 622eb2c1..707e4185 100644
--- a/apps/web/app/layout.tsx
+++ b/apps/web/app/layout.tsx
@@ -33,7 +33,10 @@ export default function RootLayout({
}>) {
return (
<html lang="en" suppressHydrationWarning>
- <body className={`${font.variable} antialiased overflow-x-hidden`}>
+ <body
+ className={`${font.variable} antialiased overflow-x-hidden`}
+ suppressHydrationWarning
+ >
<ThemeProvider
attribute="class"
defaultTheme="system"
diff --git a/apps/web/components/graph-dialog.tsx b/apps/web/components/graph-dialog.tsx
index 8849d4ce..ef291d69 100644
--- a/apps/web/components/graph-dialog.tsx
+++ b/apps/web/components/graph-dialog.tsx
@@ -7,7 +7,7 @@ import { useInfiniteQuery } from "@tanstack/react-query"
import { useCallback, useEffect, useMemo, useState } from "react"
import type { z } from "zod"
import { MemoryGraph } from "@repo/ui/memory-graph"
-import { Dialog, DialogContent } from "@repo/ui/components/dialog"
+import { Dialog, DialogContent, DialogTitle } from "@repo/ui/components/dialog"
import { ConnectAIModal } from "@/components/connect-ai-modal"
import { AddMemoryView } from "@/components/views/add-memory"
import { useChatOpen, useProject, useGraphModal } from "@/stores"
@@ -173,6 +173,7 @@ export function GraphDialog() {
className="w-[95vw] h-[95vh] p-0 max-w-6xl sm:max-w-6xl"
showCloseButton={true}
>
+ <DialogTitle className="sr-only">Memory Graph</DialogTitle>
<div className="w-full h-full">
<MemoryGraph
documents={allDocuments}
diff --git a/apps/web/components/text-effect.tsx b/apps/web/components/text-effect.tsx
index 82c6823c..0cbb67ce 100644
--- a/apps/web/components/text-effect.tsx
+++ b/apps/web/components/text-effect.tsx
@@ -1,294 +1,290 @@
-'use client';
-import { cn } from '@lib/utils';
-import {
- AnimatePresence,
- motion
-} from 'motion/react';
+"use client"
+import { cn } from "@lib/utils"
+import { AnimatePresence, motion } from "motion/react"
import type {
- TargetAndTransition,
- Transition,
- Variant,
- Variants,
-} from 'motion/react'
-import React from 'react';
+ TargetAndTransition,
+ Transition,
+ Variant,
+ Variants,
+} from "motion/react"
+import React from "react"
-export type PresetType = 'blur' | 'fade-in-blur' | 'scale' | 'fade' | 'slide';
+export type PresetType = "blur" | "fade-in-blur" | "scale" | "fade" | "slide"
-export type PerType = 'word' | 'char' | 'line';
+export type PerType = "word" | "char" | "line"
export type TextEffectProps = {
- children: string;
- per?: PerType;
- as?: keyof React.JSX.IntrinsicElements;
- variants?: {
- container?: Variants;
- item?: Variants;
- };
- className?: string;
- preset?: PresetType;
- delay?: number;
- speedReveal?: number;
- speedSegment?: number;
- trigger?: boolean;
- onAnimationComplete?: () => void;
- onAnimationStart?: () => void;
- segmentWrapperClassName?: string;
- containerTransition?: Transition;
- segmentTransition?: Transition;
- style?: React.CSSProperties;
-};
+ children: string
+ per?: PerType
+ as?: keyof React.JSX.IntrinsicElements
+ variants?: {
+ container?: Variants
+ item?: Variants
+ }
+ className?: string
+ preset?: PresetType
+ delay?: number
+ speedReveal?: number
+ speedSegment?: number
+ trigger?: boolean
+ onAnimationComplete?: () => void
+ onAnimationStart?: () => void
+ segmentWrapperClassName?: string
+ containerTransition?: Transition
+ segmentTransition?: Transition
+ style?: React.CSSProperties
+}
const defaultStaggerTimes: Record<PerType, number> = {
- char: 0.03,
- word: 0.05,
- line: 0.1,
-};
+ char: 0.03,
+ word: 0.05,
+ line: 0.1,
+}
const defaultContainerVariants: Variants = {
- hidden: { opacity: 0 },
- visible: {
- opacity: 1,
- transition: {
- staggerChildren: 0.05,
- },
- },
- exit: {
- transition: { staggerChildren: 0.05, staggerDirection: -1 },
- },
-};
+ hidden: { opacity: 0 },
+ visible: {
+ opacity: 1,
+ transition: {
+ staggerChildren: 0.05,
+ },
+ },
+ exit: {
+ transition: { staggerChildren: 0.05, staggerDirection: -1 },
+ },
+}
const defaultItemVariants: Variants = {
- hidden: { opacity: 0 },
- visible: {
- opacity: 1,
- },
- exit: { opacity: 0 },
-};
+ hidden: { opacity: 0 },
+ visible: {
+ opacity: 1,
+ },
+ exit: { opacity: 0 },
+}
const presetVariants: Record<
- PresetType,
- { container: Variants; item: Variants }
+ PresetType,
+ { container: Variants; item: Variants }
> = {
- blur: {
- container: defaultContainerVariants,
- item: {
- hidden: { opacity: 0, filter: 'blur(12px)' },
- visible: { opacity: 1, filter: 'blur(0px)' },
- exit: { opacity: 0, filter: 'blur(12px)' },
- },
- },
- 'fade-in-blur': {
- container: defaultContainerVariants,
- item: {
- hidden: { opacity: 0, y: 20, filter: 'blur(12px)' },
- visible: { opacity: 1, y: 0, filter: 'blur(0px)' },
- exit: { opacity: 0, y: 20, filter: 'blur(12px)' },
- },
- },
- scale: {
- container: defaultContainerVariants,
- item: {
- hidden: { opacity: 0, scale: 0 },
- visible: { opacity: 1, scale: 1 },
- exit: { opacity: 0, scale: 0 },
- },
- },
- fade: {
- container: defaultContainerVariants,
- item: {
- hidden: { opacity: 0 },
- visible: { opacity: 1 },
- exit: { opacity: 0 },
- },
- },
- slide: {
- container: defaultContainerVariants,
- item: {
- hidden: { opacity: 0, y: 20 },
- visible: { opacity: 1, y: 0 },
- exit: { opacity: 0, y: 20 },
- },
- },
-};
+ blur: {
+ container: defaultContainerVariants,
+ item: {
+ hidden: { opacity: 0, filter: "blur(12px)" },
+ visible: { opacity: 1, filter: "blur(0px)" },
+ exit: { opacity: 0, filter: "blur(12px)" },
+ },
+ },
+ "fade-in-blur": {
+ container: defaultContainerVariants,
+ item: {
+ hidden: { opacity: 0, y: 20, filter: "blur(12px)" },
+ visible: { opacity: 1, y: 0, filter: "blur(0px)" },
+ exit: { opacity: 0, y: 20, filter: "blur(12px)" },
+ },
+ },
+ scale: {
+ container: defaultContainerVariants,
+ item: {
+ hidden: { opacity: 0, scale: 0 },
+ visible: { opacity: 1, scale: 1 },
+ exit: { opacity: 0, scale: 0 },
+ },
+ },
+ fade: {
+ container: defaultContainerVariants,
+ item: {
+ hidden: { opacity: 0 },
+ visible: { opacity: 1 },
+ exit: { opacity: 0 },
+ },
+ },
+ slide: {
+ container: defaultContainerVariants,
+ item: {
+ hidden: { opacity: 0, y: 20 },
+ visible: { opacity: 1, y: 0 },
+ exit: { opacity: 0, y: 20 },
+ },
+ },
+}
const AnimationComponent: React.FC<{
- segment: string;
- variants: Variants;
- per: 'line' | 'word' | 'char';
- segmentWrapperClassName?: string;
+ segment: string
+ variants: Variants
+ per: "line" | "word" | "char"
+ segmentWrapperClassName?: string
}> = React.memo(({ segment, variants, per, segmentWrapperClassName }) => {
- const content =
- per === 'line' ? (
- <motion.span variants={variants} className='block'>
- {segment}
- </motion.span>
- ) : per === 'word' ? (
- <motion.span
- aria-hidden='true'
- variants={variants}
- className='inline-block whitespace-pre'
- >
- {segment}
- </motion.span>
- ) : (
- <motion.span className='inline-block whitespace-pre'>
- {segment.split('').map((char, charIndex) => (
- <motion.span
- key={`char-${charIndex}`}
- aria-hidden='true'
- variants={variants}
- className='inline-block whitespace-pre'
- >
- {char}
- </motion.span>
- ))}
- </motion.span>
- );
+ const content =
+ per === "line" ? (
+ <motion.span variants={variants} className="block">
+ {segment}
+ </motion.span>
+ ) : per === "word" ? (
+ <motion.span
+ aria-hidden="true"
+ variants={variants}
+ className="inline-block whitespace-pre"
+ >
+ {segment}
+ </motion.span>
+ ) : (
+ <motion.span className="inline-block whitespace-pre">
+ {segment.split("").map((char, charIndex) => (
+ <motion.span
+ // biome-ignore lint/suspicious/noArrayIndexKey: Character position is stable within animation
+ key={`char-${charIndex}`}
+ aria-hidden="true"
+ variants={variants}
+ className="inline-block whitespace-pre"
+ >
+ {char}
+ </motion.span>
+ ))}
+ </motion.span>
+ )
- if (!segmentWrapperClassName) {
- return content;
- }
+ if (!segmentWrapperClassName) {
+ return content
+ }
- const defaultWrapperClassName = per === 'line' ? 'block' : 'inline-block';
+ const defaultWrapperClassName = per === "line" ? "block" : "inline-block"
- return (
- <span className={cn(defaultWrapperClassName, segmentWrapperClassName)}>
- {content}
- </span>
- );
-});
+ return (
+ <span className={cn(defaultWrapperClassName, segmentWrapperClassName)}>
+ {content}
+ </span>
+ )
+})
-AnimationComponent.displayName = 'AnimationComponent';
+AnimationComponent.displayName = "AnimationComponent"
const splitText = (text: string, per: PerType) => {
- if (per === 'line') return text.split('\n');
- return text.split(/(\s+)/);
-};
+ if (per === "line") return text.split("\n")
+ return text.split(/(\s+)/)
+}
const hasTransition = (
- variant?: Variant
+ variant?: Variant,
): variant is TargetAndTransition & { transition?: Transition } => {
- if (!variant) return false;
- return (
- typeof variant === 'object' && 'transition' in variant
- );
-};
+ if (!variant) return false
+ return typeof variant === "object" && "transition" in variant
+}
const createVariantsWithTransition = (
- baseVariants: Variants,
- transition?: Transition & { exit?: Transition }
+ baseVariants: Variants,
+ transition?: Transition & { exit?: Transition },
): Variants => {
- if (!transition) return baseVariants;
+ if (!transition) return baseVariants
- const { exit: _, ...mainTransition } = transition;
+ const { exit: _, ...mainTransition } = transition
- return {
- ...baseVariants,
- visible: {
- ...baseVariants.visible,
- transition: {
- ...(hasTransition(baseVariants.visible)
- ? baseVariants.visible.transition
- : {}),
- ...mainTransition,
- },
- },
- exit: {
- ...baseVariants.exit,
- transition: {
- ...(hasTransition(baseVariants.exit)
- ? baseVariants.exit.transition
- : {}),
- ...mainTransition,
- staggerDirection: -1,
- },
- },
- };
-};
+ return {
+ ...baseVariants,
+ visible: {
+ ...baseVariants.visible,
+ transition: {
+ ...(hasTransition(baseVariants.visible)
+ ? baseVariants.visible.transition
+ : {}),
+ ...mainTransition,
+ },
+ },
+ exit: {
+ ...baseVariants.exit,
+ transition: {
+ ...(hasTransition(baseVariants.exit)
+ ? baseVariants.exit.transition
+ : {}),
+ ...mainTransition,
+ staggerDirection: -1,
+ },
+ },
+ }
+}
export function TextEffect({
- children,
- per = 'word',
- as = 'p',
- variants,
- className,
- preset = 'fade',
- delay = 0,
- speedReveal = 1,
- speedSegment = 1,
- trigger = true,
- onAnimationComplete,
- onAnimationStart,
- segmentWrapperClassName,
- containerTransition,
- segmentTransition,
- style,
+ children,
+ per = "word",
+ as = "p",
+ variants,
+ className,
+ preset = "fade",
+ delay = 0,
+ speedReveal = 1,
+ speedSegment = 1,
+ trigger = true,
+ onAnimationComplete,
+ onAnimationStart,
+ segmentWrapperClassName,
+ containerTransition,
+ segmentTransition,
+ style,
}: TextEffectProps) {
- const segments = splitText(children, per);
- const MotionTag = motion[as as keyof typeof motion] as typeof motion.div;
+ const segments = splitText(children, per)
+ const MotionTag = motion[as as keyof typeof motion] as typeof motion.div
- const baseVariants = preset
- ? presetVariants[preset]
- : { container: defaultContainerVariants, item: defaultItemVariants };
+ const baseVariants = preset
+ ? presetVariants[preset]
+ : { container: defaultContainerVariants, item: defaultItemVariants }
- const stagger = defaultStaggerTimes[per] / speedReveal;
+ const stagger = defaultStaggerTimes[per] / speedReveal
- const baseDuration = 0.3 / speedSegment;
+ const baseDuration = 0.3 / speedSegment
- const customStagger = hasTransition(variants?.container?.visible ?? {})
- ? (variants?.container?.visible as TargetAndTransition).transition
- ?.staggerChildren
- : undefined;
+ const customStagger = hasTransition(variants?.container?.visible ?? {})
+ ? (variants?.container?.visible as TargetAndTransition).transition
+ ?.staggerChildren
+ : undefined
- const customDelay = hasTransition(variants?.container?.visible ?? {})
- ? (variants?.container?.visible as TargetAndTransition).transition
- ?.delayChildren
- : undefined;
+ const customDelay = hasTransition(variants?.container?.visible ?? {})
+ ? (variants?.container?.visible as TargetAndTransition).transition
+ ?.delayChildren
+ : undefined
- const computedVariants = {
- container: createVariantsWithTransition(
- variants?.container || baseVariants.container,
- {
- staggerChildren: customStagger ?? stagger,
- delayChildren: customDelay ?? delay,
- ...containerTransition,
- exit: {
- staggerChildren: customStagger ?? stagger,
- staggerDirection: -1,
- },
- }
- ),
- item: createVariantsWithTransition(variants?.item || baseVariants.item, {
- duration: baseDuration,
- ...segmentTransition,
- }),
- };
+ const computedVariants = {
+ container: createVariantsWithTransition(
+ variants?.container || baseVariants.container,
+ {
+ staggerChildren: customStagger ?? stagger,
+ delayChildren: customDelay ?? delay,
+ ...containerTransition,
+ exit: {
+ staggerChildren: customStagger ?? stagger,
+ staggerDirection: -1,
+ },
+ },
+ ),
+ item: createVariantsWithTransition(variants?.item || baseVariants.item, {
+ duration: baseDuration,
+ ...segmentTransition,
+ }),
+ }
- return (
- <AnimatePresence mode='popLayout'>
- {trigger && (
- <MotionTag
- initial='hidden'
- animate='visible'
- exit='exit'
- variants={computedVariants.container}
- className={className}
- onAnimationComplete={onAnimationComplete}
- onAnimationStart={onAnimationStart}
- style={style}
- >
- {per !== 'line' ? <span className='sr-only'>{children}</span> : null}
- {segments.map((segment, index) => (
- <AnimationComponent
- key={`${per}-${index}-${segment}`}
- segment={segment}
- variants={computedVariants.item}
- per={per}
- segmentWrapperClassName={segmentWrapperClassName}
- />
- ))}
- </MotionTag>
- )}
- </AnimatePresence>
- );
+ return (
+ <AnimatePresence mode="popLayout">
+ {trigger && (
+ <MotionTag
+ initial="hidden"
+ animate="visible"
+ exit="exit"
+ variants={computedVariants.container}
+ className={className}
+ onAnimationComplete={onAnimationComplete}
+ onAnimationStart={onAnimationStart}
+ style={style}
+ >
+ {per !== "line" ? <span className="sr-only">{children}</span> : null}
+ {segments.map((segment, index) => (
+ <AnimationComponent
+ key={`${per}-${index}-${segment}`}
+ segment={segment}
+ variants={computedVariants.item}
+ per={per}
+ segmentWrapperClassName={segmentWrapperClassName}
+ />
+ ))}
+ </MotionTag>
+ )}
+ </AnimatePresence>
+ )
}
diff --git a/apps/web/components/views/add-memory/index.tsx b/apps/web/components/views/add-memory/index.tsx
index f7940bce..4e250b53 100644
--- a/apps/web/components/views/add-memory/index.tsx
+++ b/apps/web/components/views/add-memory/index.tsx
@@ -361,7 +361,7 @@ export function AddMemoryView({
return { previousMemories, optimisticId: optimisticMemory.id }
},
// If the mutation fails, roll back to the previous value
- onError: (error, variables, context) => {
+ onError: (_error, variables, context) => {
if (context?.previousMemories) {
queryClient.setQueryData(
["documents-with-memories", variables.project],
@@ -551,6 +551,7 @@ export function AddMemoryView({
className="w-[100vw] max-w-4xl sm:max-w-4xl backdrop-blur-xl border-white/10 z-[80] h-[52vh] overflow-y-auto p-4"
showCloseButton={false}
>
+ <DialogTitle className="sr-only">Add Memory</DialogTitle>
<Tabs
value={activeTab}
onValueChange={(value) => setActiveTab(value as typeof activeTab)}
@@ -638,9 +639,13 @@ export function AddMemoryView({
>
{({ state, handleChange, handleBlur }) => (
<>
- <div className={addContentMutation.isPending ? "opacity-50" : ""}>
- <TextEditor
- containerClassName="bg-white/5 border-white/10 rounded-md"
+ <div
+ className={
+ addContentMutation.isPending ? "opacity-50" : ""
+ }
+ >
+ <TextEditor
+ containerClassName="bg-white/5 border-white/10 rounded-md"
disabled={addContentMutation.isPending}
onBlur={handleBlur}
onChange={handleChange}
@@ -843,14 +848,14 @@ export function AddMemoryView({
</TabsContent>
<TabsContent value="file" className="space-y-4">
- <form
+ <form
onSubmit={(e) => {
e.preventDefault()
e.stopPropagation()
fileUploadForm.handleSubmit()
}}
- className="h-full flex flex-col"
- >
+ className="h-full flex flex-col"
+ >
<div className="grid gap-4">
<motion.div
animate={{ opacity: 1, y: 0 }}
@@ -938,7 +943,7 @@ export function AddMemoryView({
</fileUploadForm.Field>
</motion.div>
</div>
- <div className="mt-6 flex flex-col sm:flex-row sm:justify-between sm:items-end w-full gap-4 mt-auto">
+ <div className="flex flex-col sm:flex-row sm:justify-between sm:items-end w-full gap-4 mt-auto">
<div className="flex items-end gap-4">
{/* Left side - Project Selection */}
<motion.div
diff --git a/apps/web/components/views/chat/index.tsx b/apps/web/components/views/chat/index.tsx
index 2b7befa1..6fabadc8 100644
--- a/apps/web/components/views/chat/index.tsx
+++ b/apps/web/components/views/chat/index.tsx
@@ -1,7 +1,7 @@
-"use client";
+"use client"
-import { cn } from "@lib/utils";
-import { Button } from "@ui/components/button";
+import { cn } from "@lib/utils"
+import { Button } from "@ui/components/button"
import {
Dialog,
DialogContent,
@@ -9,38 +9,38 @@ import {
DialogHeader,
DialogTitle,
DialogTrigger,
-} from "@ui/components/dialog";
-import { ScrollArea } from "@ui/components/scroll-area";
-import { formatDistanceToNow } from "date-fns";
-import { HistoryIcon, Plus, Trash2, X } from "lucide-react";
-import { useMemo, useState } from "react";
-import { analytics } from "@/lib/analytics";
-import { useChatOpen, usePersistentChat, useProject } from "@/stores";
-import { ChatMessages } from "./chat-messages";
+} from "@ui/components/dialog"
+import { ScrollArea } from "@ui/components/scroll-area"
+import { formatDistanceToNow } from "date-fns"
+import { HistoryIcon, Plus, Trash2, X } from "lucide-react"
+import { useMemo, useState } from "react"
+import { analytics } from "@/lib/analytics"
+import { useChatOpen, usePersistentChat, useProject } from "@/stores"
+import { ChatMessages } from "./chat-messages"
export function ChatRewrite() {
- const { setIsOpen } = useChatOpen();
- const { selectedProject } = useProject();
+ const { setIsOpen } = useChatOpen()
+ const { selectedProject } = useProject()
const { conversations, currentChatId, setCurrentChatId, getCurrentChat } =
- usePersistentChat();
+ usePersistentChat()
- const [isDialogOpen, setIsDialogOpen] = useState(false);
+ const [isDialogOpen, setIsDialogOpen] = useState(false)
const sorted = useMemo(() => {
return [...conversations].sort((a, b) =>
a.lastUpdated < b.lastUpdated ? 1 : -1,
- );
- }, [conversations]);
+ )
+ }, [conversations])
function handleNewChat() {
- analytics.newChatStarted();
- const newId = crypto.randomUUID();
- setCurrentChatId(newId);
- setIsDialogOpen(false);
+ analytics.newChatStarted()
+ const newId = crypto.randomUUID()
+ setCurrentChatId(newId)
+ setIsDialogOpen(false)
}
function formatRelativeTime(isoString: string): string {
- return formatDistanceToNow(new Date(isoString), { addSuffix: true });
+ return formatDistanceToNow(new Date(isoString), { addSuffix: true })
}
return (
@@ -74,18 +74,17 @@ export function ChatRewrite() {
<ScrollArea className="max-h-96">
<div className="flex flex-col gap-1">
{sorted.map((c) => {
- const isActive = c.id === currentChatId;
+ const isActive = c.id === currentChatId
return (
- <div
+ <button
+ type="button"
key={c.id}
- role="button"
- tabIndex={0}
onClick={() => {
- setCurrentChatId(c.id);
- setIsDialogOpen(false);
+ setCurrentChatId(c.id)
+ setIsDialogOpen(false)
}}
className={cn(
- "flex items-center justify-between rounded-md px-3 py-2 outline-none",
+ "flex items-center justify-between rounded-md px-3 py-2 outline-none w-full text-left",
"transition-colors",
isActive ? "bg-primary/10" : "hover:bg-muted",
)}
@@ -111,15 +110,15 @@ export function ChatRewrite() {
variant="ghost"
size="icon"
onClick={(e) => {
- e.stopPropagation();
- analytics.chatDeleted();
+ e.stopPropagation()
+ analytics.chatDeleted()
}}
aria-label="Delete conversation"
>
<Trash2 className="size-4 text-muted-foreground" />
</Button>
- </div>
- );
+ </button>
+ )
})}
{sorted.length === 0 && (
<div className="text-xs text-muted-foreground px-3 py-2">
@@ -152,5 +151,5 @@ export function ChatRewrite() {
</div>
<ChatMessages />
</div>
- );
+ )
}
diff --git a/apps/web/globals.css b/apps/web/globals.css
index 2c150cf0..f95da3a2 100644
--- a/apps/web/globals.css
+++ b/apps/web/globals.css
@@ -1,7 +1,6 @@
@import "tailwindcss";
@plugin "@tailwindcss/typography";
-
.sm-tweet-theme .react-tweet-theme {
--tweet-container-margin: 0px;
}
diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts
index bbb63c42..7bab1d21 100644
--- a/apps/web/middleware.ts
+++ b/apps/web/middleware.ts
@@ -4,6 +4,7 @@ import { NextResponse } from "next/server"
export default async function proxy(request: Request) {
console.debug("[PROXY] === PROXY START ===")
const url = new URL(request.url)
+
console.debug("[PROXY] Path:", url.pathname)
console.debug("[PROXY] Method:", request.method)