Skip to content

Conversation

richiemcilroy
Copy link
Member

@richiemcilroy richiemcilroy commented Oct 13, 2025

This pull request introduces a new feature that allows the cursor to automatically hide after a period of inactivity, with a configurable delay.

Demo:
https://internal.cap.so/s/zye90nrj7fetttp

Summary by CodeRabbit

  • New Features

    • Added “Hide When Idle” option in the editor’s cursor settings.
    • When enabled, you can set an “Inactivity Delay” (0.5–5.0s) before the cursor hides.
  • Improvements

    • Cursor now fades out smoothly when idle and fades in on activity.
    • Enhanced cursor motion blur visuals for clearer movement.

Copy link
Contributor

coderabbitai bot commented Oct 13, 2025

Warning

Rate limit exceeded

@richiemcilroy has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 19 minutes and 5 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 8ef8362 and becfadd.

📒 Files selected for processing (3)
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx (3 hunks)
  • apps/desktop/src/utils/tauri.ts (1 hunks)
  • crates/rendering/src/layers/cursor.rs (4 hunks)

Walkthrough

Adds an idle-hide cursor feature configurable in the desktop editor. Introduces optional fields for cursor idle behavior and delay in both TypeScript and Rust configuration. Updates rendering layer and WGSL shader to support cursor opacity based on idle state and refactors cursor uniform layout. UI exposes toggle and delay slider.

Changes

Cohort / File(s) Summary
Editor UI: Idle toggle & delay
apps/desktop/src/routes/editor/ConfigSidebar.tsx
Adds “Hide When Idle” toggle and conditional “Inactivity Delay” slider (0.5–5s, step 0.1). Introduces helper functions for default delay and clamping; updates project state bindings.
Desktop types: CursorConfiguration
apps/desktop/src/utils/tauri.ts
Makes hideWhenIdle optional and adds hideWhenIdleDelay?: number to CursorConfiguration. Adjusts validation and control paths relying on these fields.
Project config (Rust)
crates/project/src/configuration.rs
Exposes hide_when_idle publicly and adds hide_when_idle_delay: f32 with serde defaults; provides default_hide_when_idle_delay() -> f32 = 2.0; updates Default impl.
Rendering layer: uniforms & idle opacity
crates/rendering/src/layers/cursor.rs
Adds idle-opacity computation with delay and fade-out constants. Refactors CursorUniforms to new packed fields: position_size, output_size, screen_bounds, velocity_blur_opacity. Adds helpers/tests for idle/fade behavior. Changes #[repr(C, align(16))] to #[repr(C)].
Shader: uniform schema & blur/opacity
crates/rendering/src/shaders/cursor.wgsl
Updates Uniforms to use position_size: vec4<f32> and velocity_blur_opacity: vec4<f32>; derives size/position accordingly. Uses .w as opacity in fragment stage. Adjusts blur logic and sampling (num_samples = 20).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as ConfigSidebar (Desktop)
  participant State as Project State
  participant Rend as Renderer
  participant GPU as Shader (WGSL)

  User->>UI: Toggle "Hide When Idle" / adjust "Inactivity Delay"
  UI->>State: Update project.cursor.hideWhenIdle / hideWhenIdleDelay
  State-->>Rend: Provide cursor config on render tick
  Rend->>Rend: Compute idle opacity (delay + fade)
  Rend->>GPU: Write CursorUniforms (position_size, ... , velocity_blur_opacity.w = opacity)
  GPU-->>User: Render cursor with opacity and motion blur
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

codex

Suggested reviewers

  • Brendonovich

Poem

I tap my paw, then softly wait—
The cursor fades, a hush of fate.
With sliders set and toggles true,
I hop through shaders, blending hue.
When motion stirs, I reappear—
A blink of light, a bunny cheer! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and concisely summarizes the primary change by indicating that the pull request adds a configurable idle cursor hiding delay along with a fade effect, matching the PR objectives and content.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (6)
apps/desktop/src/routes/editor/ConfigSidebar.tsx (3)

56-56: Do not manually import icons in the desktop app

Per guidelines, rely on auto-imported icons. Remove the explicit import and let auto-import tooling provide IconLucideTimer.

-import IconLucideTimer from "~icons/lucide/timer";

As per coding guidelines


231-236: Minor: avoid unnecessary type assertions and duplicate defaults

  • The cast to as number is redundant; ?? 2 already yields a number.
  • Consider centralizing the default (2.0) from shared types or a constant to avoid drift with Rust defaults.
-const cursorIdleDelay = () =>
-  ((project.cursor as { hideWhenIdleDelay?: number }).hideWhenIdleDelay ?? 2) as number;
+const cursorIdleDelay = () =>
+  (project.cursor as { hideWhenIdleDelay?: number }).hideWhenIdleDelay ?? 2;

470-504: Strict TS: remove as any casts when updating project cursor fields

The as any casts for hideWhenIdleDelay (and useSvg below) violate strict typing. Prefer updating the setter typings or introducing a typed helper for cursor updates to keep compile-time safety.

If desired, I can propose a typed setCursor helper to eliminate these casts across the file.

crates/rendering/src/shaders/cursor.wgsl (1)

6-11: Uniform packing and opacity pass-through look good; clean up unused locals

  • New position_size and velocity_blur_opacity usage is coherent with the Rust side and supports opacity fade.
  • Minor: weight_sum and t are unused; consider removing to reduce WGSL warnings/noise.
-    var weight_sum = 0.0;
...
-        let t = i / num_samples;
+        // keep sampling distribution simple; non-linear distribution can be re-introduced if needed

Also applies to: 38-48, 62-69, 71-89, 91-109

crates/rendering/src/layers/cursor.rs (2)

397-404: Uniform struct alignment: restore 16-byte alignment for uniform buffers

WGSL uniform structs are 16-byte aligned; while field sizes keep offsets at 16-byte multiples, adding align(16) avoids portability pitfalls across platforms/backends.

-#[repr(C)]
+#[repr(C, align(16))]
 #[derive(Debug, Clone, Copy, Pod, Zeroable, Default)]
 pub struct CursorUniforms {

419-443: Algorithmic note: consider binary search for last move ≤ time

rposition is O(n) per frame; with long recordings this can be costly. Since moves are time-ordered, use binary_search_by to find the last index ≤ current_time_ms in O(log n).

I can provide a drop-in binary search helper if you want to adopt it.

Also applies to: 454-473

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2a4471 and 8ef8362.

📒 Files selected for processing (5)
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx (3 hunks)
  • apps/desktop/src/utils/tauri.ts (1 hunks)
  • crates/project/src/configuration.rs (3 hunks)
  • crates/rendering/src/layers/cursor.rs (4 hunks)
  • crates/rendering/src/shaders/cursor.wgsl (4 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/tauri.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Never edit auto-generated IPC bindings file tauri.ts

Do not edit auto-generated files named tauri.ts.

Files:

  • apps/desktop/src/utils/tauri.ts
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/desktop/**/*.{ts,tsx}: Do not manually import icons in the desktop app; rely on auto-imported icons
In the desktop app, use @tanstack/solid-query for server state management

Files:

  • apps/desktop/src/utils/tauri.ts
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not add inline, block, or docstring comments in any language; code must be self-explanatory

Files:

  • apps/desktop/src/utils/tauri.ts
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx
  • crates/rendering/src/layers/cursor.rs
  • crates/project/src/configuration.rs
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use strict TypeScript and avoid any; leverage shared types from packages

**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by running pnpm format.

Files:

  • apps/desktop/src/utils/tauri.ts
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g., user-menu.tsx).
Use PascalCase for React/Solid components.

Files:

  • apps/desktop/src/utils/tauri.ts
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx
crates/*/src/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Rust crates should place tests within the src/ and/or a sibling tests/ directory for each crate inside crates/*.

Files:

  • crates/rendering/src/shaders/cursor.wgsl
  • crates/rendering/src/layers/cursor.rs
  • crates/project/src/configuration.rs
crates/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

For desktop IPC, use tauri_specta derive/macros on Rust types/events; do not hand-roll bindings

Files:

  • crates/rendering/src/layers/cursor.rs
  • crates/project/src/configuration.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Format Rust code using rustfmt and ensure all Rust code passes workspace-level clippy lints.
Rust modules should be named with snake_case, and crate directories should be in kebab-case.

Files:

  • crates/rendering/src/layers/cursor.rs
  • crates/project/src/configuration.rs
🧬 Code graph analysis (2)
apps/desktop/src/routes/editor/ConfigSidebar.tsx (2)
apps/desktop/src/routes/editor/ui.tsx (3)
  • Field (25-47)
  • Subfield (49-63)
  • Slider (65-147)
apps/desktop/src/components/Toggle.tsx (1)
  • Toggle (37-50)
crates/rendering/src/layers/cursor.rs (1)
crates/project/src/cursor.rs (1)
  • move_event (282-290)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (5)
crates/project/src/configuration.rs (1)

394-398: Cursor idle config: defaults and serialization look solid

Fields are public, serde defaults are correct, and TS bindings reflect optionality. Default of 2.0s aligns with UI.

Also applies to: 416-422, 438-441

apps/desktop/src/utils/tauri.ts (1)

381-381: Generated bindings updated correctly; ensure not edited manually

Type now includes optional hideWhenIdle/Delay, matching Rust serde defaults. Confirm this file remains auto-generated by tauri-specta in CI and not hand-edited.

crates/rendering/src/layers/cursor.rs (3)

359-374: Packing uniforms matches shader; good

position_size, output_size, and velocity_blur_opacity are correctly filled and written.

Also applies to: 376-380


214-216: Velocity/motion blur currently disabled

velocity is zeroed and motion_blur_amount multiplied by 0.0. If intentional, fine; otherwise restore real velocity to re-enable motion blur.


475-540: Tests cover fade-out and fade-in paths well

Good coverage of key idle transitions and thresholds.

@richiemcilroy richiemcilroy merged commit d882822 into main Oct 17, 2025
15 checks passed
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.

1 participant