90 lines · 2.8 KB · TypeScript
RawDownload
import { MessageCircle, Trash2 } from "lucide-react";import { useState } from "react"; import { Button } from "~/components/ui/button";import { Textarea } from "~/components/ui/textarea"; interface LocalCommentAnnotationProps {  kind: "draft" | "comment";  rangeLabel: string;  text: string;  onCancel: () => void;  onComment: (text: string) => void;  onDelete: () => void;} export function LocalCommentAnnotation({  kind,  rangeLabel,  text: savedText,  onCancel,  onComment,  onDelete,}: LocalCommentAnnotationProps) {  const [text, setText] = useState("");   if (kind === "comment") {    return (      <div        data-file-comment-annotation        className="mx-3 my-2 rounded-xl border border-border/70 bg-background p-3 shadow-sm"        contentEditable={false}        onPointerDown={(event) => event.stopPropagation()}      >        <div className="flex items-center gap-2">          <MessageCircle className="size-4 text-muted-foreground" />          <span className="text-xs font-medium">Local comment</span>          <span className="ml-auto text-[11px] text-muted-foreground">{rangeLabel}</span>          <Button variant="ghost" size="icon-xs" aria-label="Delete comment" onClick={onDelete}>            <Trash2 className="size-3.5" />          </Button>        </div>        <p className="mt-2 whitespace-pre-wrap text-sm leading-relaxed text-foreground">          {savedText}        </p>      </div>    );  }   return (    <div      data-file-comment-annotation      className="mx-3 my-2 rounded-xl border border-border/70 bg-background p-3 shadow-lg"      contentEditable={false}      onPointerDown={(event) => event.stopPropagation()}    >      <div className="flex items-center gap-2">        <MessageCircle className="size-4 text-muted-foreground" />        <span className="text-sm font-medium">Local comment</span>      </div>      <div className="mt-1 text-xs text-muted-foreground">Comment on lines {rangeLabel}</div>      <Textarea        autoFocus        className="mt-3"        size="sm"        value={text}        placeholder="Request change"        aria-label={`Comment on lines ${rangeLabel}`}        onChange={(event) => setText(event.target.value)}        onKeyDown={(event) => {          if (event.key === "Escape") {            event.preventDefault();            onCancel();          }          if ((event.metaKey || event.ctrlKey) && event.key === "Enter" && text.trim()) {            event.preventDefault();            onComment(text.trim());          }        }}      />      <div className="mt-3 flex justify-end gap-2">        <Button variant="ghost" size="sm" onClick={onCancel}>          Cancel        </Button>        <Button size="sm" disabled={!text.trim()} onClick={() => onComment(text.trim())}>          Comment        </Button>      </div>    </div>  );}