reduces clickable space to the external link icon and the service name and added a tooltip to show truncated paths at the pointer
This commit is contained in:
@@ -671,27 +671,53 @@ function ServiceBadge({ svc, host, onEdit, onRemove }: { svc: ServiceInfo; host?
|
|||||||
const pathMaxWidth = Math.max(0, maxTotalWidth - nameWidth - 60);
|
const pathMaxWidth = Math.max(0, maxTotalWidth - nameWidth - 60);
|
||||||
const showPath = pathLabel && pathMaxWidth > 30;
|
const showPath = pathLabel && pathMaxWidth > 30;
|
||||||
|
|
||||||
|
const [tooltip, setTooltip] = useState<{ visible: boolean; x: number; y: number; text: string }>({ visible: false, x: 0, y: 0, text: '' });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="group flex items-center border rounded-md text-xs transition-colors px-2 py-1.5 min-w-0"
|
className="group flex items-center border rounded-md text-xs transition-colors px-2 py-1.5 min-w-0"
|
||||||
style={{ background: '#21262d', borderColor: '#30363d', position: 'relative' }}
|
style={{ background: '#21262d', borderColor: '#30363d', position: 'relative' }}
|
||||||
>
|
>
|
||||||
<span className="shrink-0 w-1.5 h-1.5 rounded-full mr-1" style={{ backgroundColor: color }} />
|
<span className="shrink-0 w-1.5 h-1.5 rounded-full mr-1" style={{ backgroundColor: color }} />
|
||||||
<span
|
{url ? (
|
||||||
className="font-medium truncate flex-grow min-w-0"
|
<a
|
||||||
style={{ color, marginRight: 12, maxWidth: '100%' }}
|
href={url}
|
||||||
title={svc.service_name}
|
target="_blank"
|
||||||
tabIndex={0}
|
rel="noopener noreferrer"
|
||||||
aria-label={svc.service_name}
|
className="font-medium truncate flex-grow min-w-0"
|
||||||
>
|
style={{ color, marginRight: 12, maxWidth: '100%' }}
|
||||||
{svc.service_name}
|
title={svc.service_name}
|
||||||
</span>
|
tabIndex={0}
|
||||||
|
aria-label={svc.service_name}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{svc.service_name}
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<span
|
||||||
|
className="font-medium truncate flex-grow min-w-0"
|
||||||
|
style={{ color, marginRight: 12, maxWidth: '100%' }}
|
||||||
|
title={svc.service_name}
|
||||||
|
tabIndex={0}
|
||||||
|
aria-label={svc.service_name}
|
||||||
|
>
|
||||||
|
{svc.service_name}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
<div className="flex items-center gap-1 shrink-0" style={{ maxWidth: 180, minWidth: 0 }}>
|
<div className="flex items-center gap-1 shrink-0" style={{ maxWidth: 180, minWidth: 0 }}>
|
||||||
{showPath && (
|
{showPath && (
|
||||||
<span
|
<span
|
||||||
className="truncate text-[#8b949e] text-right"
|
className="truncate text-[#8b949e] text-right"
|
||||||
style={{ minWidth: 0, maxWidth: pathMaxWidth, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'block' }}
|
style={{ minWidth: 0, maxWidth: pathMaxWidth, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'block' }}
|
||||||
title={pathLabel}
|
onMouseEnter={e => {
|
||||||
|
if (e.currentTarget.offsetWidth < e.currentTarget.scrollWidth) {
|
||||||
|
setTooltip({ visible: true, x: e.clientX, y: e.clientY, text: pathLabel });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onMouseMove={e => {
|
||||||
|
setTooltip(t => t.visible ? { ...t, x: e.clientX, y: e.clientY } : t);
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => setTooltip(t => ({ ...t, visible: false }))}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
aria-label={pathLabel}
|
aria-label={pathLabel}
|
||||||
>
|
>
|
||||||
@@ -701,9 +727,22 @@ function ServiceBadge({ svc, host, onEdit, onRemove }: { svc: ServiceInfo; host?
|
|||||||
{hasPort && (
|
{hasPort && (
|
||||||
<span className="font-mono text-[#8b949e]" style={{ whiteSpace: 'nowrap', flexShrink: 0 }}>{portLabel}/{svc.protocol}</span>
|
<span className="font-mono text-[#8b949e]" style={{ whiteSpace: 'nowrap', flexShrink: 0 }}>{portLabel}/{svc.protocol}</span>
|
||||||
)}
|
)}
|
||||||
<span className="inline-flex w-2.5 h-2.5 items-center justify-center shrink-0" aria-hidden="true">
|
{url ? (
|
||||||
{url ? <ExternalLink size={10} className="text-muted-foreground" /> : <span style={{ width: 10, display: 'inline-block' }} />}
|
<a
|
||||||
</span>
|
href={url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex w-2.5 h-2.5 items-center justify-center shrink-0"
|
||||||
|
tabIndex={0}
|
||||||
|
aria-label="Open service link"
|
||||||
|
style={{ color: 'inherit' }}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<ExternalLink size={10} className="text-muted-foreground" />
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<span style={{ width: 10, display: 'inline-block' }} />
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={(e) => { e.preventDefault(); e.stopPropagation(); onEdit(); }}
|
onClick={(e) => { e.preventDefault(); e.stopPropagation(); onEdit(); }}
|
||||||
className="opacity-100 transition-opacity text-[#8b949e] hover:text-[#00d4ff] ml-0.5"
|
className="opacity-100 transition-opacity text-[#8b949e] hover:text-[#00d4ff] ml-0.5"
|
||||||
@@ -719,24 +758,28 @@ function ServiceBadge({ svc, host, onEdit, onRemove }: { svc: ServiceInfo; host?
|
|||||||
<X size={10} />
|
<X size={10} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{url && (
|
|
||||||
<a
|
{tooltip.visible && (
|
||||||
href={url}
|
<div
|
||||||
target="_blank"
|
style={{
|
||||||
rel="noopener noreferrer"
|
position: 'fixed',
|
||||||
style={{
|
left: tooltip.x - 50,
|
||||||
position: 'absolute',
|
top: tooltip.y + 10,
|
||||||
left: 0,
|
background: '#222',
|
||||||
top: 0,
|
color: '#fff',
|
||||||
bottom: 0,
|
padding: '2px 8px',
|
||||||
right: 80,
|
borderRadius: 4,
|
||||||
zIndex: 1,
|
fontSize: 12,
|
||||||
opacity: 0,
|
zIndex: 9999,
|
||||||
}}
|
pointerEvents: 'none',
|
||||||
tabIndex={-1}
|
boxShadow: '0 2px 8px #0008',
|
||||||
aria-hidden="true"
|
whiteSpace: 'nowrap',
|
||||||
/>
|
overflow: 'visible'
|
||||||
)}
|
}}
|
||||||
|
>
|
||||||
|
{tooltip.text}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user