improvement(workflow): smooth the running hatch and sit it in the slot's own box - #6638
Conversation
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.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryLow Risk Overview The repeating gradient now uses 0.75px feathered stops (centre-to-centre period) instead of hard edges, so slanted stripes no longer look stepped when rasterized. The overlay uses Inline comments document the gradient math and taper geometry; no behavior or API changes. Reviewed by Cursor Bugbot for commit 8a96d50. Configure here. |
Greptile SummaryThis PR smooths the running-block hatch and expands it to match the action slots’ full height.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx | The revised gradient fully contains both edge ramps within its repeat interval, resolving the previously reported asymmetry without introducing another eligible failure. |
Reviews (2): Last reviewed commit: "fix(workflow): feather both hatch edges,..." | Re-trigger Greptile
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.
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.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 8a96d50. Configure here.
Summary
Two things about the running-block hatch, from the Slack thread.
Slanted edges read as stepped. 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 it, and on a mark this thin the staircase is the whole edge. Each edge now ramps over 0.75px — roughly a device pixel — which hands the rasterizer the intermediate values antialiasing would have produced.
The period runs centre-of-mark to centre-of-mark (11.59 → 36.7) rather than starting at an edge. A repeating gradient truncates at its own wrap, so anchoring at 0 left the ramp leaving the mark cut in half and pulled its 50%-coverage line 0.19px inward — one side of every stripe stayed sharper and the gap rendered 1.75px instead of 1.93px. Both ramps have to sit strictly inside the period. The list still tiles backwards from its first stop, so the marks land where anchoring at 0 put them: same 26px pitch, same phase against the squares, which matters because the marks are aligned to the slot rhythm.
The bar did not match the slots. The hatch was inset 4px into a 24px row, so it stood 16px tall inside a swell whose slots are 24px — a shorter bar floating in the row rather than the slots themselves filling — and its right end stopped short of where a hovered slot's fill ends. It now spans the row. 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 had to move with it. Its two numbers were read off the slot's diagonal at the old overlay's top and bottom (y=4, 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.
Type of Change
Testing
Reproduced the swell faithfully in headless Chromium — real container metrics (
h-[28px],py-0.5,px-[0.2rem]), the real capclip-pathvalues, the compositedwill-change: transformlayer — with a hovered slot rendered alongside as ground truth.Height and padding, sampling a column through the stop's hover fill and through the hatch:
Edge smoothness, tracking a single stripe and measuring its deviation from its own straight line:
0.28 device px is the signature of a fully quantized edge (uniform-over-one-pixel has σ≈0.289). Pixel magnification confirms it: before is binary black/white steps with no intermediate greys, after is a smooth ramp — now symmetric on both sides — with the mark's dark core intact.
Feather symmetry, 50%-coverage crossings across three periods (gap nominal 1.93px):
Feather width was chosen by sweeping 0.35/0.5/0.75/1.0px — wider keeps smoothing, but the gap is only 1.93px of stop so it comes straight out of the core.
Also verified: fading to
transparentproduces no dark fringe (premultiplied interpolation — measured 250→253→255 over white), and Tailwind emits every arbitrary value here intact rather than silently dropping it.Not yet seen on a running block in the app — verified against the isolated swell only.
Checklist