+
);
};
diff --git a/src/frontend/apps/web/src/features/chat/ui/chat-textarea.tsx b/src/frontend/apps/web/src/features/chat/ui/chat-textarea.tsx
new file mode 100644
index 00000000..f8e5c9b7
--- /dev/null
+++ b/src/frontend/apps/web/src/features/chat/ui/chat-textarea.tsx
@@ -0,0 +1,22 @@
+'use client';
+
+import { Textarea } from '@workspace/ui/components';
+import ChatToggleGroup from './chat-toggle-group';
+
+const ChatTextArea = () => {
+ const handleSendClick = () => alert('Send clicked');
+
+ return (
+
+ );
+};
+
+export default ChatTextArea;
diff --git a/src/frontend/apps/web/src/features/chat/ui/chat-toggle-group.tsx b/src/frontend/apps/web/src/features/chat/ui/chat-toggle-group.tsx
new file mode 100644
index 00000000..5ab8a889
--- /dev/null
+++ b/src/frontend/apps/web/src/features/chat/ui/chat-toggle-group.tsx
@@ -0,0 +1,51 @@
+'use client';
+import { useState, useRef } from 'react';
+
+import { Button } from '@workspace/ui/components';
+import { handleFileChangeEvent, removeFile } from '@/src/features/chat/model';
+
+import { FilePreviewList } from './file-preivew-list';
+import { FileUploadTrigger } from './file-upload-trigger';
+import type { FileData } from '../model';
+
+type ChatToggleGroupsProps = {
+ name: string;
+ onSend?: () => void;
+};
+
+const ChatToggleGroup = ({ name, onSend }: ChatToggleGroupsProps) => {
+ const [selectedFiles, setSelectedFiles] = useState
([]);
+
+ const handleFileChange = (event: React.ChangeEvent) => {
+ handleFileChangeEvent(event, setSelectedFiles);
+ };
+
+ const handleRemoveFile = (id: string) => {
+ removeFile(id, setSelectedFiles);
+ };
+
+ return (
+
+
+
+
+ {onSend && (
+
+ )}
+
+
+ );
+};
+
+export default ChatToggleGroup;
diff --git a/src/frontend/apps/web/src/features/chat/ui/content-avatar.tsx b/src/frontend/apps/web/src/features/chat/ui/content-avatar.tsx
index f0df47b0..df879e67 100644
--- a/src/frontend/apps/web/src/features/chat/ui/content-avatar.tsx
+++ b/src/frontend/apps/web/src/features/chat/ui/content-avatar.tsx
@@ -9,7 +9,7 @@ const ContentAvatar = ({ type }: ContentAvatarProps) => {
return (
<>
{type === 'live' ? (
-
+
void;
+};
+
+export const FilePreviewList = ({
+ selectedFiles,
+ onRemoveFile,
+}: FilePreviewListProps) => {
+ if (selectedFiles.length === 0) {
+ return null;
+ }
+
+ return (
+
+
+ {selectedFiles.map((fileData) => (
+
+ ))}
+
+
+ );
+};
diff --git a/src/frontend/apps/web/src/features/chat/ui/file-preview-item.tsx b/src/frontend/apps/web/src/features/chat/ui/file-preview-item.tsx
new file mode 100644
index 00000000..35192107
--- /dev/null
+++ b/src/frontend/apps/web/src/features/chat/ui/file-preview-item.tsx
@@ -0,0 +1,42 @@
+'use client';
+
+import Image from 'next/image';
+import type { FileData } from '../model';
+
+type FilePreviewItemProps = {
+ fileData: FileData;
+ onRemove: (id: string) => void;
+};
+
+export const FilePreviewItem = ({
+ fileData,
+ onRemove,
+}: FilePreviewItemProps) => {
+ return (
+
+
+ {fileData.type === 'image' ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+};
diff --git a/src/frontend/apps/web/src/features/chat/ui/file-upload-trigger.tsx b/src/frontend/apps/web/src/features/chat/ui/file-upload-trigger.tsx
new file mode 100644
index 00000000..702df6d3
--- /dev/null
+++ b/src/frontend/apps/web/src/features/chat/ui/file-upload-trigger.tsx
@@ -0,0 +1,46 @@
+'use client';
+
+import { ChangeEvent, useRef } from 'react';
+import { Button } from '@workspace/ui/components';
+
+type FileUploadTriggerProps = {
+ name: string;
+ onFileChange: (e: ChangeEvent) => void;
+};
+
+export const FileUploadTrigger = ({
+ name,
+ onFileChange,
+}: FileUploadTriggerProps) => {
+ const fileInputRef = useRef(null);
+
+ const handlePickFile = () => {
+ fileInputRef.current?.click();
+ };
+
+ return (
+
+
+
+
+ Images (max 20MB) or Videos (max 200MB)
+
+
+ );
+};
diff --git a/src/frontend/packages/ui/src/components/ChatTextarea/chat-textarea.stories.tsx b/src/frontend/packages/ui/src/components/ChatTextarea/chat-textarea.stories.tsx
deleted file mode 100644
index 53ecff41..00000000
--- a/src/frontend/packages/ui/src/components/ChatTextarea/chat-textarea.stories.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import { Meta, StoryObj } from '@storybook/react';
-import { action } from '@storybook/addon-actions';
-
-import { ChatTextarea } from './chat-textarea';
-
-const meta: Meta = {
- title: 'Widget/ChatTextarea',
- component: ChatTextarea,
- parameters: {
- layout: 'centered',
- },
- tags: ['autodocs'],
- argTypes: {
- onSend: { action: 'Send button clicked' },
- onAdd: { action: 'Add button clicked' },
- },
-};
-export default meta;
-
-type Story = StoryObj;
-
-export const Default: Story = {
- args: {
- onSend: action('Send button clicked'),
- onAdd: action('Add button clicked'),
- },
- render: () => (
-
-
-
- ),
-};
diff --git a/src/frontend/packages/ui/src/components/ChatTextarea/chat-textarea.tsx b/src/frontend/packages/ui/src/components/ChatTextarea/chat-textarea.tsx
deleted file mode 100644
index 6eaab65d..00000000
--- a/src/frontend/packages/ui/src/components/ChatTextarea/chat-textarea.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-'use client';
-
-import { Textarea } from '../Textarea';
-import { Button } from '../Button';
-
-import { cn } from '@workspace/ui/lib/utils';
-
-const ChatTextarea = ({ onSend, onAdd }) => {
- return (
-
-
-
-
-
-
-
- );
-};
-ChatTextarea.displayName = 'ChatTextarea';
-
-export { ChatTextarea };
diff --git a/src/frontend/packages/ui/src/components/ChatTextarea/index.ts b/src/frontend/packages/ui/src/components/ChatTextarea/index.ts
deleted file mode 100644
index 3bfdb2c6..00000000
--- a/src/frontend/packages/ui/src/components/ChatTextarea/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { ChatTextarea } from './chat-textarea';
diff --git a/src/frontend/packages/ui/src/components/Textarea/textarea.stories.tsx b/src/frontend/packages/ui/src/components/Textarea/textarea.stories.tsx
index c00a1d9a..559e70df 100644
--- a/src/frontend/packages/ui/src/components/Textarea/textarea.stories.tsx
+++ b/src/frontend/packages/ui/src/components/Textarea/textarea.stories.tsx
@@ -1,5 +1,6 @@
import { Meta, StoryObj } from '@storybook/react';
import { Textarea } from './textarea';
+import { Button } from '../Button';
const meta: Meta = {
title: 'Widget/Textarea',
@@ -45,3 +46,33 @@ export const Disabled: Story = {
),
};
+
+export const ChatTextarea: Story = {
+ render: () => {
+ const handleAddClick = () => alert('Add clicked');
+ const handleSendClick = () => alert('Send clicked');
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+ },
+};
diff --git a/src/frontend/packages/ui/src/components/Textarea/textarea.tsx b/src/frontend/packages/ui/src/components/Textarea/textarea.tsx
index caa47488..8fb1e5cf 100644
--- a/src/frontend/packages/ui/src/components/Textarea/textarea.tsx
+++ b/src/frontend/packages/ui/src/components/Textarea/textarea.tsx
@@ -4,7 +4,10 @@ import * as React from 'react';
import { cn } from '@workspace/ui/lib/utils';
-const Textarea = React.forwardRef
>(({ className, ...props }, ref) => {
+const Textarea = React.forwardRef<
+ HTMLTextAreaElement,
+ React.ComponentPropsWithRef<'textarea'>
+>(({ className, ...props }, ref) => {
const autoResizeTextarea = () => {
const textarea = document.querySelector('textarea');
@@ -18,7 +21,7 @@ const Textarea = React.forwardRef