Skip to content

Commit 9aa16e3

Browse files
authored
improvement(workflow): smooth the running hatch and sit it in the slot's own box (#6638)
* improvement(workflow): smooth the running hatch's slanted edges The marks read as stepped rather than slanted. A repeating gradient is sampled once per pixel with no coverage term, so a hard colour stop on an edge 15° off vertical can only land wholly on one side or the other — there is no partial value to soften the transition, and the staircase is the whole edge on a mark this thin. Ramp each edge over 0.75px, roughly a device pixel, instead of switching colour at a single offset. That hands the rasterizer the intermediate values antialiasing would have produced: measured deviation of the edge from its own straight line falls from 0.28 device px — pure quantization — to 0.05. The ramps are centred on the offsets the hard stops used, so the 50%-coverage line does not move: same 75° lean, same 24/2 rhythm, same 26px scroll period. * improvement(workflow): sit the running hatch in the slot's own box The hatch was inset 4px into a 24px row, so it stood 16px tall inside a swell whose slots are 24px — it read as a shorter bar floating inside the row rather than as the slots themselves filling, and its right end stopped short of where a hovered slot's fill ends. Span the row instead. The row already sits inside the container's 2px/3.2px inset, so occupying it outright puts the hatch in exactly the box a slot's hover fill occupies: same height, same padding in from the swell on every side. The end taper has to move with it, since its two numbers were read off the slot's diagonal at the old overlay's top and bottom (y=4 and y=20). Continuing that same edge — slope 20/24 — across the full row gives 20px in at the top and flush at the bottom, so the hatch still ends on the slot's own diagonal. * fix(workflow): feather both hatch edges, not just one The trailing ramp straddled the period boundary. Anchored at 0, the mark's leaving edge ramped 24.735 → 25.485, but a repeating gradient truncates at its own wrap, so it was cut at 25.11: half the feather, and its 50%-coverage line pulled 0.19px inward. That edge stayed sharper than the other and the gap rendered 1.75px instead of 1.93px. Run the period centre-of-mark to centre-of-mark instead, so both ramps sit strictly inside it. The stop list still tiles backwards from its first stop, so the marks land where anchoring at 0 put them — measured pitch is unchanged at 26px and both edges now carry the full 0.75px.
1 parent 1b63541 commit 9aa16e3

1 file changed

Lines changed: 33 additions & 7 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,30 @@ const ACTION_BUTTON_STYLES = [
6666
* 25.11px of period. Writing 24/26 directly would render ~3.5% wide and drift
6767
* out of the squares' rhythm across the row.
6868
*
69+
* Each edge ramps over 0.75px rather than switching colour at a single offset,
70+
* which is why the stops come in pairs 0.375px either side of the mark's two
71+
* edges. A gradient is sampled once per pixel with no coverage term, so a hard
72+
* stop on a 15°-off-vertical edge can only ever land wholly on one side or the
73+
* other — the marks came out visibly stepped, which is the one thing a shape
74+
* this thin cannot hide. Ramping across roughly a device pixel gives the
75+
* rasterizer the intermediate values antialiasing would have produced, and
76+
* measured edge deviation drops from 0.28 device px (pure quantization) to 0.05.
77+
*
78+
* The period runs centre-of-mark to centre-of-mark (11.59 → 36.7) rather than
79+
* starting at an edge, because a repeating gradient truncates at its own wrap:
80+
* anchored at 0, the ramp leaving the mark would have run 24.735 → 25.485 and
81+
* been cut at 25.11, so that edge got half the feather and the gap came out
82+
* 1.93 → 1.75px. Both ramps have to sit strictly inside the period. The list
83+
* still tiles backwards from its first stop, so the marks land exactly where
84+
* anchoring at 0 put them — same 26px pitch, same phase against the squares.
85+
*
86+
* Widening the feather further would keep smoothing, but the gap is only 1.93px
87+
* of stop, so it comes straight out of the mark's dark core.
88+
*
6989
* `--surface-2` is the same fill the slots used; only where it is painted moved.
7090
*/
7191
const RUNNING_FILL =
72-
'bg-[repeating-linear-gradient(75deg,var(--surface-2)_0_23.18px,transparent_23.18px_25.11px)]'
92+
'bg-[repeating-linear-gradient(75deg,var(--surface-2)_11.59px_22.805px,transparent_23.555px_24.735px,var(--surface-2)_25.485px_36.7px)]'
7393

7494
/** Left edge of the fill: clears the run/stop button, which stays live mid-run. */
7595
const RUNNING_FILL_INSET_SWELL = 'left-[42px]'
@@ -84,12 +104,14 @@ const RUNNING_FILL_INSET_PLAIN = 'left-[26px]'
84104
* inside it at the bottom — the fill visibly ran off the block. The per-slot
85105
* version never did, because each button's own clip contained it.
86106
*
87-
* Same taper, read off that path: the edge sits 16.67px in from the row's right
88-
* at the overlay's top (y=4) and 3.33px at its bottom (y=20), a slope of 20/24.
89-
* Changing the end silhouette means changing these two numbers with it.
107+
* Same taper, read off that path. Its straight run — (22.4, 2.88) to
108+
* (36.59, 19.9) in the slot's own 40×24 box — has a slope of 20/24, so across
109+
* the full row it moves from 20px in at the top to flush at the bottom. The
110+
* overlay spans the row, so those are its two numbers; they are the slot's own
111+
* edge continued, which is what puts the hatch's end exactly where a hovered
112+
* slot's fill ends. Changing the end silhouette means changing them with it.
90113
*/
91-
const RUNNING_FILL_END_TAPER =
92-
'[clip-path:polygon(0_0,calc(100%_-_16.67px)_0,calc(100%_-_3.33px)_100%,0_100%)]'
114+
const RUNNING_FILL_END_TAPER = '[clip-path:polygon(0_0,calc(100%_-_20px)_0,100%_100%,0_100%)]'
93115

94116
const ICON_SIZE = 'size-[14px]'
95117

@@ -415,7 +437,11 @@ export const ActionBar = memo(
415437
<span
416438
aria-hidden='true'
417439
className={cn(
418-
'pointer-events-none absolute inset-y-[4px] right-0 overflow-hidden',
440+
/* Spans the row, so the hatch occupies exactly the box a slot's
441+
hover fill does — same height, and the same padding in from
442+
the swell on every side, since the row already sits inside
443+
the container's own inset. */
444+
'pointer-events-none absolute inset-y-0 right-0 overflow-hidden',
419445
isSwell ? RUNNING_FILL_INSET_SWELL : RUNNING_FILL_INSET_PLAIN,
420446
isSwell && RUNNING_FILL_END_TAPER
421447
)}

0 commit comments

Comments
 (0)