mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-26 17:26:23 +02:00
feat: implement responsive comment UI with mobile and desktop variants
This commit is contained in:
parent
d83e9aa52d
commit
ab91cbd148
8 changed files with 229 additions and 9 deletions
|
|
@ -19,6 +19,7 @@ export function CommentPanelContainer({
|
|||
messageId,
|
||||
isOpen,
|
||||
maxHeight,
|
||||
variant = "desktop",
|
||||
}: CommentPanelContainerProps) {
|
||||
const { data: commentsData, isLoading: isCommentsLoading } = useComments({
|
||||
messageId,
|
||||
|
|
@ -80,6 +81,7 @@ export function CommentPanelContainer({
|
|||
onDeleteComment={handleDeleteComment}
|
||||
isSubmitting={isSubmitting}
|
||||
maxHeight={maxHeight}
|
||||
variant={variant}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,4 +2,6 @@ export interface CommentPanelContainerProps {
|
|||
messageId: number;
|
||||
isOpen: boolean;
|
||||
maxHeight?: number;
|
||||
/** Variant for responsive styling - desktop shows border/bg, mobile is plain */
|
||||
variant?: "desktop" | "mobile";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { MessageSquarePlus } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { CommentComposer } from "../comment-composer/comment-composer";
|
||||
import { CommentThread } from "../comment-thread/comment-thread";
|
||||
import type { CommentPanelProps } from "./types";
|
||||
|
|
@ -18,6 +19,7 @@ export function CommentPanel({
|
|||
onDeleteComment,
|
||||
isSubmitting = false,
|
||||
maxHeight,
|
||||
variant = "desktop",
|
||||
}: CommentPanelProps) {
|
||||
const [isComposerOpen, setIsComposerOpen] = useState(false);
|
||||
|
||||
|
|
@ -30,9 +32,14 @@ export function CommentPanel({
|
|||
setIsComposerOpen(false);
|
||||
};
|
||||
|
||||
const isMobile = variant === "mobile";
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex min-h-[120px] w-96 items-center justify-center rounded-lg border bg-card p-4">
|
||||
<div className={cn(
|
||||
"flex min-h-[120px] items-center justify-center p-4",
|
||||
!isMobile && "w-96 rounded-lg border bg-card"
|
||||
)}>
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<div className="size-4 animate-spin rounded-full border-2 border-current border-t-transparent" />
|
||||
Loading comments...
|
||||
|
|
@ -50,8 +57,11 @@ export function CommentPanel({
|
|||
|
||||
return (
|
||||
<div
|
||||
className="flex w-85 flex-col rounded-lg border bg-card"
|
||||
style={effectiveMaxHeight ? { maxHeight: effectiveMaxHeight } : undefined}
|
||||
className={cn(
|
||||
"flex flex-col",
|
||||
isMobile ? "w-full" : "w-85 rounded-lg border bg-card"
|
||||
)}
|
||||
style={!isMobile && effectiveMaxHeight ? { maxHeight: effectiveMaxHeight } : undefined}
|
||||
>
|
||||
{hasThreads && (
|
||||
<div className="min-h-0 flex-1 overflow-y-auto scrollbar-thin">
|
||||
|
|
@ -82,7 +92,11 @@ export function CommentPanel({
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className={showEmptyState ? "border-t p-3" : "p-3"}>
|
||||
<div className={cn(
|
||||
"p-3",
|
||||
showEmptyState && !isMobile && "border-t",
|
||||
isMobile && "border-t"
|
||||
)}>
|
||||
{isComposerOpen ? (
|
||||
<CommentComposer
|
||||
members={members}
|
||||
|
|
|
|||
|
|
@ -12,4 +12,6 @@ export interface CommentPanelProps {
|
|||
onDeleteComment: (commentId: number) => void;
|
||||
isSubmitting?: boolean;
|
||||
maxHeight?: number;
|
||||
/** Variant for responsive styling - desktop shows border/bg, mobile is plain */
|
||||
variant?: "desktop" | "mobile";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
"use client";
|
||||
|
||||
import { MessageSquare } from "lucide-react";
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
} from "@/components/ui/sheet";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { CommentPanelContainer } from "../comment-panel-container/comment-panel-container";
|
||||
import type { CommentSheetProps } from "./types";
|
||||
|
||||
export function CommentSheet({
|
||||
messageId,
|
||||
isOpen,
|
||||
onOpenChange,
|
||||
commentCount = 0,
|
||||
side = "bottom",
|
||||
}: CommentSheetProps) {
|
||||
const isBottomSheet = side === "bottom";
|
||||
|
||||
return (
|
||||
<Sheet open={isOpen} onOpenChange={onOpenChange}>
|
||||
<SheetContent
|
||||
side={side}
|
||||
className={cn(
|
||||
"flex flex-col p-0",
|
||||
isBottomSheet
|
||||
? "h-[85vh] max-h-[85vh] rounded-t-xl"
|
||||
: "h-full w-full max-w-md"
|
||||
)}
|
||||
>
|
||||
{/* Drag handle indicator - only for bottom sheet */}
|
||||
{isBottomSheet && (
|
||||
<div className="flex justify-center pt-3 pb-1">
|
||||
<div className="h-1 w-10 rounded-full bg-muted-foreground/30" />
|
||||
</div>
|
||||
)}
|
||||
<SheetHeader className={cn(
|
||||
"flex-shrink-0 border-b px-4",
|
||||
isBottomSheet ? "pb-3" : "py-4"
|
||||
)}>
|
||||
<SheetTitle className="flex items-center gap-2 text-base font-semibold">
|
||||
<MessageSquare className="size-5" />
|
||||
Comments
|
||||
{commentCount > 0 && (
|
||||
<span className="rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary">
|
||||
{commentCount}
|
||||
</span>
|
||||
)}
|
||||
</SheetTitle>
|
||||
</SheetHeader>
|
||||
<div className="min-h-0 flex-1 overflow-y-auto">
|
||||
<CommentPanelContainer
|
||||
messageId={messageId}
|
||||
isOpen={true}
|
||||
variant="mobile"
|
||||
/>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
export interface CommentSheetProps {
|
||||
messageId: number;
|
||||
isOpen: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
commentCount?: number;
|
||||
/** Side to open the sheet from - bottom for mobile, right for medium screens */
|
||||
side?: "bottom" | "right";
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue