From a5ad4f4e584e55532de719d87846e3702a8b1077 Mon Sep 17 00:00:00 2001 From: Chris Feijoo Date: Wed, 26 Aug 2026 22:53:50 +0200 Subject: [PATCH 1/2] Place arc weight labels on the Adaptive Bezier curve The Adaptive Bezier renderer put weight labels at the straight-line midpoint between the arc's endpoints, despite a comment claiming the bezier midpoint. Long arcs sweep far from that line, leaving the label floating in empty space. The label now uses the cubic bezier point at t = 0.5: (P0 + 3*CP1 + 3*CP2 + P3) / 8. --- .changeset/adaptive-bezier-label-midpoint.md | 5 +++++ .../petrinaut/src/ui/views/SDCPN/components/arc.tsx | 7 +++---- 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 .changeset/adaptive-bezier-label-midpoint.md diff --git a/.changeset/adaptive-bezier-label-midpoint.md b/.changeset/adaptive-bezier-label-midpoint.md new file mode 100644 index 00000000000..75477c2b7c9 --- /dev/null +++ b/.changeset/adaptive-bezier-label-midpoint.md @@ -0,0 +1,5 @@ +--- +"@hashintel/petrinaut": patch +--- + +Arc weight labels sit on the Adaptive Bezier curve instead of floating at the straight-line midpoint between the arc's endpoints. diff --git a/libs/@hashintel/petrinaut/src/ui/views/SDCPN/components/arc.tsx b/libs/@hashintel/petrinaut/src/ui/views/SDCPN/components/arc.tsx index 23304b0e88b..87e3d15c049 100644 --- a/libs/@hashintel/petrinaut/src/ui/views/SDCPN/components/arc.tsx +++ b/libs/@hashintel/petrinaut/src/ui/views/SDCPN/components/arc.tsx @@ -248,7 +248,6 @@ function getCustomArcPath({ targetPosition: Position; }): [path: string, labelX: number, labelY: number] { const dx = targetX - sourceX; - const dy = targetY - sourceY; // Control point offset scales with horizontal distance, with a minimum const offset = Math.max(Math.abs(dx) * 0.7, 80); @@ -260,9 +259,9 @@ function getCustomArcPath({ const path = `M ${sourceX},${sourceY} C ${cp1x},${cp1y} ${cp2x},${cp2y} ${targetX},${targetY}`; - // Label at the midpoint of the cubic bezier (t=0.5) - const labelX = sourceX + dx / 2; - const labelY = sourceY + dy / 2; + // Label at the midpoint of the cubic bezier: B(0.5) = (P0 + 3·CP1 + 3·CP2 + P3) / 8 + const labelX = (sourceX + 3 * cp1x + 3 * cp2x + targetX) / 8; + const labelY = (sourceY + 3 * cp1y + 3 * cp2y + targetY) / 8; return [path, labelX, labelY]; } From 3f1e2fcbe097be80e514c1fcb51b27b877ff9cd4 Mon Sep 17 00:00:00 2001 From: Chris Feijoo Date: Thu, 27 Aug 2026 03:44:16 +0200 Subject: [PATCH 2/2] Give sidebar list labels the full row width until the row menu shows Rows revealed their action button by animating opacity, so the hidden button always reserved its layout space: lists with row menus wrapped labels earlier than lists without, and the space was wasted until hover. The button is now hidden with display, so labels take the full row width and only shrink while the row is hovered or its menu is open. Item content rendered as nested lines (a name with a subtitle) escaped the row's ellipsis and clipped hard; nested lines now truncate the same way plain-text items do. --- .changeset/sidebar-row-label-width.md | 5 ++++ .../subviews/filterable-list-sub-view.tsx | 25 ++++++++++--------- 2 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 .changeset/sidebar-row-label-width.md diff --git a/.changeset/sidebar-row-label-width.md b/.changeset/sidebar-row-label-width.md new file mode 100644 index 00000000000..ca6b3badd13 --- /dev/null +++ b/.changeset/sidebar-row-label-width.md @@ -0,0 +1,5 @@ +--- +"@hashintel/petrinaut": patch +--- + +Sidebar list labels use the full row width and truncate with an ellipsis consistently; the row menu button only takes space while hovering the row or while its menu is open. diff --git a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/subviews/filterable-list-sub-view.tsx b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/subviews/filterable-list-sub-view.tsx index 73ed26bcdd4..6fd2c2b3274 100644 --- a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/subviews/filterable-list-sub-view.tsx +++ b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/subviews/filterable-list-sub-view.tsx @@ -52,22 +52,15 @@ const listItemRowStyle = cva({ true: { cursor: "pointer", - /* Reveal the action button on hover or when its menu is open */ + /* Reveal the action button on hover or when its menu is open. Hidden + with `display` rather than `opacity` so it takes no space and the + label keeps the full row width until the button is shown. */ "& [data-row-action]": { - opacity: "[0]", - transition: "[opacity 150ms ease-out]", - }, - "& [data-row-action] svg": { - transform: "[translateX(2px)]", - transition: "[transform 150ms ease-out]", + display: "none", }, "&:hover [data-row-action], & [data-row-action][data-state=open]": { - opacity: "[1]", + display: "flex", }, - "&:hover [data-row-action] svg, & [data-row-action][data-state=open] svg": - { - transform: "none", - }, }, }, isSelected: { @@ -118,6 +111,7 @@ const listItemContentStyle = css({ const listItemNameStyle = css({ flex: "[1]", + minWidth: "[0]", fontSize: "sm", fontWeight: "medium", lineHeight: "snug", @@ -125,6 +119,13 @@ const listItemNameStyle = css({ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", + /* renderItem may nest its own lines (e.g. a name with a subtitle); each + line truncates the same way plain-text items do. */ + "& *": { + overflow: "hidden", + textOverflow: "ellipsis", + whiteSpace: "nowrap", + }, }); const LIST_ITEM_ICON_SIZE = 12;