-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Status Quo
When a user navigates to a different terminal in grid view, the newly focused terminal's blue border appears immediately with no transition. The wave animation (horizontal-squish strip effect in renderWaveStrips(), renderer.zig:829–886) fires only when agent status notifications arrive, triggered via SessionInteractionComponent.setAttention().
The terminal border (focused, unfocused, and attention states) is drawn by drawThickBorder() in gfx/primitives.zig:47–61, which calls the 1px-wide drawRoundedBorder() outline thickness times with each call inset by 1px but using the same corner radius (hardcoded 12). Because the arc radius doesn't shrink as the rect shrinks, the nested corner arcs aren't concentric — they diverge at the corners, producing jagged/uneven edges. The radius is also not DPI-scaled.
Objectives
When a developer moves focus between terminals in grid view, a brief wave animation acknowledges the navigation. The terminal border (selected and unselected) should have smooth, properly filled corners at all DPI settings.
User Flow
Trigger: User presses Cmd+Arrow or Cmd+1–9 to move focus to a different terminal in grid view.
- Focus moves to the new terminal; its smooth blue border appears.
- A brief wave animation (~400 ms, smaller amplitude than the agent notification wave) plays on the newly focused terminal.
- Animation completes; terminal displays normally with the clean border.
Result: Navigation feels responsive and polished; all terminal borders have smooth, filled corners.
Scope
In scope:
- Wave animation (strip squish, same timing as the attention animation) triggered on focus change in grid view, with a smaller amplitude
- Fix
drawThickBorderto render a properly filled donut between outer and inner rounded rects (scanline approach), with radius as a parameter and DPI scaling at call sites - All three terminal border call sites in
renderer.zig(focused, unfocused, attention) benefit from the fix
Out of scope:
- Changing the existing attention animation (amplitude, timing, color)
- Wave animation on focus change in full-screen mode
- Changing any other
drawRoundedBorder/fillRoundedRectcall sites (buttons, modals, scrollbars — all use thin 1px borders or fills that are already correct) - Configurable border radii or animation durations
Implementation Plan
Affected Modules
src/gfx/primitives.zig: rewritedrawThickBorderto use scanline-fill donut approach; addradiusparametersrc/render/renderer.zig: updatedrawThickBordercall sites to pass explicit radius (DPI-scaled); handlenav_wave_start_timealongsidewave_start_timewith separate amplitudesrc/ui/session_view_state.zig: addnav_wave_start_time: i64 = 0fieldsrc/ui/components/session_interaction.zig: addnav_wave_amplitudeconstant andtriggerNavWave()methodsrc/app/runtime.zig: calltriggerNavWave()whenfocused_sessionchanges in grid view
Tasks
- Rewrite
drawThickBorderingfx/primitives.zigto use a scanline-fill approach: for each scanline compute the span inside the outer rounded rect and outside the inner rounded rect (inset bythickness), fill only those two side-spans and the corner regions — addradius: c_intas a parameter instead of hardcoding 12 —src/gfx/primitives.zig - Update the 3
drawThickBordercall sites inrenderer.zigto pass an explicit DPI-scaled radius (e.g.dpi.scale(6, ui_scale)) —src/render/renderer.zig - Add
nav_wave_start_time: i64 = 0toSessionViewState—src/ui/session_view_state.zig - Add
pub const nav_wave_amplitude: f32 = 0.04constant andtriggerNavWave(idx, now_ms)method (mirrorssetAttentionbut only setsnav_wave_start_time, no border color change) —src/ui/components/session_interaction.zig - Detect focus change in grid view in the frame loop and call
triggerNavWave()on the newly focused session —src/app/runtime.zig - In
renderWaveStrips(), accept anamplitude: f32parameter; in the per-session render path handlenav_wave_start_timealongsidewave_start_time, passingnav_wave_amplitude—src/render/renderer.zig - Write tests:
triggerNavWave()setsnav_wave_start_time, does not setattentionor changestatus;setAttention()does not interfere withnav_wave_start_time—src/ui/components/session_interaction.zig
Acceptance Criteria
- All tasks completed
- Navigating between terminals in grid view triggers a brief wave animation with visibly smaller amplitude than the agent-notification wave
- Wave does not trigger when switching to/from full-screen mode
- All three terminal border states (focused, unfocused, attention) have smooth, filled corners with no jagged artifacts
- Border rendering is visually correct on Retina/HiDPI displays
- Existing attention animation is visually unchanged
-
zig build,zig build test, andjust lintall pass