fix: restyle sankey to match reference - thinner nodes, all labels, scrollable
- Switch to fixed-width Sankey with horizontal scroll (250px per step) - Thinner nodes (8px), tighter spacing (8px) - Labels on all columns, not just first/last - Lower link opacity (0.15) for cleaner look - Increased node cap to 25 per step
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { ResponsiveSankey } from '@nivo/sankey'
|
import { Sankey } from '@nivo/sankey'
|
||||||
import { TreeStructure, X } from '@phosphor-icons/react'
|
import { TreeStructure, X } from '@phosphor-icons/react'
|
||||||
import type { PathTransition } from '@/lib/api/journeys'
|
import type { PathTransition } from '@/lib/api/journeys'
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ const COLUMN_COLORS = [
|
|||||||
'#EC4899', '#06B6D4', '#EF4444', '#84CC16', '#F97316', '#6366F1',
|
'#EC4899', '#06B6D4', '#EF4444', '#84CC16', '#F97316', '#6366F1',
|
||||||
]
|
]
|
||||||
|
|
||||||
const MAX_NODES_PER_STEP = 15
|
const MAX_NODES_PER_STEP = 25
|
||||||
|
|
||||||
// ─── Helpers ────────────────────────────────────────────────────────
|
// ─── Helpers ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -257,9 +257,11 @@ export default function SankeyJourney({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const labelColor = isDark ? '#a3a3a3' : '#525252'
|
const labelColor = isDark ? '#a3a3a3' : '#525252'
|
||||||
const steps = data.nodes.map((n) => n.stepIndex)
|
|
||||||
const minStep = Math.min(...steps)
|
// Calculate dimensions: give each step ~250px of horizontal space
|
||||||
const maxStep = Math.max(...steps)
|
const numSteps = new Set(data.nodes.map((n) => n.stepIndex)).size
|
||||||
|
const chartWidth = Math.max(800, numSteps * 250)
|
||||||
|
const chartHeight = 500
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -283,38 +285,35 @@ export default function SankeyJourney({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div style={{ height: 500 }}>
|
<div className="overflow-x-auto -mx-6 px-6" style={{ maxHeight: chartHeight + 16 }}>
|
||||||
<ResponsiveSankey<SankeyNode, SankeyLink>
|
<div style={{ width: chartWidth, height: chartHeight }}>
|
||||||
|
<Sankey<SankeyNode, SankeyLink>
|
||||||
data={data}
|
data={data}
|
||||||
margin={{ top: 8, right: 140, bottom: 8, left: 140 }}
|
width={chartWidth}
|
||||||
|
height={chartHeight}
|
||||||
|
margin={{ top: 8, right: 160, bottom: 8, left: 160 }}
|
||||||
align="justify"
|
align="justify"
|
||||||
sort="descending"
|
sort="descending"
|
||||||
colors={(node) =>
|
colors={(node) =>
|
||||||
COLUMN_COLORS[node.stepIndex % COLUMN_COLORS.length]
|
COLUMN_COLORS[node.stepIndex % COLUMN_COLORS.length]
|
||||||
}
|
}
|
||||||
nodeThickness={12}
|
nodeThickness={8}
|
||||||
nodeSpacing={20}
|
nodeSpacing={8}
|
||||||
nodeInnerPadding={0}
|
nodeInnerPadding={0}
|
||||||
nodeBorderWidth={0}
|
nodeBorderWidth={0}
|
||||||
nodeBorderRadius={3}
|
nodeBorderRadius={2}
|
||||||
nodeOpacity={1}
|
nodeOpacity={1}
|
||||||
nodeHoverOpacity={1}
|
nodeHoverOpacity={1}
|
||||||
nodeHoverOthersOpacity={0.3}
|
nodeHoverOthersOpacity={0.3}
|
||||||
linkOpacity={0.2}
|
linkOpacity={0.15}
|
||||||
linkHoverOpacity={0.5}
|
linkHoverOpacity={0.5}
|
||||||
linkHoverOthersOpacity={0.05}
|
linkHoverOthersOpacity={0.03}
|
||||||
linkContract={2}
|
linkContract={1}
|
||||||
enableLinkGradient
|
enableLinkGradient
|
||||||
enableLabels
|
enableLabels
|
||||||
label={(node) => {
|
label={(node) => smartLabel(pathFromId(node.id))}
|
||||||
// Only show labels for first and last step columns
|
|
||||||
if (node.stepIndex === minStep || node.stepIndex === maxStep) {
|
|
||||||
return smartLabel(pathFromId(node.id))
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
}}
|
|
||||||
labelPosition="outside"
|
labelPosition="outside"
|
||||||
labelPadding={8}
|
labelPadding={6}
|
||||||
labelTextColor={labelColor}
|
labelTextColor={labelColor}
|
||||||
isInteractive
|
isInteractive
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
@@ -352,5 +351,6 @@ export default function SankeyJourney({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user