fix: use actual lucide Footprints icon for trace badges
Replace hand-drawn teardrop paths (looked like plants) with the real lucide Footprints SVG paths. Configured = bare teal icon, data captured = white icon in solid teal circle with staggered pulse rings. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import React from 'react';
|
||||
import type { NodeConfig } from './types';
|
||||
|
||||
const BADGE_SIZE = 18;
|
||||
const BADGE_GAP = 4;
|
||||
const TRACE_ENABLED_COLOR = '#1A7F8E'; // teal — tracing configured
|
||||
const TRACE_DATA_COLOR = '#3D7C47'; // green — data captured
|
||||
const TRACE_COLOR = '#1A7F8E'; // teal
|
||||
const TAP_COLOR = '#7C3AED'; // purple
|
||||
|
||||
interface ConfigBadgeProps {
|
||||
nodeWidth: number;
|
||||
@@ -12,45 +13,78 @@ interface ConfigBadgeProps {
|
||||
hasTraceData?: boolean;
|
||||
}
|
||||
|
||||
export function ConfigBadge({ nodeWidth, config, hasTraceData }: ConfigBadgeProps) {
|
||||
const badges: { icon: 'tap' | 'trace'; color: string }[] = [];
|
||||
if (config.tapExpression) badges.push({ icon: 'tap', color: '#7C3AED' });
|
||||
// Show trace badge if tracing is enabled OR data was captured
|
||||
if (config.traceEnabled || hasTraceData) {
|
||||
badges.push({ icon: 'trace', color: hasTraceData ? TRACE_DATA_COLOR : TRACE_ENABLED_COLOR });
|
||||
}
|
||||
if (badges.length === 0) return null;
|
||||
|
||||
let xOffset = nodeWidth;
|
||||
/** Lucide Footprints icon (24x24 viewBox) scaled to fit badge */
|
||||
function FootprintsIcon({ color, size }: { color: string; size: number }) {
|
||||
const scale = size / 24;
|
||||
return (
|
||||
<g className="config-badges">
|
||||
{badges.map((badge, i) => {
|
||||
xOffset -= BADGE_SIZE + (i > 0 ? BADGE_GAP : 0);
|
||||
return (
|
||||
<g key={badge.icon} transform={`translate(${xOffset}, ${-BADGE_SIZE - 4})`}>
|
||||
<circle
|
||||
cx={BADGE_SIZE / 2}
|
||||
cy={BADGE_SIZE / 2}
|
||||
r={BADGE_SIZE / 2}
|
||||
fill={badge.color}
|
||||
/>
|
||||
{badge.icon === 'tap' ? (
|
||||
/* Droplets icon (simplified) */
|
||||
<g transform="translate(4, 4)" stroke="white" strokeWidth={1.4} fill="none" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M5 1 C5 1 2 4.5 2 6.5a3 3 0 006 0C8 4.5 5 1 5 1z" />
|
||||
</g>
|
||||
) : (
|
||||
/* Footprints icon (simplified) */
|
||||
<g transform="translate(3.5, 3)" stroke="white" strokeWidth={1.3} fill="none" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M4 1c0 0-1.5 2-1.5 3.5a1.5 1.5 0 003 0C5.5 3 4 1 4 1z" />
|
||||
<path d="M7.5 4c0 0-1 1.5-1 2.5a1 1 0 002 0c0-1-1-2.5-1-2.5z" />
|
||||
<line x1="3.5" y1="7" x2="3" y2="9.5" />
|
||||
<line x1="7" y1="8" x2="7.5" y2="10" />
|
||||
</g>
|
||||
)}
|
||||
</g>
|
||||
);
|
||||
})}
|
||||
<g transform={`scale(${scale})`} stroke={color} strokeWidth={2} fill="none" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M4 16v-2.38C4 11.5 2.97 10.5 3 8c.03-2.72 1.49-6 4.5-6C9.37 2 10 3.8 10 5.5c0 3.11-2 5.66-2 8.68V16a2 2 0 1 1-4 0Z" />
|
||||
<path d="M20 20v-2.38c0-2.12 1.03-3.12 1-5.62-.03-2.72-1.49-6-4.5-6C14.63 6 14 7.8 14 9.5c0 3.11 2 5.66 2 8.68V20a2 2 0 1 0 4 0Z" />
|
||||
<path d="M16 17h4" />
|
||||
<path d="M4 13h4" />
|
||||
</g>
|
||||
);
|
||||
}
|
||||
|
||||
export function ConfigBadge({ nodeWidth, config, hasTraceData }: ConfigBadgeProps) {
|
||||
const showTap = !!config.tapExpression;
|
||||
const showTrace = config.traceEnabled || hasTraceData;
|
||||
if (!showTap && !showTrace) return null;
|
||||
|
||||
const badges: React.ReactNode[] = [];
|
||||
let xOffset = nodeWidth;
|
||||
|
||||
// Tap badge: always solid purple circle with white droplet icon
|
||||
if (showTap) {
|
||||
xOffset -= BADGE_SIZE;
|
||||
const cx = BADGE_SIZE / 2;
|
||||
const cy = BADGE_SIZE / 2;
|
||||
badges.push(
|
||||
<g key="tap" transform={`translate(${xOffset}, ${-BADGE_SIZE - 4})`}>
|
||||
<circle cx={cx} cy={cy} r={BADGE_SIZE / 2} fill={TAP_COLOR} />
|
||||
<g transform="translate(4, 4)" stroke="white" strokeWidth={1.4} fill="none" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M5 1 C5 1 2 4.5 2 6.5a3 3 0 006 0C8 4.5 5 1 5 1z" />
|
||||
</g>
|
||||
</g>,
|
||||
);
|
||||
}
|
||||
|
||||
// Trace badge
|
||||
if (showTrace) {
|
||||
xOffset -= BADGE_SIZE + (showTap ? BADGE_GAP : 0);
|
||||
const cx = BADGE_SIZE / 2;
|
||||
const cy = BADGE_SIZE / 2;
|
||||
const r = BADGE_SIZE / 2;
|
||||
|
||||
if (hasTraceData) {
|
||||
// Data captured: solid teal circle, white icon, pulsing rings
|
||||
badges.push(
|
||||
<g key="trace" transform={`translate(${xOffset}, ${-BADGE_SIZE - 4})`}>
|
||||
<circle cx={cx} cy={cy} r={r} fill="none" stroke={TRACE_COLOR} strokeWidth={2} opacity={0.5}>
|
||||
<animate attributeName="r" values={`${r};${r + 8}`} dur="1.5s" repeatCount="indefinite" />
|
||||
<animate attributeName="opacity" values="0.5;0" dur="1.5s" repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx={cx} cy={cy} r={r} fill="none" stroke={TRACE_COLOR} strokeWidth={2} opacity={0.5}>
|
||||
<animate attributeName="r" values={`${r};${r + 8}`} dur="1.5s" begin="0.75s" repeatCount="indefinite" />
|
||||
<animate attributeName="opacity" values="0.5;0" dur="1.5s" begin="0.75s" repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx={cx} cy={cy} r={r} fill={TRACE_COLOR} />
|
||||
<g transform={`translate(${(BADGE_SIZE - 14) / 2}, ${(BADGE_SIZE - 14) / 2})`}>
|
||||
<FootprintsIcon color="white" size={14} />
|
||||
</g>
|
||||
</g>,
|
||||
);
|
||||
} else {
|
||||
// Configured only: bare teal icon, no circle background
|
||||
badges.push(
|
||||
<g key="trace" transform={`translate(${xOffset}, ${-BADGE_SIZE - 4})`}>
|
||||
<g transform={`translate(${(BADGE_SIZE - 14) / 2}, ${(BADGE_SIZE - 14) / 2})`}>
|
||||
<FootprintsIcon color={TRACE_COLOR} size={14} />
|
||||
</g>
|
||||
</g>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return <g className="config-badges">{badges}</g>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user