diff --git a/frontend/src/components/ChatInterface.tsx b/frontend/src/components/ChatInterface.tsx index 985467e..da0c189 100644 --- a/frontend/src/components/ChatInterface.tsx +++ b/frontend/src/components/ChatInterface.tsx @@ -38,22 +38,26 @@ const ChatInterface: React.FC = () => { } }, [messageText]); + const copyToClipboardFallback = (text: string) => { + const textArea = document.createElement('textarea'); + textArea.value = text; + textArea.style.position = 'fixed'; + textArea.style.left = '-9999px'; + textArea.style.top = '-9999px'; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + }; + const handleCopyMessage = async (messageId: string, content: string) => { try { - if (navigator.clipboard && window.isSecureContext) { + try { await navigator.clipboard.writeText(content); - } else { - // Fallback for iframe/non-secure contexts (SharePoint) - const textArea = document.createElement('textarea'); - textArea.value = content; - textArea.style.position = 'fixed'; - textArea.style.left = '-9999px'; - textArea.style.top = '-9999px'; - document.body.appendChild(textArea); - textArea.focus(); - textArea.select(); - document.execCommand('copy'); - document.body.removeChild(textArea); + } catch { + // Clipboard API failed (iframe/permissions) — use fallback + copyToClipboardFallback(content); } setCopiedMessageId(messageId); setTimeout(() => setCopiedMessageId(null), 2000); diff --git a/frontend/src/styles/components.css b/frontend/src/styles/components.css index 67ed035..e1e2529 100644 --- a/frontend/src/styles/components.css +++ b/frontend/src/styles/components.css @@ -156,7 +156,7 @@ border-radius: var(--radius-md); box-shadow: var(--shadow-sm); font-size: var(--font-size-base); - line-height: 1.6; + line-height: 1.3; color: var(--text-primary); }