Skip to content

Comments

feat(ui): wave animation on grid focus change, smooth filled terminal borders#236

Merged
forketyfork merged 4 commits intomainfrom
feat/nav-wave-smooth-border
Feb 22, 2026
Merged

feat(ui): wave animation on grid focus change, smooth filled terminal borders#236
forketyfork merged 4 commits intomainfrom
feat/nav-wave-smooth-border

Conversation

@forketyfork
Copy link
Owner

@forketyfork forketyfork commented Feb 22, 2026

Summary

Cmd+Arrow navigation in grid view now triggers a short squish-wave on the destination terminal. The nav wave runs for 250ms (vs 400ms for the attention wave) with amplitude 0.02 (vs 0.08), so it reads as "you moved here" rather than "something happened here." The waving terminal renders on top of its neighbours during the animation so the expanded strips aren't occluded. Terminal borders are redrawn with a scanline donut fill instead of stacked 1px arcs, which gets rid of the jagged corners and makes thickness consistent all the way around. Border thickness is now DPI-scaled (6 logical px × display density). The DPI scaling helper moved from src/ui/scale.zig to src/dpi.zig so the rendering layer can reach it without breaking the architecture layering rules.

Closes #235

Changes

src/gfx/primitives.zig: drawThickBorder used to draw thickness nested 1px outlines with the same corner radius. As each outline shrank inward, the arcs drifted apart and the corners looked uneven. The new version scanline-fills the donut between an outer rounded rect and an inner rounded rect inset by thickness, with inner radius clamped to max(0, outer_radius - thickness). The border is now the same width everywhere, corners included. A radius parameter replaces the hardcoded 12px value.

src/dpi.zig: scale.zig was in src/ui/, off-limits to the rendering layer. Moved to src/dpi.zig next to geom.zig and colors.zig. The 16 UI component imports were updated.

src/ui/components/session_interaction.zig, src/render/renderer.zig, src/app/runtime.zig: SessionViewState gets a nav_wave_start_time field alongside wave_start_time. triggerNavWave() sets it without touching attention state or session status. runtime.zig calls it after navigateGrid() for Cmd+Arrow in grid mode only, not for Cmd+1-9 (which expands to full-screen) or mouse clicks. The renderer reads the nav wave in renderGridSessionCached and passes nav_wave_amplitude (0.02, duration 250ms) to renderWaveStrips. If both waves are active at once, the attention wave wins. The .Grid render loop uses two passes so the waving terminal always draws on top. Border thickness is computed as dpi.scale(attention_thickness, ui_scale) at the draw site.

Test plan

  • In grid view with multiple terminals, press Cmd+Arrow in each direction and confirm a short wave plays on the newly focused terminal and is not hidden under neighbours
  • Confirm the wave amplitude is visibly smaller and shorter than the wave from an agent status notification
  • Press Cmd+1 from grid view and confirm no wave plays (the terminal expands to full-screen with no squish)
  • Confirm the blue focused-terminal border has smooth filled corners with no jagged edges
  • Confirm unfocused and attention-state borders also look clean at all four corners
  • On a Retina display, confirm both the corner radius and border thickness scale with display density

… borders

Issue: Cmd+Arrow grid navigation had no visual feedback. Terminal borders
were nested 1px rounded outlines with a fixed corner radius, so the arcs
diverged at corners and looked jagged. The DPI scaling helper was stuck in
src/ui/scale.zig, unreachable from the rendering layer without breaking the
architecture rules.

Solution: Cmd+Arrow now triggers a brief squish-wave on the destination
terminal at half the amplitude of the agent-notification wave. drawThickBorder
was rewritten to scanline-fill the donut between outer and inner rounded
rects, giving uniform border thickness with clean corners. The inner corner
radius shrinks by the border thickness to keep the frame consistent all the
way around. The DPI helper moved to src/dpi.zig alongside geom and colors,
where the renderer can reach it cleanly.
Issue: Waving terminal was hidden under neighbours in grid view; nav wave animation was too slow and too prominent; border was too thin.
Solution: Two-pass grid rendering ensures waving terminals draw last (on top). Nav wave duration reduced to 250ms and amplitude to 0.02. Border thickness increased from 3 to 6px. renderWaveStrips now takes total_ms so attention and nav waves can have independent durations.
@forketyfork forketyfork marked this pull request as ready for review February 22, 2026 06:34
@forketyfork forketyfork requested a review from Copilot February 22, 2026 06:40
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a distinct “navigation wave” animation when grid focus changes via Cmd+Arrow, improves terminal border rendering to use a scanline-filled rounded-rect donut for smoother corners, and relocates the DPI scaling helper so the render layer can import it.

Changes:

  • Add nav_wave_start_time to session view state and plumb a new nav-wave timing/amplitude through grid rendering.
  • Rewrite drawThickBorder to fill the border area (donut) between outer/inner rounded rects for consistent corner thickness; add an explicit radius parameter.
  • Move DPI scaling helper to src/dpi.zig and update UI component imports accordingly.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/ui/session_view_state.zig Adds nav_wave_start_time to support independent nav-wave animation state.
src/ui/components/session_interaction.zig Introduces nav-wave constants, triggerNavWave(), frame scheduling, and new tests.
src/render/renderer.zig Two-pass grid rendering to draw waving sessions on top; uses nav wave in renderGridSessionCached; passes DPI-scaled border radius into thick border drawing.
src/gfx/primitives.zig Replaces nested-outline thick border with scanline-filled donut border; adds roundedRectXSpan helper.
src/dpi.zig New shared DPI scaling helper module (previously under src/ui/).
src/app/runtime.zig Triggers nav wave after Cmd+Arrow grid navigation.
src/ui/components/worktree_overlay.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/story_overlay.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/scrollbar.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/recent_folders_overlay.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/reader_overlay.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/quit_confirm.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/hotkey_indicator.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/help_overlay.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/fullscreen_overlay.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/flowing_line.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/expanding_overlay.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/escape_hold.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/diff_overlay.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/cwd_bar.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/confirm_dialog.zig Updates DPI import path to new src/dpi.zig.
src/ui/components/button.zig Updates DPI import path to new src/dpi.zig.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Issue: Redundant markDirty() after triggerNavWave(); border thickness not DPI-scaled; PR description out of sync with actual constants.
Solution: Remove the redundant markDirty() call since triggerNavWave() already calls it. Apply dpi.scale() to attention_thickness at the draw site in renderSessionOverlays so border thickness scales correctly on Retina displays. Update PR description to reflect current values (250ms, 0.02 amplitude, 6px logical border, z-order fix).
Issue: dpi.zig (moved from ui/scale.zig) was missing from shared utilities documentation; Cmd+Arrow grid navigation was undocumented in README.
Solution: Add dpi to the shared utilities lists in ARCHITECTURE.md. Add Cmd+Arrow navigation with wave animation to the keyboard navigation line in README.
@forketyfork forketyfork merged commit 359e4dc into main Feb 22, 2026
4 checks passed
@forketyfork forketyfork deleted the feat/nav-wave-smooth-border branch February 22, 2026 07:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Wave animation on grid focus change + smooth filled terminal border

1 participant