diff --git a/web/src/components/consensus/ConsensusComplete.tsx b/web/src/components/consensus/ConsensusComplete.tsx index 2de7c5e..84035da 100644 --- a/web/src/components/consensus/ConsensusComplete.tsx +++ b/web/src/components/consensus/ConsensusComplete.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useState, useRef, useEffect } from 'react' import { GlassPanel, GlowButton, Markdown, Disclosure } from '@/components/shared' import { ConfidenceMeter } from './ConfidenceMeter' import { DissentBanner } from './DissentBanner' @@ -103,8 +103,21 @@ function downloadFile(content: string | Blob, filename: string, mimeType: string export function ConsensusComplete({ decision, confidence, rigor, dissent, cost, usage, collapsible, overview }: ConsensusCompleteProps) { const [copied, setCopied] = useState(false) const [exportOpen, setExportOpen] = useState(false) + const exportRef = useRef(null) const { question, rounds, threadId } = useConsensusStore() + // Close the export menu when clicking outside it + useEffect(() => { + if (!exportOpen) return + const handler = (e: MouseEvent) => { + if (exportRef.current && !exportRef.current.contains(e.target as Node)) { + setExportOpen(false) + } + } + document.addEventListener('mousedown', handler) + return () => document.removeEventListener('mousedown', handler) + }, [exportOpen]) + const handleCopy = async () => { await navigator.clipboard.writeText(overview ?? decision) setCopied(true) @@ -138,8 +151,50 @@ export function ConsensusComplete({ decision, confidence, rigor, dissent, cost, ) + const actions = ( +
+ + {copied ? 'Copied' : 'Copy'} + +
+ setExportOpen(!exportOpen)}> + Export + + {exportOpen && ( +
+ + + + +
+ )} +
+
+ ) + const body = ( <> + {actions} {overview ? ( <> {overview} @@ -152,45 +207,6 @@ export function ConsensusComplete({ decision, confidence, rigor, dissent, cost, ) : ( {decision} )} - -
- - {copied ? 'Copied' : 'Copy'} - -
- setExportOpen(!exportOpen)}> - Export - - {exportOpen && ( -
- - - - -
- )} -
-
)