From 01bdea224e1198ac085cc2d685ce84ad18f5478d Mon Sep 17 00:00:00 2001 From: Naor Sabag <32329815+naorsabag@users.noreply.github.com> Date: Sun, 10 May 2026 06:52:45 +0000 Subject: [PATCH 1/2] fix(web): keep header/sidebar/inspector above mid-flight data pixels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DataPixel renders at zIndex 1000 inside the canvas wrapper, but the canvas pane has overflow: visible — so a carrot positioned near the pane's edge could paint over the chrome (top header, left FLOWS sidebar, right INSPECT panel, bookmark tabs). Pin all four to position: relative + zIndex: 1001 so they always sit above the pixels regardless of where the carrot is in mid-flight. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/web/src/App.tsx | 10 +++++++++- packages/web/src/AppFragment.tsx | 7 ++++++- packages/web/src/components/DataInspectionPanel.tsx | 10 +++++++++- packages/web/src/components/Sidebar.tsx | 8 +++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/web/src/App.tsx b/packages/web/src/App.tsx index f82c4a4..e81d324 100644 --- a/packages/web/src/App.tsx +++ b/packages/web/src/App.tsx @@ -357,7 +357,15 @@ function App() { {/* Header */}

diff --git a/packages/web/src/components/DataInspectionPanel.tsx b/packages/web/src/components/DataInspectionPanel.tsx index fc56235..ea45902 100644 --- a/packages/web/src/components/DataInspectionPanel.tsx +++ b/packages/web/src/components/DataInspectionPanel.tsx @@ -72,6 +72,11 @@ export function DataInspectionPanel({ width: side === 'right' ? size : '100%', height: side === 'bottom' ? size : '100%', flexShrink: 0, + // Sit above DataPixel (z=1000) so a carrot mid-flight can't paint + // over the inspector when the canvas pane lets it bleed past its + // bounds. + position: 'relative', + zIndex: 1001, } const handleStyle: React.CSSProperties = { @@ -409,7 +414,10 @@ export function BookmarkTab({ open, onToggle, edge, label, ariaLabel }: Bookmark top: '50%', transform: 'translateY(-50%)', [edge === 'right' ? 'right' : 'left']: 0, - zIndex: 20, + // Above DataPixel (z=1000) — same reason the header/sidebars + // sit above carrots: pixels in mid-flight can extend past the + // canvas pane bounds. + zIndex: 1001, width: 24, minWidth: 24, minHeight: 76, diff --git a/packages/web/src/components/Sidebar.tsx b/packages/web/src/components/Sidebar.tsx index bf16870..42136a3 100644 --- a/packages/web/src/components/Sidebar.tsx +++ b/packages/web/src/components/Sidebar.tsx @@ -479,7 +479,13 @@ export function Sidebar({ return (

@@ -803,11 +803,11 @@ function PlaybackButton({ border: '1px solid #1a4a22', color: disabled ? '#3a5a42' : '#7fffaa', cursor: disabled ? 'default' : 'pointer', - fontSize: 14, - fontFamily: 'monospace', - lineHeight: 1, padding: 0, borderRadius: 3, + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', }} > {children} @@ -815,6 +815,81 @@ function PlaybackButton({ ) } +// Inline SVG icons keep the playback chrome monochrome — emoji glyphs +// (⏮ ⏪ ▶ ⏸ ⏩) get rendered in the platform's color emoji font on most +// systems, ignoring the button's color and showing as Apple-blue or +// Win11-pink depending on the OS. SVG with currentColor + a sharp 16px +// viewBox keeps the buttons in the green accent the rest of the chrome +// uses. + +function ICON_FRAME(children: React.ReactNode) { + return ( + + ) +} + +function RestartIcon() { + // Counter-clockwise circular arrow with an arrowhead at the tail — + // unambiguous "start over" affordance instead of the skip-back glyph + // (⏮) the emoji set used. + return ( + + ) +} + +function PrevIcon() { + return ICON_FRAME( + <> + + + + ) +} + +function NextIcon() { + return ICON_FRAME( + <> + + + + ) +} + +function PlayIcon() { + return ICON_FRAME() +} + +function PauseIcon() { + return ICON_FRAME( + <> + + + + ) +} + export function FlowCanvas(props: FlowCanvasProps) { return (