A select trigger's value ends in an ellipsis instead of being clipped, and with centred ranks an edge's value chip is cut to the 60px the layout made room for, so a long JSON value no longer overlaps its neighbour

This commit is contained in:
2026-11-10 22:09:47 +01:00
parent 4586f3688d
commit 53d7545c11
3 changed files with 10 additions and 2 deletions
@@ -288,6 +288,8 @@ function LiveEdgeComponent({
<div
style={{
transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
// Only where the chip sits in the room the layout made for it.
maxWidth: square ? route?.chipWidth : undefined,
}}
className="pointer-events-none absolute max-w-[140px] truncate rounded-full border border-border bg-card px-2 py-0.5 font-mono text-xs text-foreground"
>
+7 -1
View File
@@ -132,7 +132,8 @@ const TOO_WIDE = (ABREAST + 1) * (NODE_W + NODE_GAP)
*
* Centring packs a rank's chips together where the edges meet in the middle,
* so with no width at all they piled onto each other. This is a number's
* worth: a longer value overlaps its neighbour rather than widening the graph.
* worth: a longer value is cut to fit (see `Route.chipWidth`) rather than
* widening the graph, and the edge's inspector shows it whole.
*/
const CENTRED_LABEL_W = 60
@@ -168,6 +169,8 @@ export type Route = {
points: Point[]
/** Where the room reserved for the edge's value chip is centred. */
label: Point
/** How wide the chip may be, where that room is narrower than the chip. */
chipWidth?: number
from: Point
to: Point
}
@@ -453,6 +456,7 @@ export async function layoutGraph(
}
let { placed, laid } = await place([])
let centred = false
// Running downwards, a rank wider than the screen is the one thing the
// layout can still do something about. Wrapping one rank pushes whatever was
@@ -469,6 +473,7 @@ export async function layoutGraph(
}
const [left, right] = extentOf(placed, shapes, direction)
if (wrap.length && right - left > TOO_WIDE) {
centred = true
;({ placed, laid } = await place(wrap, true))
}
}
@@ -506,6 +511,7 @@ export async function layoutGraph(
direction === "TB" && (room.x < left || room.x > right)
? (longestRun(points) ?? room)
: room,
chipWidth: centred ? CENTRED_LABEL_W : undefined,
from: positions.get(source) ?? { x: 0, y: 0 },
to: positions.get(target) ?? { x: 0, y: 0 },
})
+1 -1
View File
@@ -35,7 +35,7 @@ function SelectTrigger({
data-slot="select-trigger"
data-size={size}
className={cn(
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-full border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-none transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-full border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-none transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:truncate [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}