Fix duplicate label selection and add label wrapping

Label selection fix:
- Prevent duplicate labels when creating a label that already exists
- Check if label is already selected before adding to selection

Label wrapping improvements:
- Labels now wrap within a 200px container to prevent nodes growing too large
- LabelBadge updated to only truncate when maxWidth is explicitly provided
- Labels display full text without individual truncation
- Applies to both CustomNode and CustomEdge components

Note: Some overlap may occur with circular shapes - accepted for now.
This commit is contained in:
Jan-Henrik Bruhn 2026-01-24 16:50:22 +01:00
parent d17702452d
commit 66d47fb022
3 changed files with 6 additions and 8 deletions

View file

@ -6,7 +6,7 @@ import { getContrastColor } from '../../utils/colorUtils';
* Features:
* - Pill-shaped design
* - Auto-contrast text color
* - Truncation with ellipsis
* - Optional truncation with ellipsis (if maxWidth is provided)
* - Tooltip on hover (via title attribute)
*/
@ -17,7 +17,7 @@ interface Props {
size?: 'sm' | 'md';
}
const LabelBadge = ({ name, color, maxWidth = '120px', size = 'sm' }: Props) => {
const LabelBadge = ({ name, color, maxWidth, size = 'sm' }: Props) => {
const textColor = getContrastColor(color);
const sizeClasses = size === 'sm'
@ -26,11 +26,11 @@ const LabelBadge = ({ name, color, maxWidth = '120px', size = 'sm' }: Props) =>
return (
<span
className={`inline-block rounded-full font-medium whitespace-nowrap overflow-hidden text-ellipsis ${sizeClasses}`}
className={`inline-block rounded-full font-medium whitespace-nowrap ${maxWidth ? 'overflow-hidden text-ellipsis' : ''} ${sizeClasses}`}
style={{
backgroundColor: color,
color: textColor,
maxWidth,
...(maxWidth && { maxWidth }),
}}
title={name}
>

View file

@ -226,7 +226,7 @@ const CustomEdge = ({
</div>
)}
{data?.labels && data.labels.length > 0 && (
<div className="flex flex-wrap gap-1 justify-center">
<div className="flex flex-wrap gap-1 justify-center" style={{ maxWidth: '200px' }}>
{data.labels.map((labelId) => {
const labelConfig = labels.find((l) => l.id === labelId);
if (!labelConfig) return null;
@ -235,7 +235,6 @@ const CustomEdge = ({
key={labelId}
name={labelConfig.name}
color={labelConfig.color}
maxWidth="80px"
size="sm"
/>
);

View file

@ -266,7 +266,7 @@ const CustomNode = ({ data, selected }: NodeProps<Actor>) => {
{/* Labels */}
{data.labels && data.labels.length > 0 && (
<div className="flex flex-wrap gap-1 justify-center mt-2">
<div className="flex flex-wrap gap-1 justify-center mt-2" style={{ maxWidth: '200px' }}>
{data.labels.map((labelId) => {
const labelConfig = labels.find((l) => l.id === labelId);
if (!labelConfig) return null;
@ -275,7 +275,6 @@ const CustomNode = ({ data, selected }: NodeProps<Actor>) => {
key={labelId}
name={labelConfig.name}
color={labelConfig.color}
maxWidth="80px"
size="sm"
/>
);