Skip to content

Conversation

@ItsEeleeya
Copy link
Contributor

@ItsEeleeya ItsEeleeya commented Dec 7, 2025

Summary by CodeRabbit

  • New Features

    • Added macOS window control customization for traffic light visibility
    • Added file association metadata for Cap projects on macOS
  • Bug Fixes

    • Improved macOS accessibility permission handling
  • Refactor

    • Restructured window management API for consistency
    • Updated macOS platform integration layer
    • Migrated UI styling system to modern data-attribute selectors
    • Modernized PostCSS configuration
  • Dependencies

    • Updated Tauri and core plugins
    • Upgraded Tailwind CSS to v4
    • Updated UI component libraries
  • Style

    • Standardized CSS utilities across codebase
    • Unified UI state selectors

✏️ Tip: You can customize this high-level summary in your review settings.

New min width for settings window.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 7, 2025

Walkthrough

This PR performs a comprehensive refactoring of the desktop application's window system (renaming CapWindowId to CapWindowDef and ShowCapWindow to CapWindow), migrates macOS platform code from legacy objc/cocoa to objc2 dependencies, updates Tailwind CSS to v4 syntax across the frontend, and consolidates styling state selectors from ui-* to data-* attributes. It also removes custom window delegate handling and introduces new macOS platform extensions.

Changes

Cohort / File(s) Summary
Window Type Renaming & Core Refactoring
apps/desktop/src-tauri/src/windows.rs, apps/desktop/src-tauri/src/lib.rs, apps/desktop/src-tauri/src/recording.rs, apps/desktop/src-tauri/src/target_select_overlay.rs, apps/desktop/src-tauri/src/screenshot_editor.rs, apps/desktop/src-tauri/src/tray.rs, apps/desktop/src-tauri/src/deeplink_actions.rs, apps/desktop/src-tauri/src/hotkeys.rs, apps/desktop/src/utils/tauri.ts
Systematic replacement of CapWindowIdCapWindowDef and ShowCapWindowCapWindow throughout window management and invocation layers; includes updated variant patterns, label lookups, getter methods, and public API signatures.
macOS Platform Code Migration
apps/desktop/src-tauri/Cargo.toml, apps/desktop/src-tauri/src/permissions.rs, apps/desktop/src-tauri/src/platform/macos/mod.rs, apps/desktop/src-tauri/src/platform/macos/delegates.rs, apps/desktop/src-tauri/src/platform/mod.rs
Transition from objc/cocoa to objc2-based dependencies; removal of delegates.rs (custom window delegate handling); introduction of WebviewWindowExt trait with objc2_nswindow() and set_traffic_lights_visible() methods; updated permissions flow using objc2 FFI.
Workspace & Dependency Updates
Cargo.toml, apps/desktop/package.json, apps/desktop/src-tauri/Cargo.toml, crates/cursor-info/Cargo.toml, crates/scap-screencapturekit/Cargo.toml, packages/ui-solid/package.json
Bumped tauri from 2.5.0 to 2.9.3, updated plugin versions, added objc2 as workspace dependency, replaced Tailwind tooling (@tailwindcss/postcss, tailwind-scrollbar), updated @kobalte/core.
Configuration & Build Files
apps/desktop/postcss.config.cjs, apps/desktop/tailwind.config.js, packages/ui-solid/tailwind.config.js, packages/ui-solid/src/main.css, apps/desktop/src/styles/theme.css, apps/desktop/tauri.conf.json
Explicit PostCSS plugin configuration; removed app-level Tailwind config (migrated to main.css); introduced comprehensive theme/custom-variant definitions in main.css; added macOS minimumSystemVersion 13.1 and file associations.
Frontend Styling Syntax Migration
~80+ component files across apps/desktop/src/ and packages/ui*/src/
Systematic class-name updates: arbitrary bracket syntax text-[--text-primary] → parenthesis syntax text-(--text-primary), bg-gradient-to-*bg-linear-to-*, replaced ui-* state selectors with data-* equivalents, standardized arbitrary size/spacing to Tailwind tokens (e.g., h-[2rem]h-8, gap-[0.75rem]gap-3).
Editor Timeline Refactoring
apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx
Replaced memoization and conditional rendering with direct Index iteration over project.timeline.zoomSegments; refactored drag/resize logic to use index parameter from iterator; removed isSegmentVisible computation.
UI Component Updates
packages/ui-solid/src/Button.tsx, packages/ui/src/components/Button.tsx, packages/ui-solid/src/SwitchTab.tsx, and related component files
Updated size variants to Tailwind tokens, replaced gradient utilities, adjusted state selectors to data-* attributes, standardized border/radius/padding tokens.

Sequence Diagram(s)

No sequence diagrams generated. The changes, while extensive and affecting multiple components, are predominantly refactoring (renaming), styling updates, and dependency management—they do not introduce new multi-component control-flow interactions or significant feature behavior changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Key areas requiring extra attention:

  • apps/desktop/src-tauri/src/windows.rs: Core refactoring of window type definitions and public API surface; verify all enum variants, method signatures, and trait implementations are consistent across all call sites.
  • apps/desktop/src-tauri/Cargo.toml: macOS-specific dependency migration from objc/cocoa to objc2; verify feature flags and compatibility with native window handling.
  • apps/desktop/src-tauri/src/platform/macos/mod.rs & removed delegates.rs: Transition from custom delegate-based window management to new extension trait; ensure no functionality loss (traffic lights, event handling, window lifecycle).
  • apps/desktop/src-tauri/src/lib.rs: Largest file with pervasive CapWindowIdCapWindowDef replacements; verify control-flow logic, pattern matching, and error handling remain correct.
  • packages/ui-solid/src/main.css & theme migration: New Tailwind v4 theme structure and custom variants; ensure all colors, animations, and tokens resolve correctly across frontend.
  • apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx: Logic-level refactor from memoized rendering to iterator-based; verify segment manipulation (drag, resize, split) behavior is preserved and state updates are correct.
  • Styling consistency across ~80 frontend files: Spot-check a sample of arbitrary-to-token conversions (e.g., h-[2rem]h-8, text-[--text-primary]text-(--text-primary)) to ensure no visual regressions.

Possibly related PRs

Suggested labels

Desktop, macOS, refactoring, styling, dependencies

Suggested reviewers

  • oscartbeaumont
  • Brendonovich

Poem

🐰 Windows renamed, from Id to Def,
objc2 now speaks where cocoa left—
Tailwind v4 paints, data-states align,
Zoom tracks iterate, where memos were fine,
A grand refactor, made clean and refined! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.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 'Desktop app Tailwind 4' accurately describes the primary change: upgrading the desktop application to use Tailwind CSS v4, which is reflected across numerous file changes including tailwind.config.js updates, CSS class syntax changes, and dependency version bumps.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@ItsEeleeya
Copy link
Contributor Author

Some hover elements aren't working properly yet.
This fixes one issue where cursor-default didn't have any effects before, now the cursor stays the same when hovering over buttons etc, like any native app.

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: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/desktop/src-tauri/src/lib.rs (1)

2858-2864: Avoid unwrap() on CapWindowDef::from_str in hide_dock_icon logic

Here:

if let Some(settings) = GeneralSettingsStore::get(app).unwrap_or(None)
    && settings.hide_dock_icon
    && app
        .webview_windows()
        .keys()
        .all(|label| !CapWindowDef::from_str(label).unwrap().activates_dock())
{
    // ...
}

any window label not recognized by CapWindowDef::from_str (for example, windows created by plugins) will cause a panic via unwrap(). This can crash the app when the last window is destroyed while hide_dock_icon is enabled.

Consider treating unknown labels as non‑activating instead of panicking:

-        .keys()
-        .all(|label| !CapWindowDef::from_str(label).unwrap().activates_dock())
+        .keys()
+        .all(|label| {
+            CapWindowDef::from_str(label)
+                .map(|id| !id.activates_dock())
+                .unwrap_or(true)
+        })

This preserves behavior for known windows and safely ignores any others.

apps/desktop/src-tauri/src/windows.rs (1)

377-407: Fix undefined window_builder in Windows TargetSelectOverlay branch

In the TargetSelectOverlay variant, the Windows-specific block currently reads:

#[cfg(windows)]
{
-    builder = window_builder.inner_size(100.0, 100.0).position(0.0, 0.0);
}

window_builder is not defined in this scope; the intended variable is the existing mutable builder. This will fail to compile on Windows.

Suggested fix:

#[cfg(windows)]
{
-    builder = window_builder.inner_size(100.0, 100.0).position(0.0, 0.0);
+    builder = builder.inner_size(100.0, 100.0).position(0.0, 0.0);
}

This keeps the behavior the same while fixing the compilation error.

🧹 Nitpick comments (5)
apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx (1)

400-412: Consider using segment IDs instead of positional indices for selection.

The findIndex lookup by start/end values works around the issue that sorting segments (lines 477-480, 593-596) invalidates stored indices. However, this creates O(n) lookups per segment and a dependency on the entire zoomSegments array.

A cleaner approach would be to assign stable IDs to segments and use those in selection.indices instead of positional indices. This would simplify isSelected to:

 const isSelected = createMemo(() => {
   const selection = editorState.timeline.selection;
   if (!selection || selection.type !== "zoom") return false;
-  const seg = segment();
-  const segmentIndex = project.timeline?.zoomSegments?.findIndex(
-    (s) => s.start === seg.start && s.end === seg.end,
-  );
-  if (segmentIndex === undefined || segmentIndex === -1) return false;
-  return selection.indices.includes(segmentIndex);
+  return selection.ids.includes(segment().id);
 });
packages/ui/src/components/Cmdk.tsx (1)

94-101: Confirm group heading token behavior and consider centralizing styling

The CommandGroup heading styles now mirror the token-based approach from CommandDialog (**:[[cmdk-group-heading]]:*) while still retaining the [&_[cmdk-group-heading]]:text-muted-foreground selector. Functionally this should work, but:

  • It’s worth verifying that both selectors still resolve to the same DOM node after the cmdk/Tailwind changes.
  • If the intent is for [[cmdk-group-heading]] to be the single source of truth, you may want to centralize all heading typography/spacing in CommandGroup (or a shared place) to avoid future divergence.

This is primarily a maintainability concern rather than a functional bug.

apps/desktop/src/routes/screenshot-editor/popovers/BackgroundSettingsPopover.tsx (1)

255-269: Consolidate ui-* variants to data-* / standard hover for consistency

These blocks still mix legacy ui-not-selected / ui-not-checked variants with the new data-selected and data-checked styling:

  • Line 260: KTabs.Trigger keeps ui-not-selected:hover:border-gray-7.
  • Line 288: Wallpaper theme tab trigger also uses ui-not-selected:hover:border-gray-7.
  • Line 325: KRadioGroup.ItemControl keeps multiple ui-not-checked:* ring classes alongside data-checked:*.

If the ui-* variant plugin is being phased out with the Tailwind 4 migration, these classes will become dead weight and make state styling harder to follow. Even if the plugin remains, it would be clearer to express “idle” vs “selected/checked” purely via:

  • Baseline + hover:* utilities for the idle state.
  • data-selected:* / data-checked:* utilities for the active state.

Consider removing the ui-* pieces and encoding the intended hover/border/ring behavior with hover:* plus the existing data-* attributes.

Also applies to: 288-288, 323-335, 345-355

apps/desktop/src/routes/editor/Editor.tsx (1)

476-485: Consider tightening vertical padding on crop NumberField input

The crop dialog’s NumberField.Input now combines h-8 with py-[18px]:

class="... h-8 ... py-[18px] ..."

For an 8‑unit tall control this is a lot of vertical padding and may visually fight with the fixed height (or lead to inconsistent text baselines compared to other 8‑unit inputs). It might be worth revisiting the py-* value here to better match the new height scale and the rest of the editor’s form controls, while keeping the rest of the spacing/transition changes as‑is.

Also applies to: 487-507, 525-528

apps/desktop/src-tauri/src/recording.rs (1)

1224-1242: Avoid duplicated Camera window close calls in handle_recording_end

Within the else branch after attempting to unminimize CapWindowDef::Main, CapWindowDef::Camera.get(&handle) is invoked twice to close the camera window. This is harmless but redundant and slightly obscures intent.

You can simplify to a single close:

-    } else {
-        if let Some(v) = CapWindowDef::Camera.get(&handle) {
-            let _ = v.close();
-        }
-        let _ = app.mic_feed.ask(microphone::RemoveInput).await;
-        let _ = app.camera_feed.ask(camera::RemoveInput).await;
-        app.selected_mic_label = None;
-        app.selected_camera_id = None;
-        app.camera_in_use = false;
-        if let Some(win) = CapWindowDef::Camera.get(&handle) {
-            win.close().ok();
-        }
-    }
+    } else {
+        if let Some(camera) = CapWindowDef::Camera.get(&handle) {
+            camera.close().ok();
+        }
+        let _ = app.mic_feed.ask(microphone::RemoveInput).await;
+        let _ = app.camera_feed.ask(camera::RemoveInput).await;
+        app.selected_mic_label = None;
+        app.selected_camera_id = None;
+        app.camera_in_use = false;
+    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cea939a and ce7192e.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (96)
  • Cargo.toml (3 hunks)
  • apps/desktop/package.json (2 hunks)
  • apps/desktop/postcss.config.cjs (1 hunks)
  • apps/desktop/src-tauri/Cargo.toml (2 hunks)
  • apps/desktop/src-tauri/src/deeplink_actions.rs (2 hunks)
  • apps/desktop/src-tauri/src/hotkeys.rs (2 hunks)
  • apps/desktop/src-tauri/src/lib.rs (22 hunks)
  • apps/desktop/src-tauri/src/permissions.rs (2 hunks)
  • apps/desktop/src-tauri/src/platform/macos/delegates.rs (0 hunks)
  • apps/desktop/src-tauri/src/platform/macos/mod.rs (1 hunks)
  • apps/desktop/src-tauri/src/platform/mod.rs (1 hunks)
  • apps/desktop/src-tauri/src/recording.rs (9 hunks)
  • apps/desktop/src-tauri/src/screenshot_editor.rs (2 hunks)
  • apps/desktop/src-tauri/src/target_select_overlay.rs (5 hunks)
  • apps/desktop/src-tauri/src/tray.rs (3 hunks)
  • apps/desktop/src-tauri/src/windows.rs (28 hunks)
  • apps/desktop/src-tauri/tauri.conf.json (2 hunks)
  • apps/desktop/src/components/CapErrorBoundary.tsx (1 hunks)
  • apps/desktop/src/components/Loader.tsx (1 hunks)
  • apps/desktop/src/components/SignInButton.tsx (1 hunks)
  • apps/desktop/src/components/Toggle.tsx (2 hunks)
  • apps/desktop/src/components/titlebar/Titlebar.tsx (1 hunks)
  • apps/desktop/src/entry-server.tsx (1 hunks)
  • apps/desktop/src/routes/(window-chrome).tsx (1 hunks)
  • apps/desktop/src/routes/(window-chrome)/(main).tsx (10 hunks)
  • apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx (1 hunks)
  • apps/desktop/src/routes/(window-chrome)/new-main/MicrophoneSelect.tsx (1 hunks)
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetCard.tsx (4 hunks)
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx (1 hunks)
  • apps/desktop/src/routes/(window-chrome)/new-main/index.tsx (3 hunks)
  • apps/desktop/src/routes/(window-chrome)/settings.tsx (3 hunks)
  • apps/desktop/src/routes/(window-chrome)/settings/changelog.tsx (1 hunks)
  • apps/desktop/src/routes/(window-chrome)/settings/hotkeys.tsx (1 hunks)
  • apps/desktop/src/routes/(window-chrome)/settings/integrations/s3-config.tsx (2 hunks)
  • apps/desktop/src/routes/(window-chrome)/settings/license.tsx (3 hunks)
  • apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx (3 hunks)
  • apps/desktop/src/routes/(window-chrome)/settings/screenshots.tsx (3 hunks)
  • apps/desktop/src/routes/(window-chrome)/setup.tsx (7 hunks)
  • apps/desktop/src/routes/(window-chrome)/update.tsx (3 hunks)
  • apps/desktop/src/routes/(window-chrome)/upgrade.tsx (6 hunks)
  • apps/desktop/src/routes/camera.tsx (3 hunks)
  • apps/desktop/src/routes/capture-area.tsx (4 hunks)
  • apps/desktop/src/routes/debug.tsx (1 hunks)
  • apps/desktop/src/routes/editor/AspectRatioSelect.tsx (1 hunks)
  • apps/desktop/src/routes/editor/CaptionsTab.tsx (4 hunks)
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx (26 hunks)
  • apps/desktop/src/routes/editor/Editor.tsx (3 hunks)
  • apps/desktop/src/routes/editor/ExportDialog.tsx (1 hunks)
  • apps/desktop/src/routes/editor/Header.tsx (1 hunks)
  • apps/desktop/src/routes/editor/PresetsDropdown.tsx (1 hunks)
  • apps/desktop/src/routes/editor/ShadowSettings.tsx (1 hunks)
  • apps/desktop/src/routes/editor/ShareButton.tsx (3 hunks)
  • apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx (5 hunks)
  • apps/desktop/src/routes/editor/Timeline/MaskTrack.tsx (2 hunks)
  • apps/desktop/src/routes/editor/Timeline/SceneTrack.tsx (3 hunks)
  • apps/desktop/src/routes/editor/Timeline/TextTrack.tsx (3 hunks)
  • apps/desktop/src/routes/editor/Timeline/Track.tsx (1 hunks)
  • apps/desktop/src/routes/editor/Timeline/TrackManager.tsx (2 hunks)
  • apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx (3 hunks)
  • apps/desktop/src/routes/editor/Timeline/index.tsx (4 hunks)
  • apps/desktop/src/routes/editor/ui.tsx (11 hunks)
  • apps/desktop/src/routes/in-progress-recording.tsx (3 hunks)
  • apps/desktop/src/routes/recordings-overlay.tsx (8 hunks)
  • apps/desktop/src/routes/screenshot-editor/AnnotationConfig.tsx (1 hunks)
  • apps/desktop/src/routes/screenshot-editor/AnnotationTools.tsx (1 hunks)
  • apps/desktop/src/routes/screenshot-editor/ColorPicker.tsx (3 hunks)
  • apps/desktop/src/routes/screenshot-editor/Editor.tsx (5 hunks)
  • apps/desktop/src/routes/screenshot-editor/popovers/AspectRatioSelect.tsx (1 hunks)
  • apps/desktop/src/routes/screenshot-editor/popovers/BackgroundSettingsPopover.tsx (4 hunks)
  • apps/desktop/src/routes/screenshot-editor/popovers/BorderPopover.tsx (1 hunks)
  • apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsx (1 hunks)
  • apps/desktop/src/routes/screenshot-editor/popovers/ShadowSettings.tsx (1 hunks)
  • apps/desktop/src/routes/screenshot-editor/ui.tsx (11 hunks)
  • apps/desktop/src/routes/target-select-overlay.tsx (3 hunks)
  • apps/desktop/src/styles/theme.css (2 hunks)
  • apps/desktop/src/utils/tauri.ts (2 hunks)
  • apps/desktop/tailwind.config.js (0 hunks)
  • apps/web/app/(org)/dashboard/caps/components/web-recorder-dialog/CameraPreviewWindow.tsx (5 hunks)
  • crates/cursor-info/Cargo.toml (1 hunks)
  • crates/scap-screencapturekit/Cargo.toml (1 hunks)
  • packages/ui-solid/package.json (1 hunks)
  • packages/ui-solid/src/Button.tsx (1 hunks)
  • packages/ui-solid/src/SwitchTab.tsx (2 hunks)
  • packages/ui-solid/src/main.css (1 hunks)
  • packages/ui-solid/tailwind.config.js (0 hunks)
  • packages/ui/src/components/Button.tsx (2 hunks)
  • packages/ui/src/components/Card.tsx (1 hunks)
  • packages/ui/src/components/Cmdk.tsx (3 hunks)
  • packages/ui/src/components/Dialog.tsx (2 hunks)
  • packages/ui/src/components/Dropdown.tsx (5 hunks)
  • packages/ui/src/components/NavigationMenu.tsx (3 hunks)
  • packages/ui/src/components/Select.tsx (4 hunks)
  • packages/ui/src/components/SkeletonRows.tsx (1 hunks)
  • packages/ui/src/components/Switch.tsx (1 hunks)
  • packages/ui/src/components/Table.tsx (2 hunks)
  • packages/ui/src/components/input/Input.tsx (1 hunks)
💤 Files with no reviewable changes (3)
  • packages/ui-solid/tailwind.config.js
  • apps/desktop/src-tauri/src/platform/macos/delegates.rs
  • apps/desktop/tailwind.config.js
🧰 Additional context used
📓 Path-based instructions (10)
**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Use React Query hooks with Server Actions for mutations and perform precise cache updates using setQueryData/setQueriesData instead of broad invalidations

Files:

  • apps/desktop/src/routes/(window-chrome)/settings/hotkeys.tsx
  • packages/ui/src/components/Dialog.tsx
  • packages/ui/src/components/input/Input.tsx
  • apps/desktop/src/routes/editor/Timeline/SceneTrack.tsx
  • apps/desktop/src/components/Toggle.tsx
  • apps/desktop/src/routes/editor/AspectRatioSelect.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx
  • packages/ui-solid/src/SwitchTab.tsx
  • apps/desktop/src/routes/screenshot-editor/AnnotationConfig.tsx
  • apps/web/app/(org)/dashboard/caps/components/web-recorder-dialog/CameraPreviewWindow.tsx
  • apps/desktop/src/routes/debug.tsx
  • apps/desktop/src/routes/editor/CaptionsTab.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/BorderPopover.tsx
  • apps/desktop/src/components/SignInButton.tsx
  • apps/desktop/src/routes/screenshot-editor/AnnotationTools.tsx
  • apps/desktop/src/routes/editor/Timeline/TrackManager.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/MicrophoneSelect.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/changelog.tsx
  • packages/ui-solid/src/Button.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx
  • packages/ui/src/components/Switch.tsx
  • apps/desktop/src/routes/(window-chrome)/settings.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/screenshots.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/AspectRatioSelect.tsx
  • packages/ui/src/components/Select.tsx
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx
  • apps/desktop/src/routes/editor/ExportDialog.tsx
  • apps/desktop/src/routes/editor/Timeline/TextTrack.tsx
  • apps/desktop/src/routes/recordings-overlay.tsx
  • apps/desktop/src/routes/camera.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/ShadowSettings.tsx
  • apps/desktop/src/routes/in-progress-recording.tsx
  • apps/desktop/src/routes/editor/Header.tsx
  • apps/desktop/src/components/Loader.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/license.tsx
  • packages/ui/src/components/NavigationMenu.tsx
  • apps/desktop/src/routes/(window-chrome)/update.tsx
  • apps/desktop/src/components/CapErrorBoundary.tsx
  • apps/desktop/src/routes/editor/PresetsDropdown.tsx
  • apps/desktop/src/routes/(window-chrome)/upgrade.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/integrations/s3-config.tsx
  • packages/ui/src/components/Card.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/index.tsx
  • apps/desktop/src/routes/editor/Timeline/index.tsx
  • packages/ui/src/components/Button.tsx
  • apps/desktop/src/routes/screenshot-editor/ColorPicker.tsx
  • apps/desktop/src/routes/editor/ShadowSettings.tsx
  • apps/desktop/src/routes/editor/Timeline/Track.tsx
  • apps/desktop/src/routes/(window-chrome)/(main).tsx
  • apps/desktop/src/routes/(window-chrome)/setup.tsx
  • apps/desktop/src/routes/capture-area.tsx
  • apps/desktop/src/routes/editor/Timeline/MaskTrack.tsx
  • apps/desktop/src/routes/editor/ui.tsx
  • apps/desktop/src/routes/editor/Editor.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx
  • apps/desktop/src/entry-server.tsx
  • packages/ui/src/components/Cmdk.tsx
  • packages/ui/src/components/SkeletonRows.tsx
  • apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetCard.tsx
  • packages/ui/src/components/Dropdown.tsx
  • apps/desktop/src/routes/target-select-overlay.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsx
  • apps/desktop/src/routes/(window-chrome).tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/BackgroundSettingsPopover.tsx
  • packages/ui/src/components/Table.tsx
  • apps/desktop/src/routes/screenshot-editor/Editor.tsx
  • apps/desktop/src/routes/editor/ShareButton.tsx
  • apps/desktop/src/components/titlebar/Titlebar.tsx
  • apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
  • apps/desktop/src/routes/screenshot-editor/ui.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Use strict TypeScript; avoid any type; leverage shared types from @cap/* packages
Follow camelCase naming for variables and functions; PascalCase for components; hooks must start with 'use' prefix
Use Biome for linting and formatting; match existing formatting conventions in the codebase
Use Tailwind CSS for styling in web components; stay consistent with spacing and tokens
Use static skeletons for loading states that mirror content; avoid bouncing animations
Memoize expensive work, code-split naturally, and use Next/Image for remote assets

**/*.{ts,tsx,js,jsx}: Use 2-space indent for TypeScript files; format with Biome using pnpm format
Use Biome for code formatting and linting; run pnpm format regularly
Use kebab-case for file names (e.g., user-menu.tsx); use PascalCase for components

Files:

  • apps/desktop/src/routes/(window-chrome)/settings/hotkeys.tsx
  • packages/ui/src/components/Dialog.tsx
  • packages/ui/src/components/input/Input.tsx
  • apps/desktop/src/routes/editor/Timeline/SceneTrack.tsx
  • apps/desktop/src/components/Toggle.tsx
  • apps/desktop/src/routes/editor/AspectRatioSelect.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx
  • packages/ui-solid/src/SwitchTab.tsx
  • apps/desktop/src/routes/screenshot-editor/AnnotationConfig.tsx
  • apps/web/app/(org)/dashboard/caps/components/web-recorder-dialog/CameraPreviewWindow.tsx
  • apps/desktop/src/routes/debug.tsx
  • apps/desktop/src/routes/editor/CaptionsTab.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/BorderPopover.tsx
  • apps/desktop/src/components/SignInButton.tsx
  • apps/desktop/src/routes/screenshot-editor/AnnotationTools.tsx
  • apps/desktop/src/routes/editor/Timeline/TrackManager.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/MicrophoneSelect.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/changelog.tsx
  • packages/ui-solid/src/Button.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx
  • packages/ui/src/components/Switch.tsx
  • apps/desktop/src/routes/(window-chrome)/settings.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/screenshots.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/AspectRatioSelect.tsx
  • packages/ui/src/components/Select.tsx
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx
  • apps/desktop/src/routes/editor/ExportDialog.tsx
  • apps/desktop/src/routes/editor/Timeline/TextTrack.tsx
  • apps/desktop/src/routes/recordings-overlay.tsx
  • apps/desktop/src/routes/camera.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/ShadowSettings.tsx
  • apps/desktop/src/routes/in-progress-recording.tsx
  • apps/desktop/src/routes/editor/Header.tsx
  • apps/desktop/src/components/Loader.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/license.tsx
  • packages/ui/src/components/NavigationMenu.tsx
  • apps/desktop/src/routes/(window-chrome)/update.tsx
  • apps/desktop/src/components/CapErrorBoundary.tsx
  • apps/desktop/src/routes/editor/PresetsDropdown.tsx
  • apps/desktop/src/routes/(window-chrome)/upgrade.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/integrations/s3-config.tsx
  • packages/ui/src/components/Card.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/index.tsx
  • apps/desktop/src/routes/editor/Timeline/index.tsx
  • packages/ui/src/components/Button.tsx
  • apps/desktop/src/routes/screenshot-editor/ColorPicker.tsx
  • apps/desktop/src/routes/editor/ShadowSettings.tsx
  • apps/desktop/src/routes/editor/Timeline/Track.tsx
  • apps/desktop/src/routes/(window-chrome)/(main).tsx
  • apps/desktop/src/routes/(window-chrome)/setup.tsx
  • apps/desktop/src/routes/capture-area.tsx
  • apps/desktop/src/routes/editor/Timeline/MaskTrack.tsx
  • apps/desktop/src/routes/editor/ui.tsx
  • apps/desktop/src/routes/editor/Editor.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx
  • apps/desktop/src/entry-server.tsx
  • apps/desktop/src/utils/tauri.ts
  • packages/ui/src/components/Cmdk.tsx
  • packages/ui/src/components/SkeletonRows.tsx
  • apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetCard.tsx
  • packages/ui/src/components/Dropdown.tsx
  • apps/desktop/src/routes/target-select-overlay.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsx
  • apps/desktop/src/routes/(window-chrome).tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/BackgroundSettingsPopover.tsx
  • packages/ui/src/components/Table.tsx
  • apps/desktop/src/routes/screenshot-editor/Editor.tsx
  • apps/desktop/src/routes/editor/ShareButton.tsx
  • apps/desktop/src/components/titlebar/Titlebar.tsx
  • apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
  • apps/desktop/src/routes/screenshot-editor/ui.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Never add any form of comments to code (single-line //, multi-line /* /, JSDoc /* */, or any other comment syntax); code must be self-explanatory through naming, types, and structure
Directory naming must use lowercase-dashed convention

Files:

  • apps/desktop/src/routes/(window-chrome)/settings/hotkeys.tsx
  • packages/ui/src/components/Dialog.tsx
  • packages/ui/src/components/input/Input.tsx
  • apps/desktop/src/routes/editor/Timeline/SceneTrack.tsx
  • apps/desktop/src/components/Toggle.tsx
  • apps/desktop/src/routes/editor/AspectRatioSelect.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx
  • packages/ui-solid/src/SwitchTab.tsx
  • apps/desktop/src/routes/screenshot-editor/AnnotationConfig.tsx
  • apps/web/app/(org)/dashboard/caps/components/web-recorder-dialog/CameraPreviewWindow.tsx
  • apps/desktop/src/routes/debug.tsx
  • apps/desktop/src/routes/editor/CaptionsTab.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/BorderPopover.tsx
  • apps/desktop/src/components/SignInButton.tsx
  • apps/desktop/src/routes/screenshot-editor/AnnotationTools.tsx
  • apps/desktop/src/routes/editor/Timeline/TrackManager.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/MicrophoneSelect.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/changelog.tsx
  • packages/ui-solid/src/Button.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx
  • packages/ui/src/components/Switch.tsx
  • apps/desktop/src/routes/(window-chrome)/settings.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/screenshots.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/AspectRatioSelect.tsx
  • packages/ui/src/components/Select.tsx
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx
  • apps/desktop/src/routes/editor/ExportDialog.tsx
  • apps/desktop/src/routes/editor/Timeline/TextTrack.tsx
  • apps/desktop/src/routes/recordings-overlay.tsx
  • apps/desktop/src/routes/camera.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/ShadowSettings.tsx
  • apps/desktop/src/routes/in-progress-recording.tsx
  • apps/desktop/src/routes/editor/Header.tsx
  • apps/desktop/src/components/Loader.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/license.tsx
  • packages/ui/src/components/NavigationMenu.tsx
  • apps/desktop/src/routes/(window-chrome)/update.tsx
  • apps/desktop/src/components/CapErrorBoundary.tsx
  • apps/desktop/src/routes/editor/PresetsDropdown.tsx
  • apps/desktop/src/routes/(window-chrome)/upgrade.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/integrations/s3-config.tsx
  • packages/ui/src/components/Card.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/index.tsx
  • apps/desktop/src/routes/editor/Timeline/index.tsx
  • packages/ui/src/components/Button.tsx
  • apps/desktop/src/routes/screenshot-editor/ColorPicker.tsx
  • apps/desktop/src/routes/editor/ShadowSettings.tsx
  • apps/desktop/src/routes/editor/Timeline/Track.tsx
  • apps/desktop/src/routes/(window-chrome)/(main).tsx
  • apps/desktop/src/routes/(window-chrome)/setup.tsx
  • apps/desktop/src/routes/capture-area.tsx
  • apps/desktop/src/routes/editor/Timeline/MaskTrack.tsx
  • apps/desktop/src/routes/editor/ui.tsx
  • apps/desktop/src/routes/editor/Editor.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx
  • apps/desktop/src/entry-server.tsx
  • apps/desktop/src/utils/tauri.ts
  • packages/ui/src/components/Cmdk.tsx
  • packages/ui/src/components/SkeletonRows.tsx
  • apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetCard.tsx
  • packages/ui/src/components/Dropdown.tsx
  • apps/desktop/src/routes/target-select-overlay.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsx
  • apps/desktop/src/routes/(window-chrome).tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/BackgroundSettingsPopover.tsx
  • packages/ui/src/components/Table.tsx
  • apps/desktop/src/routes/screenshot-editor/Editor.tsx
  • apps/desktop/src/routes/editor/ShareButton.tsx
  • apps/desktop/src/components/titlebar/Titlebar.tsx
  • apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
  • apps/desktop/src/routes/screenshot-editor/ui.tsx
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (AGENTS.md)

Never add comments to code (//, /* */, ///, //!, #, etc.); code must be self-explanatory through naming, types, and structure

Files:

  • apps/desktop/src/routes/(window-chrome)/settings/hotkeys.tsx
  • apps/desktop/src-tauri/src/tray.rs
  • packages/ui/src/components/Dialog.tsx
  • packages/ui/src/components/input/Input.tsx
  • apps/desktop/src/routes/editor/Timeline/SceneTrack.tsx
  • apps/desktop/src/components/Toggle.tsx
  • apps/desktop/src/routes/editor/AspectRatioSelect.tsx
  • apps/desktop/src-tauri/src/deeplink_actions.rs
  • apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx
  • packages/ui-solid/src/SwitchTab.tsx
  • apps/desktop/src/routes/screenshot-editor/AnnotationConfig.tsx
  • apps/web/app/(org)/dashboard/caps/components/web-recorder-dialog/CameraPreviewWindow.tsx
  • apps/desktop/src/routes/debug.tsx
  • apps/desktop/src/routes/editor/CaptionsTab.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/BorderPopover.tsx
  • apps/desktop/src/components/SignInButton.tsx
  • apps/desktop/src/routes/screenshot-editor/AnnotationTools.tsx
  • apps/desktop/src/routes/editor/Timeline/TrackManager.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/MicrophoneSelect.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/changelog.tsx
  • packages/ui-solid/src/Button.tsx
  • apps/desktop/src-tauri/src/hotkeys.rs
  • apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx
  • packages/ui/src/components/Switch.tsx
  • apps/desktop/src/routes/(window-chrome)/settings.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/screenshots.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/AspectRatioSelect.tsx
  • apps/desktop/src-tauri/src/permissions.rs
  • packages/ui/src/components/Select.tsx
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx
  • apps/desktop/src/routes/editor/ExportDialog.tsx
  • apps/desktop/src/routes/editor/Timeline/TextTrack.tsx
  • apps/desktop/src/routes/recordings-overlay.tsx
  • apps/desktop/src-tauri/src/platform/mod.rs
  • apps/desktop/src/routes/camera.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/ShadowSettings.tsx
  • apps/desktop/src/routes/in-progress-recording.tsx
  • apps/desktop/src/routes/editor/Header.tsx
  • apps/desktop/src/components/Loader.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/license.tsx
  • packages/ui/src/components/NavigationMenu.tsx
  • apps/desktop/src/routes/(window-chrome)/update.tsx
  • apps/desktop/src/components/CapErrorBoundary.tsx
  • apps/desktop/src/routes/editor/PresetsDropdown.tsx
  • apps/desktop/src/routes/(window-chrome)/upgrade.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/integrations/s3-config.tsx
  • packages/ui/src/components/Card.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/index.tsx
  • apps/desktop/src/routes/editor/Timeline/index.tsx
  • packages/ui/src/components/Button.tsx
  • apps/desktop/src-tauri/src/screenshot_editor.rs
  • apps/desktop/src/routes/screenshot-editor/ColorPicker.tsx
  • apps/desktop/src/routes/editor/ShadowSettings.tsx
  • apps/desktop/src/routes/editor/Timeline/Track.tsx
  • apps/desktop/src/routes/(window-chrome)/(main).tsx
  • apps/desktop/src/routes/(window-chrome)/setup.tsx
  • apps/desktop/src/routes/capture-area.tsx
  • apps/desktop/src/routes/editor/Timeline/MaskTrack.tsx
  • apps/desktop/src/routes/editor/ui.tsx
  • apps/desktop/src-tauri/src/platform/macos/mod.rs
  • apps/desktop/src/routes/editor/Editor.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx
  • apps/desktop/src/entry-server.tsx
  • apps/desktop/src/utils/tauri.ts
  • packages/ui/src/components/Cmdk.tsx
  • packages/ui/src/components/SkeletonRows.tsx
  • apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetCard.tsx
  • packages/ui/src/components/Dropdown.tsx
  • apps/desktop/src-tauri/src/target_select_overlay.rs
  • apps/desktop/src/routes/target-select-overlay.tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/RoundingPopover.tsx
  • apps/desktop/src/routes/(window-chrome).tsx
  • apps/desktop/src/routes/screenshot-editor/popovers/BackgroundSettingsPopover.tsx
  • packages/ui/src/components/Table.tsx
  • apps/desktop/src/routes/screenshot-editor/Editor.tsx
  • apps/desktop/src/routes/editor/ShareButton.tsx
  • apps/desktop/src/components/titlebar/Titlebar.tsx
  • apps/desktop/src-tauri/src/recording.rs
  • apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
  • apps/desktop/src-tauri/src/lib.rs
  • apps/desktop/src-tauri/src/windows.rs
  • apps/desktop/src/routes/screenshot-editor/ui.tsx
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Never use dbg!() macro; use proper logging (tracing::debug!, etc.) instead
Never write let _ = async_fn() which silently drops futures; await or explicitly handle them
Use duration.saturating_sub(other) instead of duration - other to avoid panics on underflow
Merge nested if statements: write 'if a && b { }' instead of 'if a { if b { } }'
Don't call .clone() on Copy types (integers, bools, etc.); copy them directly
Use function references directly: iter.map(foo) instead of iter.map(|x| foo(x))
Accept &[T] or &str instead of &Vec or &String in function parameters for flexibility
Use .is_empty() instead of .len() == 0 or .len() > 0 / .len() != 0
Don't assign () to a variable: write foo(); instead of let _ = foo(); or let x = foo(); when return is unit
Use .unwrap_or(val) instead of .unwrap_or_else(|| val) when the default is a simple/cheap value
Use 'for item in &collection' or 'for (i, item) in collection.iter().enumerate()' instead of 'for i in 0..collection.len()'
Use value.clamp(min, max) instead of manual if chains or .min(max).max(min) patterns
Always handle Result/Option or types marked #[must_use]; never ignore them

**/*.rs: Use rustfmt and workspace clippy lints for Rust code formatting and linting
Use snake_case for Rust module names and kebab-case for crate names
Never use dbg!() macro in Rust code; use proper logging instead (Clippy: dbg_macro = deny)
Always handle Result/Option or types marked #[must_use]; never ignore them (Rust compiler lint: unused_must_use = deny)
Never write let _ = async_fn() which silently drops futures; await or explicitly handle them (Clippy: let_underscore_future = deny)
Use saturating_sub instead of - for Duration to avoid panics (Clippy: unchecked_duration_subtraction = deny)
Merge nested if statements: use if a && b { } instead of if a { if b { } } (Clippy: collapsible_if = deny)
Don't call .clone() on Copy types; just copy them directly (Clippy: clone_on_copy = deny)
U...

Files:

  • apps/desktop/src-tauri/src/tray.rs
  • apps/desktop/src-tauri/src/deeplink_actions.rs
  • apps/desktop/src-tauri/src/hotkeys.rs
  • apps/desktop/src-tauri/src/permissions.rs
  • apps/desktop/src-tauri/src/platform/mod.rs
  • apps/desktop/src-tauri/src/screenshot_editor.rs
  • apps/desktop/src-tauri/src/platform/macos/mod.rs
  • apps/desktop/src-tauri/src/target_select_overlay.rs
  • apps/desktop/src-tauri/src/recording.rs
  • apps/desktop/src-tauri/src/lib.rs
  • apps/desktop/src-tauri/src/windows.rs
apps/web/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

apps/web/**/*.tsx: Prefer Server Components for initial data fetching and SEO; pass initialData to client components and let React Query take over
Minimize useEffect usage in React components; compute during render, handle logic in event handlers, and ensure cleanups for subscriptions/timers

Files:

  • apps/web/app/(org)/dashboard/caps/components/web-recorder-dialog/CameraPreviewWindow.tsx
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use useEffectQuery/useEffectMutation from @/lib/EffectRuntime in client components; do not call EffectRuntime.run* directly

Files:

  • apps/web/app/(org)/dashboard/caps/components/web-recorder-dialog/CameraPreviewWindow.tsx
**/*.config.{js,ts,mjs,cjs}

📄 CodeRabbit inference engine (CLAUDE.md)

Configuration files must follow their respective tool conventions (Next.js, Tailwind, etc.)

Files:

  • apps/desktop/postcss.config.cjs
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use TanStack Query v5 for all client-side server state and data fetching in TypeScript files

Files:

  • apps/desktop/src/utils/tauri.ts
apps/desktop/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

apps/desktop/**/*.ts: Use @tanstack/solid-query for server state management in SolidJS components
Use generated commands and events from tauri_specta for IPC; never manually construct IPC calls
Listen directly to generated events from tauri_specta and use typed event interfaces

Files:

  • apps/desktop/src/utils/tauri.ts
🧠 Learnings (14)
📚 Learning: 2025-11-19T18:25:41.457Z
Learnt from: ItsEeleeya
Repo: CapSoftware/Cap PR: 1396
File: apps/desktop/src/routes/(window-chrome)/settings/general.tsx:183-192
Timestamp: 2025-11-19T18:25:41.457Z
Learning: In SolidJS, when using the Show component with the `keyed` attribute and a dynamic reactive value (like a memo result), the component will recreate its children when the condition value changes by reference. This pattern is useful for triggering CSS animations (like fade-in) when the rendered content needs to update. For example, in apps/desktop/src/routes/(window-chrome)/settings/general.tsx, `<Show when={previews()[theme.id]} keyed>` ensures the image re-animates when switching between different preview sources.

Applied to files:

  • apps/desktop/src/routes/(window-chrome)/settings/hotkeys.tsx
  • apps/desktop/src/routes/(window-chrome)/update.tsx
  • apps/desktop/src/routes/editor/Timeline/index.tsx
  • apps/desktop/src/routes/capture-area.tsx
  • apps/desktop/src/routes/editor/Editor.tsx
  • apps/desktop/src/routes/screenshot-editor/Editor.tsx
📚 Learning: 2025-10-28T08:39:42.230Z
Learnt from: Brendonovich
Repo: CapSoftware/Cap PR: 1305
File: crates/recording/src/output_pipeline/macos.rs:80-90
Timestamp: 2025-10-28T08:39:42.230Z
Learning: In `crates/recording/src/output_pipeline/macos.rs`, the `AVFoundationMp4Muxer` intentionally holds the `Mutex<MP4Encoder>` lock during retry attempts in `send_video_frame()` and `send_audio_frame()`. This blocking behavior is correct because frame processing must happen sequentially to prevent audio and video frames from being interleaved incorrectly in the encoder.

Applied to files:

  • apps/desktop/src-tauri/src/tray.rs
📚 Learning: 2025-12-07T14:29:19.166Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.166Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Tailwind CSS for styling in web components; stay consistent with spacing and tokens

Applied to files:

  • packages/ui/src/components/input/Input.tsx
  • apps/desktop/src/routes/editor/Timeline/SceneTrack.tsx
  • apps/desktop/src/routes/debug.tsx
  • apps/desktop/src/routes/editor/CaptionsTab.tsx
  • apps/desktop/src/routes/editor/Timeline/TrackManager.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/changelog.tsx
  • packages/ui-solid/src/Button.tsx
  • packages/ui-solid/src/main.css
  • apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/screenshots.tsx
  • packages/ui/src/components/Select.tsx
  • apps/desktop/src/routes/editor/ConfigSidebar.tsx
  • apps/desktop/src/routes/editor/Timeline/TextTrack.tsx
  • apps/desktop/package.json
  • apps/desktop/src/styles/theme.css
  • apps/desktop/src/routes/editor/Header.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/license.tsx
  • apps/desktop/src/routes/(window-chrome)/update.tsx
  • apps/desktop/src/components/CapErrorBoundary.tsx
  • packages/ui-solid/package.json
  • apps/desktop/src/routes/(window-chrome)/upgrade.tsx
  • apps/desktop/src/routes/(window-chrome)/settings/integrations/s3-config.tsx
  • apps/desktop/postcss.config.cjs
  • apps/desktop/src/routes/(window-chrome)/new-main/index.tsx
  • apps/desktop/src/routes/editor/Timeline/index.tsx
  • packages/ui/src/components/Button.tsx
  • apps/desktop/src/routes/screenshot-editor/ColorPicker.tsx
  • apps/desktop/src/routes/editor/Timeline/Track.tsx
  • apps/desktop/src/routes/(window-chrome)/(main).tsx
  • apps/desktop/src/routes/(window-chrome)/setup.tsx
  • apps/desktop/src/routes/editor/Timeline/MaskTrack.tsx
  • apps/desktop/src/routes/editor/ui.tsx
  • apps/desktop/src/routes/editor/Editor.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetDropdownButton.tsx
  • apps/desktop/src/entry-server.tsx
  • packages/ui/src/components/Cmdk.tsx
  • packages/ui/src/components/SkeletonRows.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/TargetCard.tsx
  • apps/desktop/src/routes/(window-chrome).tsx
  • packages/ui/src/components/Table.tsx
  • apps/desktop/src/routes/screenshot-editor/Editor.tsx
  • apps/desktop/src/routes/editor/ShareButton.tsx
  • apps/desktop/src/components/titlebar/Titlebar.tsx
  • apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
  • apps/desktop/src/routes/screenshot-editor/ui.tsx
📚 Learning: 2025-12-07T14:29:40.721Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T14:29:40.721Z
Learning: Applies to **/tauri.ts|**/queries.ts|apps/desktop/src-tauri/gen/** : Never edit auto-generated files: `**/tauri.ts`, `**/queries.ts`, `apps/desktop/src-tauri/gen/**`

Applied to files:

  • apps/desktop/src/routes/editor/Timeline/SceneTrack.tsx
  • apps/desktop/src/routes/(window-chrome)/new-main/index.tsx
  • apps/desktop/src/routes/(window-chrome)/setup.tsx
📚 Learning: 2025-12-07T14:29:19.166Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.166Z
Learning: Applies to packages/web-api-contract-effect/**/*.ts : HTTP contract definitions in web-api-contract-effect must be kept in sync with API route changes

Applied to files:

  • apps/desktop/package.json
📚 Learning: 2025-12-07T14:29:40.721Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T14:29:40.721Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use kebab-case for file names (e.g., `user-menu.tsx`); use PascalCase for components

Applied to files:

  • packages/ui/src/components/NavigationMenu.tsx
  • apps/desktop/src/routes/(window-chrome)/(main).tsx
📚 Learning: 2025-12-07T14:29:19.165Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.165Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use strict TypeScript; avoid any type; leverage shared types from cap/* packages

Applied to files:

  • apps/desktop/src/components/CapErrorBoundary.tsx
  • packages/ui-solid/package.json
📚 Learning: 2025-12-07T14:29:19.165Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.165Z
Learning: Applies to apps/web/app/api/**/*.ts : Map domain-level errors to transport errors with HttpApiError.* and keep error translation exhaustive using Effect.catchTags and Effect.tapErrorCause(Effect.logError)

Applied to files:

  • apps/desktop/src/components/CapErrorBoundary.tsx
📚 Learning: 2025-12-07T14:29:19.165Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.165Z
Learning: Applies to **/*.config.{js,ts,mjs,cjs} : Configuration files must follow their respective tool conventions (Next.js, Tailwind, etc.)

Applied to files:

  • apps/desktop/postcss.config.cjs
📚 Learning: 2025-12-07T14:29:19.166Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.166Z
Learning: Applies to apps/desktop/**/*.ts : Use generated commands and events from tauri_specta for IPC; never manually construct IPC calls

Applied to files:

  • apps/desktop/src/utils/tauri.ts
📚 Learning: 2025-12-07T14:29:19.166Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.166Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use static skeletons for loading states that mirror content; avoid bouncing animations

Applied to files:

  • packages/ui/src/components/SkeletonRows.tsx
📚 Learning: 2025-09-23T12:34:13.729Z
Learnt from: Brendonovich
Repo: CapSoftware/Cap PR: 1053
File: .github/workflows/publish.yml:222-230
Timestamp: 2025-09-23T12:34:13.729Z
Learning: In the Cap desktop app, there's a beforeBundle Tauri script (prodBeforeBundle.js) that creates Cap.dSYM in the target/ directory using dsymutil, so the Sentry debug symbols upload path "target/Cap.dSYM" is correct and doesn't need to be changed to the matrix target subdirectory.

Applied to files:

  • apps/desktop/src-tauri/tauri.conf.json
📚 Learning: 2025-12-07T14:29:19.166Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T14:29:19.166Z
Learning: Never edit auto-generated files: tauri.ts, queries.ts, and files under apps/desktop/src-tauri/gen/

Applied to files:

  • apps/desktop/src-tauri/tauri.conf.json
📚 Learning: 2025-12-07T14:29:40.721Z
Learnt from: CR
Repo: CapSoftware/Cap PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T14:29:40.721Z
Learning: Use Turborepo monorepo structure with `apps/desktop`, `apps/web`, `apps/cli`, `packages/*`, `crates/*`, and tooling directories

Applied to files:

  • Cargo.toml
🧬 Code graph analysis (10)
apps/desktop/src-tauri/src/tray.rs (1)
apps/desktop/src/utils/tauri.ts (2)
  • RecordingTargetMode (461-461)
  • CapWindow (365-365)
apps/desktop/src-tauri/src/deeplink_actions.rs (1)
apps/desktop/src-tauri/src/lib.rs (8)
  • show_window (2153-2156)
  • app (576-576)
  • app (1649-1650)
  • app (2721-2721)
  • app (2757-2757)
  • app (2834-2834)
  • app (2840-2840)
  • app (3073-3074)
apps/desktop/src/routes/in-progress-recording.tsx (1)
apps/desktop/src/utils/tauri.ts (1)
  • stopRecording (20-22)
apps/desktop/src-tauri/src/screenshot_editor.rs (1)
apps/desktop/src-tauri/src/windows.rs (1)
  • from_str (61-100)
apps/desktop/src/routes/(window-chrome)/(main).tsx (1)
apps/desktop/src/routes/(window-chrome)/new-main/InfoPill.tsx (1)
  • InfoPill (4-17)
apps/desktop/src/routes/editor/ui.tsx (1)
apps/desktop/src/routes/screenshot-editor/ui.tsx (4)
  • topLeftAnimateClasses (420-421)
  • topCenterAnimateClasses (423-424)
  • topRightAnimateClasses (426-427)
  • topSlideAnimateClasses (429-430)
apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx (1)
apps/desktop/src/routes/editor/Timeline/Track.tsx (3)
  • SegmentRoot (55-96)
  • SegmentHandle (112-134)
  • SegmentContent (98-110)
apps/desktop/src-tauri/src/target_select_overlay.rs (1)
apps/desktop/src-tauri/src/windows.rs (9)
  • from_str (61-100)
  • app (265-265)
  • app (284-284)
  • app (431-431)
  • app (525-525)
  • app (829-829)
  • app (847-847)
  • app (987-987)
  • app (999-999)
apps/desktop/src-tauri/src/recording.rs (1)
apps/desktop/src-tauri/src/windows.rs (9)
  • app (265-265)
  • app (284-284)
  • app (431-431)
  • app (525-525)
  • app (829-829)
  • app (847-847)
  • app (987-987)
  • app (999-999)
  • label (129-131)
apps/desktop/src-tauri/src/lib.rs (2)
apps/desktop/src/utils/tauri.ts (2)
  • CapWindow (365-365)
  • Camera (357-357)
apps/desktop/src-tauri/src/windows.rs (13)
  • from_str (61-100)
  • app (265-265)
  • app (284-284)
  • app (431-431)
  • app (525-525)
  • app (829-829)
  • app (847-847)
  • app (987-987)
  • app (999-999)
  • label (129-131)
  • get (170-173)
  • get (986-988)
  • get (998-1000)

"@fontsource/geist-sans": "^5.0.3",
"@iconify/json": "^2.2.239",
"@tauri-apps/cli": ">=2.1.0",
"@tauri-apps/cli": "^2.9.5",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

@tauri-apps/cli 2.9.5 release notes changelog

💡 Result:

Here are the release notes / changelog entries for @tauri-apps/cli v2.9.5:

  • Bug fixes:

    • Fixed mismatched tauri package versions check for pnpm. (commit f855caf8a, #14481). [1]
    • Fixed CLI error when signing keys were set in config but --no-sign was used together with tauri-plugin-updater (commit f022b2d1a, #14582). [1]
    • Fixed parsing error when there was no Cargo.lock (reported as noisy unless --verbose) (commit 79a7d9ec0, #14468). [1]
  • Performance improvements:

    • Refactor to remove needless collect (ce98d87ce, #14474). [1]
    • Removed needless clones in various files for improved perf (ee3cca... #14475). [1]
  • Dependencies:

    • Upgraded to tauri-bundler@2.7.4, tauri-macos-sign@2.3.1, tauri-utils@2.8.1 and to tauri-cli (Rust) v2.9.5 (as referenced in the tauri repo release). [1][2]

Sources: [1] Tauri release page for @tauri-apps/cli v2.9.5, [2] tauri-apps/tauri GitHub release (tauri-cli v2.9.5).


🌐 Web query:

@tauri-apps/cli 2.9.5 @tauri-apps/api 2.5.0 compatibility

💡 Result:

Short answer: not recommended — upgrade @tauri-apps/api to a 2.9.x release to match @tauri-apps/cli 2.9.5.

Why: the Tauri ecosystem expects matching/close releases across packages (tauri, @tauri-apps/api, tauri-cli/@tauri-apps/cli). @tauri-apps/cli 2.9.5 is part of the 2.9.x ecosystem; @tauri-apps/api 2.5.0 is an older 2.5.x release and may miss APIs/behavior introduced since 2.5.0. For best compatibility, use @tauri-apps/api 2.9.x with @tauri-apps/cli 2.9.5. [1][2]

Sources:

  • Tauri core releases / recommended matching versions. [1]
  • @tauri-apps/api v2.5.0 release notes (shows it’s a 2.5.x release). [2]

References:
[1] Tauri Core Ecosystem Releases (shows tauri/@tauri-apps/api and cli 2.9.x alignment).
[2] @tauri-apps/api v2.5.0 release page.


Upgrade @tauri-apps/api to 2.9.x for compatibility with @tauri-apps/cli 2.9.5.

The version constraint for @tauri-apps/cli was updated to ^2.9.5, but @tauri-apps/api is pinned at 2.5.0. The Tauri ecosystem requires matching or close release versions across packages; using cli 2.9.5 with api 2.5.0 creates a significant version mismatch (4 minor versions apart). This can result in missing APIs or behavioral inconsistencies. Upgrade @tauri-apps/api to a 2.9.x release to ensure ecosystem alignment.

🤖 Prompt for AI Agents
In apps/desktop/package.json around line 76, @tauri-apps/cli was bumped to
^2.9.5 but @tauri-apps/api remains pinned at 2.5.0, causing a large version
mismatch; update the @tauri-apps/api dependency to a 2.9.x release (e.g., ^2.9.0
or ^2.9.5) in package.json, run your package manager install to update lockfile,
and rebuild/test the app to ensure there are no API breakages.

Comment on lines +1 to +8
// module.exports = require("@cap/ui/postcss");

module.exports = {
plugins: {
"@tailwindcss/postcss": {},
autoprefixer: {},
},
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd -type f -name "postcss.config.*"

Repository: CapSoftware/Cap

Length of output: 174


🏁 Script executed:

find . -type f -name "*postcss*" | grep -E "\.(ts|js|cjs|mjs)$" | head -20

Repository: CapSoftware/Cap

Length of output: 174


🏁 Script executed:

find . -path "*/cap/ui/*" -type f | grep -iE "(postcss|index)" | head -20

Repository: CapSoftware/Cap

Length of output: 174


🏁 Script executed:

rg -t js -t ts "@cap/ui/postcss" --max-count 20

Repository: CapSoftware/Cap

Length of output: 174


🌐 Web query:

Tailwind CSS 4 @tailwindcss/postcss autoprefixer redundant Lightning CSS

💡 Result:

Short answer: Yes — in Tailwind CSS v4 the new @tailwindcss/postcss plugin + Lightning CSS make separate autoprefixer (and postcss-import / postcss-preset-env) generally redundant.

What changed

  • Tailwind v4 moves the PostCSS integration into a new package: @tailwindcss/postcss (replace the old tailwindcss PostCSS plugin). [1][2]
  • Tailwind runs your CSS through Lightning CSS in production, which performs vendor-prefixing, transpilation of modern features, minification, etc. That replaces the need for autoprefixer and similar PostCSS plugins in most setups. [1][3]

What to do

  • Replace your PostCSS config from:
    plugins: { tailwindcss: {}, autoprefixer: {}, postcss-import: {} }
    to:
    plugins: { "@tailwindcss/postcss": {} }
  • If you need special behavior not covered by Lightning CSS (rare), keep the specific PostCSS plugin(s) you require.

Sources: Tailwind v4 docs and migration guidance. [1] [2] [3]


Remove JS comment and redundant autoprefixer from PostCSS config

Two things to fix here:

  1. JS comment violates repo guidelines

    The // module.exports = require("@cap/ui/postcss"); line must be removed. The codebase forbids comments in .cjs files; git history already preserves the old config.

  2. autoprefixer is redundant with @tailwindcss/postcss

    Tailwind 4's @tailwindcss/postcss plugin integrates Lightning CSS, which handles vendor-prefixing, transpilation, and minification. A separate autoprefixer entry is unnecessary and can be dropped.

Corrected config:

-// module.exports = require("@cap/ui/postcss");
-
 module.exports = {
 	plugins: {
 		"@tailwindcss/postcss": {},
-		autoprefixer: {},
 	},
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// module.exports = require("@cap/ui/postcss");
module.exports = {
plugins: {
"@tailwindcss/postcss": {},
autoprefixer: {},
},
};
module.exports = {
plugins: {
"@tailwindcss/postcss": {},
},
};
🤖 Prompt for AI Agents
In apps/desktop/postcss.config.cjs around lines 1 to 8, remove the leading JS
comment line and drop the redundant autoprefixer plugin: delete the comment //
module.exports = require("@cap/ui/postcss"); and remove the autoprefixer entry
from the plugins object so only "@tailwindcss/postcss": {} remains; keep the
file as a plain module.exports object with no comments.

Comment on lines 2947 to 2951
fn has_open_editor_window(app: &AppHandle) -> bool {
app.webview_windows()
.keys()
.any(|label| matches!(CapWindowId::from_str(label), Ok(CapWindowId::Editor { .. })))
.any(|label| matches!(CapWindow::from_str(label), Ok(CapWindow::Editor { .. })))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

has_open_editor_window should use CapWindowDef::from_str, not CapWindow::from_str

Current code:

#[cfg(target_os = "windows")]
fn has_open_editor_window(app: &AppHandle) -> bool {
    app.webview_windows()
        .keys()
-        .any(|label| matches!(CapWindow::from_str(label), Ok(CapWindow::Editor { .. })))
+        // ...
}

CapWindow does not implement FromStr in windows.rs, so this will fail to compile on Windows targets. Conceptually, this helper wants to know if any open window label corresponds to an editor window, which is exactly what CapWindowDef::from_str provides.

Suggested fix:

#[cfg(target_os = "windows")]
fn has_open_editor_window(app: &AppHandle) -> bool {
    app.webview_windows()
        .keys()
-        .any(|label| matches!(CapWindow::from_str(label), Ok(CapWindow::Editor { .. })))
+        .any(|label| matches!(CapWindowDef::from_str(label), Ok(CapWindowDef::Editor { .. })))
}

This aligns with the rest of the CapWindowDef‑based label parsing.

🤖 Prompt for AI Agents
In apps/desktop/src-tauri/src/lib.rs around lines 2947 to 2951, the helper uses
CapWindow::from_str which doesn't exist on Windows; change the parsing to use
CapWindowDef::from_str and update the pattern to match the CapWindowDef::Editor
variant (e.g. replace the matches!(CapWindow::from_str(label),
Ok(CapWindow::Editor { .. })) call with matches!(CapWindowDef::from_str(label),
Ok(CapWindowDef::Editor { .. }))) so label parsing uses CapWindowDef as in the
rest of the code.

disabled={openCommercialCheckout.isPending}
variant="dark"
class="w-full !rounded-full !h-[48px] text-lg font-medium"
class="w-full rounded-full! h-[48px]! text-lg font-medium"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix inconsistent Tailwind v4 syntax in arbitrary value.

The important modifiers have been correctly moved to suffix position, but the arbitrary height value still uses brackets. According to Tailwind v4 migration requirements, all arbitrary values must use parentheses syntax.

Apply this diff:

-						class="w-full rounded-full! h-[48px]! text-lg font-medium"
+						class="w-full rounded-full! h-(48px)! text-lg font-medium"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class="w-full rounded-full! h-[48px]! text-lg font-medium"
class="w-full rounded-full! h-(48px)! text-lg font-medium"
🤖 Prompt for AI Agents
In apps/desktop/src/routes/(window-chrome)/upgrade.tsx around line 424, the
Tailwind arbitrary height uses bracket syntax h-[48px]! which is incompatible
with Tailwind v4; replace it with the parentheses form h-(48px)! so the class
becomes e.g. "w-full rounded-full! h-(48px)! text-lg font-medium" ensuring the
important modifier remains as the suffix and spacing stays consistent.

const el = (props?: object) => (
<KTabs.Trigger
class="z-10 flex-1 py-2.5 px-2 text-xs text-gray-11 ui-selected:border-gray-3 ui-selected:bg-gray-3 ui-not-selected:hover:border-gray-7 rounded-[10px] transition-colors duration-200 outline-none border ui-selected:text-gray-12 peer"
class="z-10 flex-1 py-2.5 px-2 text-xs text-gray-11 data-selected:border-gray-3 data-selected:bg-gray-3 ui-not-selected:hover:border-gray-7 rounded-[10px] transition-colors duration-200 outline-none border data-selected:text-gray-12 peer"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Tailwind CSS v4 incompatibility: ui-not-selected pseudo-class no longer supported.

Line 1387 still contains ui-not-selected:hover:border-gray-7, which is invalid in Tailwind v4. The ui-* pseudo-classes have been replaced with data-* attribute selectors.

This needs to be either removed or replaced with a valid v4 variant. If you need to style the non-selected state, consider using a negation variant or alternative approach that works with data-* attributes from Kobalte.

🤖 Prompt for AI Agents
In apps/desktop/src/routes/editor/ConfigSidebar.tsx around line 1387, the class
string uses the removed Tailwind v4 pseudo-class
`ui-not-selected:hover:border-gray-7`; remove that token and replace it with a
valid data-attribute based variant such as
`[data-selected="false"]:hover:border-gray-7` or, if relying on the peer
element, `peer-[data-selected="false"]:hover:border-gray-7` so the non-selected
hover style works with Kobalte's data-selected attribute; update the class
string accordingly and ensure quotes/escaping match existing string formatting.

}
value={key}
class="flex relative z-10 flex-1 justify-center items-center px-4 py-2 bg-transparent rounded-lg border transition-colors duration-200 text-gray-11 ui-not-selected:hover:border-gray-7 ui-selected:bg-gray-3 ui-selected:border-gray-3 group ui-selected:text-gray-12 disabled:opacity-50 focus:outline-none"
class="flex relative z-10 flex-1 justify-center items-center px-4 py-2 bg-transparent rounded-lg border transition-colors duration-200 text-gray-11 ui-not-selected:hover:border-gray-7 data-selected:bg-gray-3 data-selected:border-gray-3 group data-selected:text-gray-12 disabled:opacity-50 focus:outline-none"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Tailwind CSS v4 incompatibility: ui-not-selected pseudo-class on line 1531.

The background theme tab trigger contains ui-not-selected:hover:border-gray-7, which is not valid in Tailwind v4. This is the same issue as line 1387 and needs to be migrated to a v4-compatible approach using data-* attributes.

🤖 Prompt for AI Agents
In apps/desktop/src/routes/editor/ConfigSidebar.tsx around line 1531, replace
the Tailwind v3 pseudo-class `ui-not-selected:hover:border-gray-7` with a
v4-compatible data-attribute variant such as
`data-[selected=false]:hover:border-gray-7` and ensure the element sets the
`data-selected` attribute to "true" or "false" appropriately (mirror the same
change applied at line 1387); this removes the invalid `ui-not-selected` token
and uses a data-* hover selector compatible with Tailwind v4.

Comment on lines +1587 to 1588
<KRadioGroup.ItemControl class="overflow-hidden w-full h-full rounded-lg transition cursor-pointer ui-not-checked:ring-offset-1 ui-not-checked:ring-offset-gray-200 ui-not-checked:hover:ring-1 ui-not-checked:hover:ring-gray-400 data-checked:ring-2 data-checked:ring-gray-500 data-checked:ring-offset-2 data-checked:ring-offset-gray-200">
<img
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Tailwind CSS v4 incompatibility: Multiple ui-not-checked pseudo-classes.

Lines 1587–1588 contain several invalid v4 variants: ui-not-checked:ring-offset-1, ui-not-checked:ring-offset-gray-200, ui-not-checked:hover:ring-1, and ui-not-checked:hover:ring-gray-400. These need to be migrated to use data-* attributes or removed entirely. The data-checked:* variants on the same lines are correctly formatted for v4, but the negation states remain unconverted.

</TooltipIconButton>
<TooltipIconButton
class="absolute right-3 bottom-3 z-[998]"
class="absolute right-3 bottom-3 z-998"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Show the actual code at the specified lines
echo "=== Code at line 366 in recordings-overlay.tsx ==="
sed -n '360,372p' apps/desktop/src/routes/recordings-overlay.tsx

echo -e "\n=== Code at line 451 in recordings-overlay.tsx ==="
sed -n '445,457p' apps/desktop/src/routes/recordings-overlay.tsx

echo -e "\n=== Search for all z-index patterns in the file ==="
rg -n "z-\d+" apps/desktop/src/routes/recordings-overlay.tsx
</parameter>

Repository: CapSoftware/Cap

Length of output: 174


🏁 Script executed:

#!/bin/bash

# Search for other z-index usage patterns in the codebase
echo "=== All z-index utilities in desktop/src ==="
rg -n "z-\[?\d+\]?" apps/desktop/src --type ts --type tsx | head -30
</parameter>

Repository: CapSoftware/Cap

Length of output: 174


🌐 Web query:

Tailwind CSS v4 z-index arbitrary values syntax brackets support

💡 Result:

Yes — Tailwind CSS v4 supports arbitrary z-index values.

  • Syntax: z-[] (e.g. class="z-[100]" or class="z-[calc(var(--i)+1)]"). [1]
  • CSS-variable shorthand: z-(--my-z) → expands to z-[var(--my-z)]. [1]
  • Negative values: you can prefix with a dash for negative utilities (e.g. -z-10); the same negative-prefix pattern also applies to arbitrary values (e.g. -z-[100]). [1][2]

Sources: Tailwind v4 docs (z-index) and v4 feature notes. [1] [2]

References
[1] Tailwind CSS — z-index (v4) documentation.
[2] Tailwind CSS v4 release / features.


Restore brackets for arbitrary z-index values in Tailwind v4.

The syntax z-998 and z-999999 (without brackets) are invalid in Tailwind v4. Arbitrary z-index values must use bracket notation: z-[998] and z-[999999]. Only predefined utilities in Tailwind's z-index scale (e.g., z-10, z-50) work without brackets; arbitrary values always require brackets according to Tailwind v4 documentation.

🤖 Prompt for AI Agents
In apps/desktop/src/routes/recordings-overlay.tsx around line 366, the class
uses invalid Tailwind v4 syntax `z-998` (and elsewhere `z-999999`) which must
use bracket notation for arbitrary values; replace those with `z-[998]` and
`z-[999999]` respectively so Tailwind v4 recognizes the arbitrary z-indexes, and
verify no other non-scale z- classes exist without brackets.

@ItsEeleeya ItsEeleeya marked this pull request as draft December 8, 2025 08:26
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.

2 participants