feat: per-link path style toggle (bezier / smooth step)

This commit is contained in:
Pouzor
2026-03-07 14:46:55 +01:00
parent 8437f5ef49
commit 07d8c4e58b
8 changed files with 39 additions and 2 deletions
+1
View File
@@ -65,6 +65,7 @@ export default function App() {
vlan_id: e.data?.vlan_id ?? null,
speed: e.data?.speed ?? null,
custom_color: e.data?.custom_color ?? null,
path_style: e.data?.path_style ?? null,
}))
await canvasApi.save({ nodes: nodesToSave, edges: edgesToSave, viewport: {} })
markSaved()
@@ -2,6 +2,7 @@ import {
BaseEdge,
EdgeLabelRenderer,
getBezierPath,
getSmoothStepPath,
type EdgeProps,
type Edge,
} from '@xyflow/react'
@@ -23,7 +24,10 @@ const EDGE_STYLES: Record<EdgeType, React.CSSProperties> = {
}
export function HomelableEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data, selected }: EdgeProps<Edge<EdgeData>>) {
const [edgePath, labelX, labelY] = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition })
const pathArgs = { sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition }
const [edgePath, labelX, labelY] = data?.path_style === 'smooth'
? getSmoothStepPath({ ...pathArgs, borderRadius: 8 })
: getBezierPath(pathArgs)
const edgeType: EdgeType = data?.type ?? 'ethernet'
const customColor = data?.custom_color as string | undefined
+24 -1
View File
@@ -5,7 +5,7 @@ import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { EDGE_TYPE_LABELS, type EdgeData, type EdgeType } from '@/types'
import { EDGE_TYPE_LABELS, type EdgeData, type EdgePathStyle, type EdgeType } from '@/types'
import { EDGE_DEFAULT_COLORS } from '@/utils/edgeColors'
const EDGE_TYPES = Object.entries(EDGE_TYPE_LABELS) as [EdgeType, string][]
@@ -24,6 +24,7 @@ export function EdgeModal({ open, onClose, onSubmit, onDelete, initial, title =
const [label, setLabel] = useState(initial?.label ?? '')
const [vlanId, setVlanId] = useState(initial?.vlan_id?.toString() ?? '')
const [customColor, setCustomColor] = useState<string | undefined>(initial?.custom_color)
const [pathStyle, setPathStyle] = useState<EdgePathStyle>(initial?.path_style ?? 'bezier')
const effectiveColor = customColor ?? EDGE_DEFAULT_COLORS[type]
@@ -34,6 +35,7 @@ export function EdgeModal({ open, onClose, onSubmit, onDelete, initial, title =
label: label || undefined,
vlan_id: type === 'vlan' && vlanId ? parseInt(vlanId) : undefined,
custom_color: customColor,
path_style: pathStyle,
})
onClose()
}
@@ -90,6 +92,27 @@ export function EdgeModal({ open, onClose, onSubmit, onDelete, initial, title =
/>
</div>
<div className="flex flex-col gap-1.5">
<Label className="text-xs text-muted-foreground">Path Style</Label>
<div className="flex rounded-md overflow-hidden border border-[#30363d]">
{(['bezier', 'smooth'] as EdgePathStyle[]).map((style) => (
<button
key={style}
type="button"
onClick={() => setPathStyle(style)}
className="flex-1 py-1 text-xs capitalize transition-colors"
style={{
background: pathStyle === style ? '#00d4ff22' : '#21262d',
color: pathStyle === style ? '#00d4ff' : '#8b949e',
borderRight: style === 'bezier' ? '1px solid #30363d' : undefined,
}}
>
{style === 'bezier' ? 'Bezier' : 'Smooth step'}
</button>
))}
</div>
</div>
<div className="flex flex-col gap-1.5">
<div className="flex items-center justify-between">
<Label className="text-xs text-muted-foreground">Color</Label>
+3
View File
@@ -44,12 +44,15 @@ export interface NodeData extends Record<string, unknown> {
custom_colors?: { border?: string; background?: string; icon?: string }
}
export type EdgePathStyle = 'bezier' | 'smooth'
export interface EdgeData extends Record<string, unknown> {
type: EdgeType
label?: string
vlan_id?: number
speed?: string
custom_color?: string
path_style?: EdgePathStyle
}
export const NODE_TYPE_LABELS: Record<NodeType, string> = {