From 4103014cdb668c922fddf71cbc342fc5a4bb8986 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Sun, 15 Mar 2026 12:28:43 +0100 Subject: [PATCH] fix: restyle journey columns to match Pirsch card-based design --- components/journeys/ColumnJourney.tsx | 78 +++++++++++---------------- 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/components/journeys/ColumnJourney.tsx b/components/journeys/ColumnJourney.tsx index 025795d..570fc56 100644 --- a/components/journeys/ColumnJourney.tsx +++ b/components/journeys/ColumnJourney.tsx @@ -64,9 +64,6 @@ function buildColumns( const numCols = depth + 1 const columns: Column[] = [] - // Build a filtered transitions set based on selections - // For each column N with a selection, only keep transitions at step_index=N - // where from_path matches the selection let filteredTransitions = transitions for (let col = 0; col < numCols - 1; col++) { @@ -82,14 +79,12 @@ function buildColumns( const pageMap = new Map() if (col === 0) { - // Column 0: aggregate from_path across step_index=0 for (const t of filteredTransitions) { if (t.step_index === 0) { pageMap.set(t.from_path, (pageMap.get(t.from_path) ?? 0) + t.session_count) } } } else { - // Column N: aggregate to_path across step_index=N-1 for (const t of filteredTransitions) { if (t.step_index === col - 1) { pageMap.set(t.to_path, (pageMap.get(t.to_path) ?? 0) + t.session_count) @@ -97,12 +92,10 @@ function buildColumns( } } - // Sort descending by count let pages = Array.from(pageMap.entries()) .map(([path, sessionCount]) => ({ path, sessionCount })) .sort((a, b) => b.sessionCount - a.sessionCount) - // Cap and merge into (other) if (pages.length > MAX_NODES_PER_COLUMN) { const kept = pages.slice(0, MAX_NODES_PER_COLUMN) const otherCount = pages @@ -135,23 +128,20 @@ function ColumnHeader({ color: string }) { return ( -
+
{column.index + 1} -
- - {column.totalSessions.toLocaleString()} - - - visitors +
+ + {column.totalSessions.toLocaleString()} visitors {column.dropOffPercent !== 0 && ( @@ -191,42 +181,39 @@ function PageRow({ data-path={page.path} className={` group flex items-center justify-between w-full - h-9 px-2 rounded-lg text-left transition-colors + px-3 py-2.5 rounded-lg text-left transition-all ${isOther ? 'cursor-default' : 'cursor-pointer'} ${ isSelected - ? 'bg-brand-orange/10 dark:bg-brand-orange/15 ring-1 ring-brand-orange/30' + ? 'bg-neutral-900 dark:bg-white border border-neutral-900 dark:border-white' : isOther - ? '' - : 'hover:bg-neutral-50 dark:hover:bg-neutral-800/50' + ? 'border border-neutral-100 dark:border-neutral-800' + : 'border border-neutral-200 dark:border-neutral-700 hover:border-neutral-300 dark:hover:border-neutral-600 hover:shadow-sm' } `} > {isOther ? page.path : smartLabel(page.path)} -
- {!isOther && ( - - {pct}% - - )} - - {page.sessionCount.toLocaleString()} - -
+ : 'text-neutral-900 dark:text-white' + }`} + > + {page.sessionCount.toLocaleString()} +
) } @@ -244,7 +231,7 @@ function JourneyColumn({ }) { if (column.pages.length === 0) { return ( -
+
@@ -256,9 +243,9 @@ function JourneyColumn({ } return ( -
+
-
+
{column.pages.map((page) => { const isOther = page.path === '(other)' return ( @@ -315,7 +302,6 @@ function ConnectionLines({ const nextCol = columns[colIdx + 1] if (!nextCol) continue - // Find the source row element const sourceEl = container.querySelector( `[data-col="${colIdx}"][data-path="${CSS.escape(selectedPath)}"]` ) as HTMLElement | null @@ -326,7 +312,6 @@ function ConnectionLines({ sourceRect.top + sourceRect.height / 2 - containerRect.top + container.scrollTop const sourceX = sourceRect.right - containerRect.left + container.scrollLeft - // Find matching transitions const relevantTransitions = transitions.filter( (t) => t.step_index === colIdx && t.from_path === selectedPath ) @@ -371,7 +356,7 @@ function ConnectionLines({ d={`M ${line.sourceX},${line.sourceY} C ${midX},${line.sourceY} ${midX},${line.destY} ${line.destX},${line.destY}`} stroke={line.color} strokeWidth={line.weight} - strokeOpacity={0.3} + strokeOpacity={0.35} fill="none" /> ) @@ -409,7 +394,6 @@ export default function ColumnJourney({ const handleSelect = useCallback( (colIndex: number, path: string) => { - // Column 0 click → set entry path filter (API-level) if (colIndex === 0 && onNodeClick) { onNodeClick(path) return @@ -417,13 +401,11 @@ export default function ColumnJourney({ setSelections((prev) => { const next = new Map(prev) - // Toggle: click same page deselects if (next.get(colIndex) === path) { next.delete(colIndex) } else { next.set(colIndex, path) } - // Clear all selections after this column for (const key of Array.from(next.keys())) { if (key > colIndex) next.delete(key) } @@ -456,7 +438,7 @@ export default function ColumnJourney({ ref={containerRef} className="overflow-x-auto -mx-6 px-6 pb-2 relative" > -
+
{columns.map((col) => (