feat: chat stickers

This commit is contained in:
gosangam
2026-08-30 02:19:31 +05:30
parent 8c7afe596d
commit 2597c6f2ec
9 changed files with 332 additions and 18 deletions
+24 -1
View File
@@ -13,12 +13,13 @@
*/
import { useCallback, useEffect, useRef, useState } from "react";
import { Paperclip, SendHorizonal, X } from "lucide-react";
import { Paperclip, Smile, SendHorizonal, X } from "lucide-react";
import { LinkPreviewCard } from "@/components/chat/link-preview-card";
import {
ComposerAttachments,
type StagedAttachment,
} from "@/components/chat/composer-attachments";
import { StickerPicker } from "@/components/chat/sticker-picker";
import { compressImage } from "@/lib/compress-image";
import { cn } from "@/lib/utils";
import {
@@ -53,6 +54,8 @@ export function ChatComposer({
replyToId?: string,
previewUrl?: string,
attachments?: UploadedAttachment[],
/** Reward artwork sent on its own. */
stickerKey?: string,
) => void;
disabled?: boolean;
placeholder?: string;
@@ -67,6 +70,7 @@ export function ChatComposer({
const [staged, setStaged] = useState<StagedAttachment[]>([]);
const ref = useRef<HTMLTextAreaElement>(null);
const fileRef = useRef<HTMLInputElement>(null);
const [pickingSticker, setPickingSticker] = useState(false);
const lookupSeq = useRef(0);
// Grow with the content, up to a cap.
@@ -253,6 +257,15 @@ export function ChatComposer({
>
<Paperclip className="size-4" />
</button>
<button
type="button"
onClick={() => setPickingSticker(true)}
disabled={disabled}
aria-label="Send a sticker"
className="inline-flex size-9 shrink-0 items-center justify-center rounded-full text-muted-foreground hover:text-foreground disabled:opacity-40"
>
<Smile className="size-4" />
</button>
<textarea
ref={ref}
@@ -303,6 +316,16 @@ export function ChatComposer({
<SendHorizonal className="size-4" />
</button>
</div>
{pickingSticker && (
<StickerPicker
// Sent on its own, with no text: a sticker IS the message.
onPick={(sticker) =>
onSend("", undefined, undefined, undefined, sticker.key)
}
onClose={() => setPickingSticker(false)}
/>
)}
</div>
);
}