feat(insights): bouton Fit view sur le graphe — reset zoom + clear focus
- zoomRef stocke le behavior d3.zoom pour accès externe au useEffect - handleFitView: d3.zoomIdentity reset (600ms transition) + clear selectedClusterId - Bouton Maximize2 en haut à droite du graphe avec aria-label - cursor-pointer + focus-visible:ring pour a11y
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useEffect, useRef } from 'react'
|
||||
import * as d3 from 'd3'
|
||||
import { Maximize2 } from 'lucide-react'
|
||||
|
||||
interface Note {
|
||||
id: string
|
||||
@@ -49,6 +50,7 @@ export function NetworkGraph({
|
||||
}: NetworkGraphProps) {
|
||||
const svgRef = useRef<SVGSVGElement>(null)
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const zoomRef = useRef<any>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (!svgRef.current || !containerRef.current) return
|
||||
@@ -67,6 +69,7 @@ export function NetworkGraph({
|
||||
g.attr('transform', event.transform)
|
||||
})
|
||||
|
||||
zoomRef.current = zoom
|
||||
svg.call(zoom as any)
|
||||
|
||||
// Filter notes with cluster assignments
|
||||
@@ -348,6 +351,15 @@ export function NetworkGraph({
|
||||
}
|
||||
}, [notes, clusters, bridgeNotes, onNoteSelect, selectedClusterId])
|
||||
|
||||
const handleFitView = () => {
|
||||
if (!svgRef.current || !zoomRef.current) return
|
||||
d3.select(svgRef.current)
|
||||
.transition()
|
||||
.duration(600)
|
||||
.call(zoomRef.current.transform, d3.zoomIdentity)
|
||||
onClusterSelect?.(null)
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="w-full h-full bg-paper dark:bg-[#121212] rounded-3xl overflow-hidden border border-border/40 relative">
|
||||
{/* Pastilles de cluster — cliquables pour activer le focus */}
|
||||
@@ -378,6 +390,15 @@ export function NetworkGraph({
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{/* Fit view button */}
|
||||
<button
|
||||
onClick={handleFitView}
|
||||
className="absolute top-6 right-6 z-10 flex items-center gap-1.5 px-3 py-1.5 rounded-full border border-border/40 bg-white/90 dark:bg-black/80 text-concrete hover:text-ink dark:hover:text-dark-ink hover:border-concrete/40 text-[9px] font-bold uppercase tracking-wider transition-all shadow-sm cursor-pointer focus-visible:ring-2 focus-visible:ring-ochre/50 focus-visible:outline-none backdrop-blur-sm"
|
||||
aria-label={fitViewLabel}
|
||||
>
|
||||
<Maximize2 size={11} />
|
||||
{fitViewLabel}
|
||||
</button>
|
||||
<svg ref={svgRef} className="w-full h-full" />
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user