Skip to content
Merged
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
10 changes: 9 additions & 1 deletion packages/web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,15 @@ function App() {
{/* Header */}
<header
className="flex items-center justify-between px-4 py-2 shrink-0"
style={{ background: '#0d2612', borderBottom: '2px solid #1a4a22' }}
style={{
background: '#0d2612',
borderBottom: '2px solid #1a4a22',
// Sit above the data pixels (z=1000) so a carrot mid-flight
// doesn't paint over the chrome when the canvas pane lets it
// bleed beyond its bounds.
position: 'relative',
zIndex: 1001,
}}
>
<div className="flex items-center gap-4">
<h1
Expand Down
7 changes: 6 additions & 1 deletion packages/web/src/AppFragment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,12 @@ export default function AppFragment() {
>
<header
className="flex items-center justify-between px-4 py-2 shrink-0"
style={{ background: '#0d2612', borderBottom: '2px solid #1a4a22' }}
style={{
background: '#0d2612',
borderBottom: '2px solid #1a4a22',
position: 'relative',
zIndex: 1001,
}}
>
<div className="flex items-center gap-4">
<h1 className="font-pixel text-accent" style={{ fontSize: 14 }}>
Expand Down
10 changes: 9 additions & 1 deletion packages/web/src/components/DataInspectionPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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,
Expand Down
89 changes: 82 additions & 7 deletions packages/web/src/components/FlowCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@
},
}
})
}, [

Check warning on line 551 in packages/web/src/components/FlowCanvas.tsx

View workflow job for this annotation

GitHub Actions / build & test (node 20)

React Hook useMemo has a missing dependency: 'nodeOutgoingSteps'. Either include it or remove the dependency array

Check warning on line 551 in packages/web/src/components/FlowCanvas.tsx

View workflow job for this annotation

GitHub Actions / build & test (node 22)

React Hook useMemo has a missing dependency: 'nodeOutgoingSteps'. Either include it or remove the dependency array
baseNodes,
animState.activeFromIds,
animState.activeToIds,
Expand Down Expand Up @@ -678,7 +678,7 @@
restart()
}}
>
{'⏮'}
<RestartIcon />
</PlaybackButton>
<PlaybackButton
ariaLabel="Previous step"
Expand All @@ -689,10 +689,10 @@
}}
disabled={(animState.currentStepIndex ?? -1) <= 0}
>
{'⏪'}
<PrevIcon />
</PlaybackButton>
<PlaybackButton ariaLabel={playing ? 'Pause flow' : 'Play flow'} onClick={onTogglePlay}>
{playing ? '⏸' : '▶'}
{playing ? <PauseIcon /> : <PlayIcon />}
</PlaybackButton>
<PlaybackButton
ariaLabel="Next step"
Expand All @@ -706,7 +706,7 @@
animState.currentStepIndex >= flowSteps.length - 1
}
>
{'⏩'}
<NextIcon />
</PlaybackButton>
</div>
</Panel>
Expand Down Expand Up @@ -803,18 +803,93 @@
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}
</button>
)
}

// 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 (
<svg
viewBox="0 0 16 16"
width={14}
height={14}
fill="currentColor"
stroke="currentColor"
aria-hidden="true"
>
{children}
</svg>
)
}

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 (
<svg
viewBox="0 0 16 16"
width={14}
height={14}
fill="none"
stroke="currentColor"
strokeWidth={1.5}
strokeLinecap="square"
strokeLinejoin="miter"
aria-hidden="true"
>
<path d="M3 8 A5 5 0 1 0 5 4" />
<path d="M5 1.5 L5 4 L7.5 4" fill="currentColor" />
</svg>
)
}

function PrevIcon() {
return ICON_FRAME(
<>
<path d="M7 3 L3 8 L7 13 Z" />
<path d="M13 3 L9 8 L13 13 Z" />
</>
)
}

function NextIcon() {
return ICON_FRAME(
<>
<path d="M3 3 L7 8 L3 13 Z" />
<path d="M9 3 L13 8 L9 13 Z" />
</>
)
}

function PlayIcon() {
return ICON_FRAME(<path d="M4 3 L13 8 L4 13 Z" />)
}

function PauseIcon() {
return ICON_FRAME(
<>
<rect x={4} y={3} width={3} height={10} />
<rect x={9} y={3} width={3} height={10} />
</>
)
}

export function FlowCanvas(props: FlowCanvasProps) {
return (
<ReactFlowProvider>
Expand Down
8 changes: 7 additions & 1 deletion packages/web/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,13 @@ export function Sidebar({
return (
<aside
className="shrink-0 flex flex-col overflow-hidden"
style={{ width: 260, background: '#141428', borderRight: '2px solid #2a2a4a' }}
style={{
width: 260,
background: '#141428',
borderRight: '2px solid #2a2a4a',
position: 'relative',
zIndex: 1001,
}}
aria-label="File explorer"
>
{/* Search */}
Expand Down
Loading