From 63e16d26858fadfd746eb5355e4f4a1862572b89 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 24 Mar 2026 23:06:55 +0100 Subject: [PATCH] feat: add generic badge system to RouteFlow and ProcessorTimeline New NodeBadge interface with variant colors (info/success/warning/error) and optional onClick. Replaces single-purpose bottleneckBadge with a flexible badges array. Backwards compatible: isBottleneck still works. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ProcessorTimeline.module.css | 19 +++++++++++++++ .../ProcessorTimeline/ProcessorTimeline.tsx | 12 ++++++++++ .../composites/RouteFlow/RouteFlow.module.css | 22 ++++++++++++++---- .../composites/RouteFlow/RouteFlow.tsx | 23 ++++++++++++++++++- src/design-system/composites/index.ts | 2 +- 5 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/design-system/composites/ProcessorTimeline/ProcessorTimeline.module.css b/src/design-system/composites/ProcessorTimeline/ProcessorTimeline.module.css index 187b1ba..7c88f9b 100644 --- a/src/design-system/composites/ProcessorTimeline/ProcessorTimeline.module.css +++ b/src/design-system/composites/ProcessorTimeline/ProcessorTimeline.module.css @@ -129,6 +129,25 @@ color: var(--text-primary); } +/* Badges */ +.badge { + font-family: var(--font-mono); + font-size: 7px; + font-weight: 600; + color: #fff; + border-radius: 6px; + padding: 0 4px; + text-transform: uppercase; + white-space: nowrap; + margin-left: 4px; + vertical-align: middle; +} + +.badgeInfo { background: var(--running); } +.badgeSuccess { background: var(--success); } +.badgeWarning { background: var(--amber); } +.badgeError { background: var(--error); } + .empty { color: var(--text-muted); font-size: 12px; diff --git a/src/design-system/composites/ProcessorTimeline/ProcessorTimeline.tsx b/src/design-system/composites/ProcessorTimeline/ProcessorTimeline.tsx index 937aebe..1a147b9 100644 --- a/src/design-system/composites/ProcessorTimeline/ProcessorTimeline.tsx +++ b/src/design-system/composites/ProcessorTimeline/ProcessorTimeline.tsx @@ -1,6 +1,7 @@ import type { ReactNode } from 'react' import styles from './ProcessorTimeline.module.css' import { Dropdown } from '../Dropdown/Dropdown' +import type { NodeBadge } from '../RouteFlow/RouteFlow' export interface ProcessorStep { name: string @@ -8,6 +9,7 @@ export interface ProcessorStep { durationMs: number status: 'ok' | 'slow' | 'fail' startMs: number + badges?: NodeBadge[] } export interface ProcessorAction { @@ -84,6 +86,16 @@ export function ProcessorTimeline({ >
{proc.name} + {proc.badges?.map((badge, bi) => ( + { e.stopPropagation(); badge.onClick!() } : undefined} + style={badge.onClick ? { cursor: 'pointer' } : undefined} + > + {badge.label} + + ))}
void +} + export interface RouteNode { name: string type: 'from' | 'process' | 'to' | 'choice' | 'error-handler' durationMs: number status: 'ok' | 'slow' | 'fail' isBottleneck?: boolean + badges?: NodeBadge[] } export interface NodeAction { @@ -132,7 +139,21 @@ export function RouteFlow({ nodes, onNodeClick, selectedIndex, actions, getActio } }} > - {node.isBottleneck && BOTTLENECK} + {(node.isBottleneck || node.badges?.length) ? ( + + {node.isBottleneck && BOTTLENECK} + {node.badges?.map((badge, bi) => ( + { e.stopPropagation(); badge.onClick!() } : undefined} + style={badge.onClick ? { cursor: 'pointer' } : undefined} + > + {badge.label} + + ))} + + ) : null}
{TYPE_ICONS[node.type] ?? '\u25A2'}
diff --git a/src/design-system/composites/index.ts b/src/design-system/composites/index.ts index 4fc92a8..947dd89 100644 --- a/src/design-system/composites/index.ts +++ b/src/design-system/composites/index.ts @@ -34,7 +34,7 @@ export { Popover } from './Popover/Popover' export { ProcessorTimeline } from './ProcessorTimeline/ProcessorTimeline' export type { ProcessorStep, ProcessorAction } from './ProcessorTimeline/ProcessorTimeline' export { RouteFlow } from './RouteFlow/RouteFlow' -export type { RouteNode, NodeAction } from './RouteFlow/RouteFlow' +export type { RouteNode, NodeAction, NodeBadge } from './RouteFlow/RouteFlow' export { ShortcutsBar } from './ShortcutsBar/ShortcutsBar' export { SegmentedTabs } from './SegmentedTabs/SegmentedTabs' export { SplitPane } from './SplitPane/SplitPane'