Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/canvas-node-geometry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@workflowbuilder/ui': patch
---

Canvas nodes follow the Design System 2.0 geometry: the default shell width is the designed 241px (`--wb-public-node-width: 241px`, a canvas dimension that no longer scales with the root font size), and the shell padding and vertical gap bind to the node head roles `--wb-ds-canvas-node-head-h-pad` and `--wb-ds-canvas-node-head-gap` (8px each) instead of the generic spacing step. Overrides of the public node variables keep working unchanged.
5 changes: 5 additions & 0 deletions .changeset/connectable-item-width.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@workflowbuilder/sdk': patch
---

Decision branch rows and AI tool rows derive their width cap from the node shell and their container insets, so long labels keep the full available width after the node shell spacing change instead of truncating early.
2 changes: 2 additions & 0 deletions DECISION-LOGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@
- _15.05.2026_: [AuthPort seam for backend authn/authz](./apps/backend/auth-port.decision-log.md)
- _03.06.2026_: [TenantContextPort — multi-tenant identity seam for the reference backend](./apps/backend/tenant-context-port.decision-log.md)
- _07.08.2026_: [Keep the postcss box-sizing plugin over lint-based or selector-based alternatives](./packages/ui/postcss-box-sizing.decision-log.md)
- _24.08.2026_: [`incomplete` as a third terminal state, distinct from `failed` and from a stall](./packages/execution-core/terminal-states.decision-log.md)
- _31.08.2026_: [Ship common font faces inline and the rest as assets](./packages/ui/font-assets.decision-log.md)
- _07.09.2026_: [Derive the ConnectableItem width from the real container insets](./packages/sdk/src/features/diagram/nodes/components/connectable-item/connectable-item-width.decision-log.md)
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.container {
--wb-sdk-connectable-item-inset: calc(0.625rem + 1px);

display: flex;
flex-direction: column;
gap: 0.75rem;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
### Title: Derive the ConnectableItem width from the real container insets

### Proposed by: Jan Librowski

### Date: 07.09.2026

## Context

`ConnectableItem` (a node body row that carries its own port: Decision branches, AI tools) caps its
width with an absolute `max-width` computed from the public node width. The cap is needed because the
Decision template sets `min-width: max-content` on its body, so a long branch label would otherwise
widen the whole node instead of truncating.

The previous rule was:

```css
max-width: calc(
var(--wb-public-node-width) - (6 * var(--wb-public-node-padding)) + 2 *
var(--wb-sdk-connectable-item-horizontal-padding) + 2 * var(--wb-sdk-connectable-item-border-width)
);
```

Two problems surfaced while moving the node shell to the DS 2.0 geometry (width 241px):

- The `6 *` factor is not documented anywhere. It only approximates the real horizontal insets
between the node edge and the item: shell padding plus border on both sides (2 x 9px) and the
section padding plus border on both sides (2 x 11px), 40px in total against the 48px it subtracts.
- The `+ 2 * padding + 2 * border` terms assume content-box sizing. The SDK applies a global
`box-sizing: border-box` reset (`packages/sdk/src/index.css`), so `max-width` already refers to
the border box and the terms inflate the cap: at 241px the old rule allows 219px while only 201px
are available inside a section, so a long label could overflow its section by 18px.

The design system does not specify a width for these items (register: node geometry gaps). Any cap
is therefore a provisional implementation decision, to be revisited when the design provides one.

## Decision

The cap is derived from named insets between the node's outer edge and the item:

```css
max-width: calc(
var(--wb-public-node-width) - 2 * (var(--wb-public-node-padding) + var(--wb-public-node-border-size)) - 2 *
var(--wb-sdk-connectable-item-inset)
);
```

`--wb-sdk-connectable-item-inset` is the horizontal inset (one side) added by the container that
wraps the items. It defaults to `0rem` and each wrapping container declares its own value:

- `NodeSection` sets it to its padding plus border width, so Decision branches inside a section get
`241 - 2 x (8 + 1) - 2 x (10 + 1) = 201px` (with the previous 258px shell: 218px).
- The AI template wraps its tool rows in `NodeInfoWrapper` (padding 0.625rem plus a 1px border
per side), which therefore declares the same inset, so tool rows get
`241 - 2 x (8 + 1) - 2 x (10 + 1) = 201px` as well. The default `0rem` applies only to a
container that adds no horizontal padding.

The variable is not cumulative: a wrapper declares the inset it adds itself, and a container that
adds horizontal padding without declaring it lets its rows exceed the visible width by that padding.

## Consequences

- Item width follows the shell geometry exactly and can no longer exceed the space its container
actually offers.
- The variable makes the nesting explicit and reviewable per container instead of encoding it in a
single global multiplier.
- Provisional until the design specifies the item width; recorded as a decision made without a
design in the DS 2.0 divergence register. The design's node body matrix (row padding 8px,
radius 4px) is a separate follow-up and does not change this derivation.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
--wb-sdk-connectable-item-border-width: 0.0625rem;
--wb-sdk-connectable-item-border-color: var(--wb-ds-components-text-field-stroke-default);
--wb-sdk-connectable-item-border-radius: 0.375rem;
--wb-sdk-connectable-item-inset: 0rem;
}

.connectable-item {
Expand All @@ -13,8 +14,8 @@
position: relative;
display: flex;
max-width: calc(
var(--wb-public-node-width) - (6 * var(--wb-public-node-padding)) + 2 *
var(--wb-sdk-connectable-item-horizontal-padding) + 2 * var(--wb-sdk-connectable-item-border-width)
var(--wb-public-node-width) - 2 * (var(--wb-public-node-padding) + var(--wb-public-node-border-size)) - 2 *
var(--wb-sdk-connectable-item-inset)
);
padding: var(--wb-sdk-connectable-item-vertical-padding) var(--wb-sdk-connectable-item-horizontal-padding);
background-color: var(--wb-sdk-connectable-item-background);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
}

.container {
--wb-sdk-connectable-item-inset: calc(var(--wb-sdk-node-section-padding) + var(--wb-sdk-node-section-border-width));

display: flex;
flex-direction: column;
gap: var(--wb-sdk-node-section-gap);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
:root {
--wb-public-node-width: 16.125rem;
--wb-public-node-width: 241px;
--wb-public-node-height: 100%;
--wb-public-node-border-size: 0.0625rem;

--wb-public-node-padding: var(--wb-ds-space-100);
--wb-public-node-gap: var(--wb-ds-space-100);
--wb-public-node-padding: var(--wb-ds-canvas-node-head-h-pad);
--wb-public-node-gap: var(--wb-ds-canvas-node-head-gap);
--wb-public-node-border-radius: var(--wb-ds-canvas-node-head-radius);

--wb-public-node-border-color: var(--wb-ds-canvas-node-stroke-default);
Expand Down
Loading