enhanced ext editor in worknote page
This commit is contained in:
parent
da1d0538e9
commit
47a5a436aa
@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Bell, Settings, User, Plus, Search, Home, FileText, CheckCircle, LogOut, PanelLeft, PanelLeftClose } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
@ -14,7 +14,7 @@ interface PageLayoutProps {
|
||||
}
|
||||
|
||||
export function PageLayout({ children, currentPage = 'dashboard', onNavigate, onNewRequest }: PageLayoutProps) {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(true);
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
|
||||
const menuItems = [
|
||||
{ id: 'dashboard', label: 'Dashboard', icon: Home },
|
||||
@ -27,11 +27,52 @@ export function PageLayout({ children, currentPage = 'dashboard', onNavigate, on
|
||||
setSidebarOpen(!sidebarOpen);
|
||||
};
|
||||
|
||||
// Handle responsive behavior: sidebar open on desktop, closed on mobile
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
// 768px is the md breakpoint in Tailwind
|
||||
if (window.innerWidth >= 768) {
|
||||
setSidebarOpen(true); // Always open on desktop
|
||||
} else {
|
||||
setSidebarOpen(false); // Closed by default on mobile
|
||||
}
|
||||
};
|
||||
|
||||
// Set initial state
|
||||
handleResize();
|
||||
|
||||
// Add event listener
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
// Cleanup
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex w-full bg-background">
|
||||
{/* Sidebar */}
|
||||
<div className={`${sidebarOpen ? 'w-64' : 'w-0'} transition-all duration-300 ease-in-out overflow-hidden flex-shrink-0`}>
|
||||
<div className="w-64 h-full border-r border-gray-800 bg-black">
|
||||
{/* Mobile Overlay */}
|
||||
{sidebarOpen && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/50 z-40 md:hidden"
|
||||
onClick={() => setSidebarOpen(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Sidebar - Hidden on mobile by default, toggleable on desktop */}
|
||||
<aside className={`
|
||||
fixed md:relative
|
||||
inset-y-0 left-0
|
||||
w-64
|
||||
transform transition-transform duration-300 ease-in-out
|
||||
${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
|
||||
md:translate-x-0
|
||||
${sidebarOpen ? 'md:w-64' : 'md:w-0 md:-translate-x-full'}
|
||||
z-50 md:z-auto
|
||||
flex-shrink-0
|
||||
border-r border-gray-800 bg-black
|
||||
overflow-y-auto
|
||||
`}>
|
||||
<div className="w-64 h-full">
|
||||
<div className="p-4 border-b border-gray-800">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-re-green rounded-lg flex items-center justify-center shrink-0">
|
||||
@ -48,7 +89,13 @@ export function PageLayout({ children, currentPage = 'dashboard', onNavigate, on
|
||||
{menuItems.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
onClick={() => onNavigate?.(item.id)}
|
||||
onClick={() => {
|
||||
onNavigate?.(item.id);
|
||||
// Close sidebar on mobile after navigation
|
||||
if (window.innerWidth < 768) {
|
||||
setSidebarOpen(false);
|
||||
}
|
||||
}}
|
||||
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm transition-colors ${
|
||||
currentPage === item.id
|
||||
? 'bg-re-green text-white font-medium'
|
||||
@ -74,7 +121,7 @@ export function PageLayout({ children, currentPage = 'dashboard', onNavigate, on
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{/* Main Content Area */}
|
||||
<div className="flex-1 flex flex-col min-w-0">
|
||||
|
||||
@ -305,7 +305,9 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
|
||||
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
|
||||
const [messages, setMessages] = useState<Message[]>(INITIAL_MESSAGES);
|
||||
const [showSidebar, setShowSidebar] = useState(false);
|
||||
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// Get request info
|
||||
const requestInfo = useMemo(() => {
|
||||
@ -334,27 +336,117 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
|
||||
}, [messages]);
|
||||
|
||||
const handleSendMessage = () => {
|
||||
if (message.trim()) {
|
||||
if (message.trim() || selectedFiles.length > 0) {
|
||||
const attachments = selectedFiles.map(file => ({
|
||||
name: file.name,
|
||||
url: URL.createObjectURL(file),
|
||||
type: file.type.split('/')[1] || 'file'
|
||||
}));
|
||||
|
||||
const newMessage: Message = {
|
||||
id: Date.now().toString(),
|
||||
user: { name: 'You', avatar: 'YO', role: 'Current User' },
|
||||
content: message,
|
||||
timestamp: new Date().toLocaleString(),
|
||||
timestamp: new Date().toLocaleString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
hour12: true
|
||||
}),
|
||||
mentions: extractMentions(message),
|
||||
isHighPriority: message.includes('!important') || message.includes('urgent')
|
||||
isHighPriority: message.includes('!important') || message.includes('urgent'),
|
||||
attachments: attachments.length > 0 ? attachments : undefined
|
||||
};
|
||||
setMessages(prev => [...prev, newMessage]);
|
||||
setMessage('');
|
||||
setSelectedFiles([]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files) {
|
||||
const filesArray = Array.from(e.target.files);
|
||||
setSelectedFiles(prev => [...prev, ...filesArray]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveFile = (index: number) => {
|
||||
setSelectedFiles(prev => prev.filter((_, i) => i !== index));
|
||||
// Reset file input to allow reselecting the same file
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.value = '';
|
||||
}
|
||||
};
|
||||
|
||||
const handleEmojiSelect = (emoji: string) => {
|
||||
setMessage(prev => prev + emoji);
|
||||
setShowEmojiPicker(false);
|
||||
};
|
||||
|
||||
const handleAttachmentClick = () => {
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
|
||||
// Emoji picker data - Expanded collection
|
||||
const emojiList = [
|
||||
// Smileys & Emotions
|
||||
'😊', '😂', '🤣', '😁', '😃', '😄', '😅', '😆', '😉', '😌',
|
||||
'😍', '🥰', '😘', '😗', '😙', '😚', '🙂', '🤗', '🤩', '🤔',
|
||||
'🤨', '😐', '😑', '😶', '🙄', '😏', '😒', '🙃', '😬', '🤐',
|
||||
'😴', '😪', '😵', '🤯', '🤪', '😜', '😝', '😛', '🤤', '😋',
|
||||
'😎', '🤓', '🧐', '😕', '😟', '🙁', '☹️', '😮', '😯', '😲',
|
||||
'😳', '🥺', '😦', '😧', '😨', '😰', '😥', '😢', '😭', '😱',
|
||||
'😖', '😣', '😞', '😓', '😩', '😫', '🥱', '😤', '😡', '😠',
|
||||
'🤬', '😈', '👿', '💀', '☠️', '💩', '🤡', '👹', '👺', '👻',
|
||||
|
||||
// Gestures & Body
|
||||
'👋', '🤚', '🖐️', '✋', '🖖', '👌', '🤌', '🤏', '✌️', '🤞',
|
||||
'🤟', '🤘', '🤙', '👈', '👉', '👆', '🖕', '👇', '☝️', '👍',
|
||||
'👎', '✊', '👊', '🤛', '🤜', '👏', '🙌', '👐', '🤲', '🤝',
|
||||
'🙏', '💪', '🦾', '🦿', '🦵', '🦶', '👂', '🦻', '👃', '🧠',
|
||||
|
||||
// Hearts & Love
|
||||
'❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍', '🤎', '💔',
|
||||
'❣️', '💕', '💞', '💓', '💗', '💖', '💘', '💝', '💟', '❤️🔥',
|
||||
|
||||
// Work & Office
|
||||
'💼', '📊', '📈', '📉', '💻', '⌨️', '🖥️', '🖨️', '🖱️', '💾',
|
||||
'💿', '📱', '☎️', '📞', '📟', '📠', '📧', '✉️', '📨', '📩',
|
||||
'📮', '📪', '📫', '📬', '📭', '📄', '📃', '📑', '📝', '✏️',
|
||||
'✒️', '🖊️', '🖋️', '📏', '📐', '📌', '📍', '🗂️', '📁', '📂',
|
||||
|
||||
// Success & Achievement
|
||||
'✅', '✔️', '☑️', '🎯', '🎖️', '🏆', '🥇', '🥈', '🥉', '⭐',
|
||||
'🌟', '✨', '💫', '🔥', '💥', '⚡', '💯', '🎉', '🎊', '🎈',
|
||||
|
||||
// Alerts & Symbols
|
||||
'⚠️', '🚫', '❌', '⛔', '🚷', '🚯', '🚱', '🚳', '🔞', '📵',
|
||||
'❗', '❓', '❕', '❔', '‼️', '⁉️', '💢', '💬', '💭', '🗯️',
|
||||
|
||||
// Time & Calendar
|
||||
'⏰', '⏱️', '⏲️', '⏳', '⌛', '📅', '📆', '🗓️', '📇', '🕐',
|
||||
'🕑', '🕒', '🕓', '🕔', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚',
|
||||
|
||||
// Actions & Arrows
|
||||
'🚀', '🎯', '🎲', '🎰', '🧩', '🔍', '🔎', '🔑', '🗝️', '🔒',
|
||||
'🔓', '🔐', '🔏', '🔔', '🔕', '📣', '📢', '💡', '🔦', '🏮',
|
||||
'➕', '➖', '✖️', '➗', '♾️', '‼️', '⁉️', '❓', '❔', '❕',
|
||||
'🔄', '🔃', '🔂', '▶️', '⏸️', '⏯️', '⏹️', '⏺️', '⏭️', '⏮️',
|
||||
'⏩', '⏪', '⏫', '⏬', '◀️', '🔼', '🔽', '➡️', '⬅️', '⬆️',
|
||||
'⬇️', '↗️', '↘️', '↙️', '↖️', '↕️', '↔️', '↪️', '↩️', '⤴️'
|
||||
];
|
||||
|
||||
const extractMentions = (text: string): string[] => {
|
||||
const mentionRegex = /@([\w\s]+)(?=\s|$|[.,!?])/g;
|
||||
const mentions = [];
|
||||
const mentions: string[] = [];
|
||||
let match;
|
||||
while ((match = mentionRegex.exec(text)) !== null) {
|
||||
if (match[1]) {
|
||||
mentions.push(match[1].trim());
|
||||
}
|
||||
}
|
||||
return mentions;
|
||||
};
|
||||
|
||||
@ -392,8 +484,8 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
|
||||
|
||||
return (
|
||||
<div className="h-screen max-h-screen flex flex-col bg-gray-50 overflow-hidden">
|
||||
{/* Header */}
|
||||
<div className="bg-white border-b border-gray-200 px-3 sm:px-6 py-4">
|
||||
{/* Header - Fixed at top */}
|
||||
<div className="bg-white border-b border-gray-200 px-3 sm:px-6 py-4 flex-shrink-0">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2 sm:gap-4 min-w-0 flex-1">
|
||||
<Button variant="ghost" size="icon" onClick={onBack} className="shrink-0">
|
||||
@ -456,9 +548,9 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
|
||||
<div className="flex-1 flex overflow-hidden relative">
|
||||
{/* Main Chat Area */}
|
||||
<div className="flex-1 flex flex-col min-w-0">
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col">
|
||||
{/* Tab Navigation */}
|
||||
<div className="bg-white border-b border-gray-200 px-2 sm:px-3 lg:px-6">
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col overflow-hidden">
|
||||
{/* Tab Navigation - Fixed */}
|
||||
<div className="bg-white border-b border-gray-200 px-2 sm:px-3 lg:px-6 flex-shrink-0">
|
||||
<TabsList className="grid w-full max-w-full sm:max-w-md grid-cols-3 bg-gray-100 h-10">
|
||||
<TabsTrigger value="chat" className="flex items-center gap-1 sm:gap-2 text-xs sm:text-sm px-2">
|
||||
<MessageSquare className="w-3 h-3 sm:w-4 sm:h-4" />
|
||||
@ -478,9 +570,9 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
|
||||
</div>
|
||||
|
||||
{/* Chat Tab */}
|
||||
<TabsContent value="chat" className="flex-1 flex flex-col m-0">
|
||||
{/* Search Bar */}
|
||||
<div className="bg-white border-b border-gray-200 px-2 sm:px-3 lg:px-6 py-2 sm:py-3">
|
||||
<TabsContent value="chat" className="flex-1 flex flex-col m-0 overflow-hidden min-h-0">
|
||||
{/* Search Bar - Fixed */}
|
||||
<div className="bg-white border-b border-gray-200 px-2 sm:px-3 lg:px-6 py-2 sm:py-3 flex-shrink-0">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
|
||||
<Input
|
||||
@ -492,8 +584,8 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Messages Area */}
|
||||
<div className="flex-1 overflow-y-auto px-2 sm:px-3 lg:px-6 py-2 sm:py-4">
|
||||
{/* Messages Area - Fixed height with proper scrolling */}
|
||||
<div className="flex-1 overflow-y-auto overflow-x-hidden px-2 sm:px-3 lg:px-6 py-2 sm:py-4 min-h-0">
|
||||
<div className="space-y-3 sm:space-y-6 max-w-full">
|
||||
{filteredMessages.map((msg) => (
|
||||
<div key={msg.id} className={`flex gap-2 sm:gap-3 lg:gap-4 ${msg.isSystem ? 'justify-center' : ''}`}>
|
||||
@ -617,11 +709,42 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Message Input */}
|
||||
<div className="bg-white border-t border-gray-200 p-2 sm:p-3 lg:p-6">
|
||||
{/* Message Input - Fixed at bottom */}
|
||||
<div className="bg-white border-t border-gray-200 p-2 sm:p-3 lg:p-6 flex-shrink-0">
|
||||
<div className="max-w-full">
|
||||
<div className="flex flex-col gap-2 sm:gap-4">
|
||||
<div className="flex-1">
|
||||
{/* Hidden File Input */}
|
||||
<input
|
||||
type="file"
|
||||
ref={fileInputRef}
|
||||
onChange={handleFileSelect}
|
||||
className="hidden"
|
||||
multiple
|
||||
accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt"
|
||||
/>
|
||||
|
||||
{/* Selected Files Preview - Scrollable if many files */}
|
||||
{selectedFiles.length > 0 && (
|
||||
<div className="mb-3 space-y-2 max-h-32 overflow-y-auto pr-2">
|
||||
{selectedFiles.map((file, index) => (
|
||||
<div key={index} className="flex items-center gap-2 p-2 bg-blue-50 rounded-lg border border-blue-200">
|
||||
<span className="text-lg flex-shrink-0">{getFileIcon(file.type.split('/')[1] || 'file')}</span>
|
||||
<span className="text-sm text-gray-700 flex-1 truncate min-w-0">{file.name}</span>
|
||||
<span className="text-xs text-gray-500 flex-shrink-0">{(file.size / 1024).toFixed(1)} KB</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => handleRemoveFile(index)}
|
||||
className="h-6 w-6 p-0 hover:bg-red-100 flex-shrink-0"
|
||||
>
|
||||
<X className="h-3 w-3 text-red-600" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Textarea with Emoji Picker */}
|
||||
<div className="relative mb-2">
|
||||
<Textarea
|
||||
placeholder="Type your message... Use @username to mention someone"
|
||||
value={message}
|
||||
@ -630,44 +753,101 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
|
||||
className="min-h-[50px] sm:min-h-[60px] resize-none border-gray-200 focus:ring-blue-500 focus:border-blue-500 w-full text-sm"
|
||||
rows={2}
|
||||
/>
|
||||
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center mt-2 gap-2">
|
||||
<div className="flex items-center gap-1 sm:gap-2 order-2 sm:order-1">
|
||||
<Button variant="ghost" size="sm" className="text-gray-500 h-7 w-7 sm:h-8 sm:w-8 p-0">
|
||||
<Paperclip className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
|
||||
{/* Emoji Picker Popup */}
|
||||
{showEmojiPicker && (
|
||||
<div className="absolute bottom-full left-0 mb-2 bg-white border border-gray-200 rounded-lg shadow-xl p-3 z-50 w-full sm:w-96 max-h-80 overflow-y-auto">
|
||||
<div className="flex items-center justify-between mb-3 sticky top-0 bg-white pb-2 border-b">
|
||||
<span className="text-sm font-semibold text-gray-700">Pick an emoji</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setShowEmojiPicker(false)}
|
||||
className="h-6 w-6 p-0"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" className="text-gray-500 h-7 w-7 sm:h-8 sm:w-8 p-0">
|
||||
<Smile className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
</div>
|
||||
<div className="grid grid-cols-8 sm:grid-cols-10 gap-1">
|
||||
{emojiList.map((emoji, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => handleEmojiSelect(emoji)}
|
||||
className="text-xl sm:text-2xl hover:bg-gray-100 rounded p-1 transition-colors flex items-center justify-center"
|
||||
title={emoji}
|
||||
>
|
||||
{emoji}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Action Buttons Row - Always visible */}
|
||||
<div className="flex items-center justify-between gap-2 flex-shrink-0">
|
||||
{/* Left side - Action buttons */}
|
||||
<div className="flex items-center gap-1 sm:gap-2 flex-shrink-0">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-gray-500 h-8 w-8 p-0 hover:bg-blue-50 hover:text-blue-600 flex-shrink-0"
|
||||
onClick={handleAttachmentClick}
|
||||
title="Attach file"
|
||||
>
|
||||
<Paperclip className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" className="text-gray-500 h-7 w-7 sm:h-8 sm:w-8 p-0 hidden sm:flex">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-gray-500 h-8 w-8 p-0 hover:bg-blue-50 hover:text-blue-600 flex-shrink-0"
|
||||
onClick={() => setShowEmojiPicker(!showEmojiPicker)}
|
||||
title="Add emoji"
|
||||
>
|
||||
<Smile className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-gray-500 h-8 w-8 p-0 hidden sm:flex hover:bg-blue-50 hover:text-blue-600 flex-shrink-0"
|
||||
onClick={() => setMessage(prev => prev + '@')}
|
||||
title="Mention someone"
|
||||
>
|
||||
<AtSign className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" className="text-gray-500 h-7 w-7 sm:h-8 sm:w-8 p-0 hidden sm:flex">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-gray-500 h-8 w-8 p-0 hidden sm:flex hover:bg-blue-50 hover:text-blue-600 flex-shrink-0"
|
||||
onClick={() => setMessage(prev => prev + '#')}
|
||||
title="Add hashtag"
|
||||
>
|
||||
<Hash className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 order-1 sm:order-2">
|
||||
<span className="text-xs text-gray-500 hidden sm:inline">
|
||||
|
||||
{/* Right side - Character count and Send button */}
|
||||
<div className="flex items-center gap-2 ml-auto flex-shrink-0">
|
||||
<span className="text-xs text-gray-500 hidden md:inline whitespace-nowrap">
|
||||
{message.length}/2000
|
||||
</span>
|
||||
<Button
|
||||
onClick={handleSendMessage}
|
||||
disabled={!message.trim()}
|
||||
className="bg-blue-600 hover:bg-blue-700 min-w-0 h-8 sm:h-9"
|
||||
disabled={!message.trim() && selectedFiles.length === 0}
|
||||
className="bg-blue-600 hover:bg-blue-700 h-8 sm:h-9 px-3 sm:px-4 disabled:opacity-50 disabled:cursor-not-allowed flex-shrink-0"
|
||||
size="sm"
|
||||
>
|
||||
<Send className="h-3 w-3 sm:h-4 sm:w-4 sm:mr-2" />
|
||||
<span className="hidden sm:inline ml-1">Send</span>
|
||||
<Send className="h-4 w-4 sm:mr-2" />
|
||||
<span className="hidden sm:inline">Send</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
{/* Files Tab */}
|
||||
<TabsContent value="files" className="flex-1 p-2 sm:p-3 lg:p-6 m-0">
|
||||
<TabsContent value="files" className="flex-1 p-2 sm:p-3 lg:p-6 m-0 pt-0">
|
||||
<div className="max-w-full">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between mb-4 sm:mb-6 gap-3">
|
||||
<h3 className="text-base sm:text-lg font-semibold text-gray-900">Shared Files</h3>
|
||||
@ -714,7 +894,7 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
|
||||
</TabsContent>
|
||||
|
||||
{/* Activity Tab */}
|
||||
<TabsContent value="activity" className="flex-1 p-2 sm:p-3 lg:p-6 m-0">
|
||||
<TabsContent value="activity" className="flex-1 p-2 sm:p-3 lg:p-6 m-0 pt-0">
|
||||
<div className="max-w-full">
|
||||
<h3 className="text-base sm:text-lg font-semibold text-gray-900 mb-4 sm:mb-6">Recent Activity</h3>
|
||||
<div className="space-y-3 sm:space-y-4">
|
||||
|
||||
@ -604,6 +604,30 @@
|
||||
[data-slot="dialog-content"] {
|
||||
background-color: rgb(255 255 255) !important;
|
||||
}
|
||||
|
||||
/* Custom scrollbar for better UX */
|
||||
.overflow-y-auto::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.overflow-y-auto::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.overflow-y-auto::-webkit-scrollbar-thumb {
|
||||
background: rgb(203 213 225);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.overflow-y-auto::-webkit-scrollbar-thumb:hover {
|
||||
background: rgb(148 163 184);
|
||||
}
|
||||
|
||||
/* Firefox scrollbar */
|
||||
.overflow-y-auto {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgb(203 213 225) transparent;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user