Skip to content

Comments

Portal Components System#28

Merged
iamEvanYT merged 20 commits intomainfrom
evan/portal-components
Apr 28, 2025
Merged

Portal Components System#28
iamEvanYT merged 20 commits intomainfrom
evan/portal-components

Conversation

@iamEvanYT
Copy link
Member

@iamEvanYT iamEvanYT commented Apr 28, 2025

Summary by CodeRabbit

  • New Features

    • Added a Portal component to render content in separate popup windows with precise positioning and style synchronization.
    • Introduced portal-based popover components for improved UI layering and animations.
    • Added sidebar side selection setting (left or right).
    • Enabled clipboard text copying via IPC with fallback support.
  • Improvements

    • Refactored sidebar with smooth animations, modular components, and hover-triggered floating behavior.
    • Enhanced popover and navigation history UI using portal-based, theme-aware popovers.
    • Improved sidebar window controls and hover detection for better interaction.
    • Added dynamic CSS size conversions and bounding rectangle tracking for consistent layout.
    • Synchronized styles between main and portal windows to maintain visual consistency.
    • Updated sidebar visibility behavior and layout adjustments based on hover and variant state.
    • Enhanced clipboard copy feedback with toast notifications.
    • Adjusted omnibox background opacity based on context.
  • Bug Fixes

    • Ensured omnibox stays fully visible by clamping its bounds within the parent window.
  • Documentation

    • Added detailed documentation for the Portal component, its API, architecture, and usage guidelines.
    • Updated view indexes documentation with new entries.
  • Chores

    • Removed legacy glance modal components and related code.
    • Updated internal APIs and IPC handlers to support portal window management.
    • Improved cleanup and lifecycle management for views and portal windows.
    • Added minimal toast provider for lightweight notification support.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 28, 2025

Walkthrough

This set of changes introduces a new portal-based component system for rendering floating UI elements, such as popovers and sidebars, into separate browser windows using Electron. It adds comprehensive documentation and implementation for the PortalComponent and related popover components, refactors the sidebar to support floating and animated variants, and introduces new hooks for measuring DOM elements and synchronizing styles across windows. The Electron backend is updated to manage portal component windows, including IPC handlers for controlling their bounds, z-index, and visibility. The legacy "glance modal" feature is removed, and the sidebar receives new settings and right-side support. Clipboard writing is now supported via IPC, and several utilities are added or enhanced for CSS size conversion and clipboard fallback.

Changes

File(s) / Path(s) Change Summary
docs/components/portal.md Added comprehensive documentation for the Portal component, its architecture, API, implementation details, related components, usage, and backend integration.
docs/references/view-indexes.md Added two new view index entries: "4 - Browser Overlay Components" and "3 - Standard Browser Components."
electron/browser/components/glance-modal.ts
vite/src/routes/glance-modal/page.tsx
vite/src/routes/glance-modal/route.tsx
Removed the GlanceModal class and its corresponding route/component files.
electron/browser/components/omnibox.ts Enhanced setOmniboxBounds to clamp bounds within parent window dimensions.
electron/browser/components/portal-component-windows.ts New module to manage portal component windows, handle window creation, IPC for bounds/z-index/visibility, and cleanup.
electron/browser/tabs/tab.ts Removed explicit glance modal bounds and visibility handling from tab layout logic.
electron/browser/utility/hot-reload.ts Increased minimum random timeout from 100ms to 300ms in throttling logic.
electron/browser/view-manager.ts Refactored to use WebContentsView for views, added automatic cleanup on destruction, and updated method signatures for view management.
electron/browser/window.ts Removed GlanceModal integration, added portal component windows initialization, and hid window buttons on creation.
electron/ipc/app/app.ts Added IPC handler for writing text to the clipboard via Electron's clipboard API.
electron/modules/basic-settings.ts Added sidebar side setting ("left"/"right"), updated sidebar settings card, and made collapse mode name visible.
electron/modules/output.ts Added PORTAL_COMPONENTS debug area to debug areas constant.
electron/preload.ts Added IPC methods to interfaceAPI for setting component window bounds, z-index, and visibility, and to appAPI for clipboard writing.
vite/src/App.tsx Removed import and route for GlanceModal.
vite/src/components/browser-ui/browser-action.tsx Switched popover rendering from UI popover to new PortalPopover components.
vite/src/components/browser-ui/browser-content.tsx Replaced manual bounding box logic with useBoundingRect hook for page bounds tracking.
vite/src/components/browser-ui/browser-sidebar.tsx Refactored sidebar for modularity, animation, hover state, floating variant, portal-based rendering, and extracted header/footer/content components.
vite/src/components/browser-ui/main.tsx Added floating sidebar variant, hover detection, right-side support, and dynamic sidebar behavior based on settings.
vite/src/components/browser-ui/sidebar/content/space-sidebar.tsx Disabled initial animation in AnimatePresence for sidebar tab groups.
vite/src/components/browser-ui/sidebar/header/action-buttons.tsx Added horizontal padding to SidebarGroup in navigation controls.
vite/src/components/browser-ui/sidebar/header/navigation-buttons.tsx Replaced dropdown menu with portal-based popover for navigation history.
vite/src/components/browser-ui/sidebar/header/window-controls.tsx Added SidebarWindowControls component to manage window button positioning and visibility.
vite/src/components/browser-ui/sidebar/hover-detector.tsx Added SidebarHoverDetector component to detect sidebar hover events.
vite/src/components/browser-ui/sidebar/spaces-switcher.tsx Updated icon color classes for space buttons in light/dark mode.
vite/src/components/portal/popover.tsx New portal-based popover component system with context, animation, and positioning.
vite/src/components/portal/portal.tsx New PortalComponent for rendering children into separate popup windows with position, size, z-index, and anchor controls.
vite/src/components/providers/spaces-provider.tsx Injected dynamic CSS variables for space backgrounds into <head> using React portal.
vite/src/components/settings/sections/general/basic-settings-cards.tsx Added flex column layout and gap to basic settings card content.
vite/src/components/ui/popover.tsx Added optional portal prop to PopoverContent for conditional portal rendering.
vite/src/components/ui/resizable-sidebar.tsx Made sidebar visible by default, added isRightSide prop to SidebarRail.
vite/src/hooks/use-bounding-rect.tsx New hook to track DOM element bounding rectangles with throttling and portal context adjustment.
vite/src/hooks/use-copy-styles.ts New hook to synchronize styles from main document to popup window, with mutation observation.
vite/src/hooks/use-css-size-to-pixels.tsx New hook to convert CSS size strings to pixel values, supporting relative/absolute units and dynamic updates.
vite/src/hooks/use-sidebar-resize.tsx Added isRightSide option to support resizing sidebar from the right.
vite/src/index.css Changed single to double quotes in Tailwind plugin directive.
vite/src/lib/css.ts New utility function cssSizeToPixels for converting CSS size strings to pixels.
vite/src/lib/flow/interfaces/app/app.ts Added writeTextToClipboard method to FlowAppAPI interface.
vite/src/lib/flow/interfaces/browser/interface.ts Added methods for component window bounds/z-index/visibility to FlowInterfaceAPI.
vite/src/lib/utils.ts Added clipboard fallback using IPC, updated copyTextToClipboard to use fallback and consolidated toast logic.
vite/src/main.tsx Added toggle for React strict mode via a constant.

Sequence Diagram(s)

sequenceDiagram
    participant ReactApp
    participant PortalComponent
    participant ElectronPreload
    participant ElectronMain
    participant TabbedBrowserWindow
    participant WebContentsView

    ReactApp->>PortalComponent: Mount with props (x, y, width, height, zIndex, visible)
    PortalComponent->>ElectronPreload: setComponentWindowBounds(componentId, bounds)
    PortalComponent->>ElectronPreload: setComponentWindowZIndex(componentId, zIndex)
    PortalComponent->>ElectronPreload: setComponentWindowVisible(componentId, visible)
    ElectronPreload->>ElectronMain: IPC: setComponentWindowBounds
    ElectronMain->>TabbedBrowserWindow: Find/Create WebContentsView for componentId
    TabbedBrowserWindow->>WebContentsView: Set bounds/z-index/visibility
    ReactApp->>PortalComponent: Unmount
    PortalComponent->>ElectronPreload: setComponentWindowVisible(componentId, false)
    ElectronPreload->>ElectronMain: IPC: setComponentWindowVisible
    ElectronMain->>TabbedBrowserWindow: Hide WebContentsView
Loading
sequenceDiagram
    participant BrowserSidebar
    participant PortalComponent
    participant MainWindow
    participant ElectronPreload
    participant ElectronMain

    BrowserSidebar->>PortalComponent: Render floating sidebar (variant: floating)
    PortalComponent->>ElectronPreload: setComponentWindowBounds (sidebar window)
    ElectronPreload->>ElectronMain: IPC: setComponentWindowBounds
    ElectronMain->>MainWindow: Add/Update sidebar as overlay window
    BrowserSidebar->>PortalComponent: Unmount on close/exit
    PortalComponent->>ElectronPreload: setComponentWindowVisible (sidebar window, false)
Loading

Suggested labels

enhancement

Poem

🐇
A portal appears, a window anew,
Floating popovers and sidebars too!
With hooks and styles that leap and bound,
Across the DOM, new views are found.
The sidebar now floats, on left or right,
While clipboard magic works out of sight.
Hip-hip-hooray, the rabbit exclaims—
For portals and popovers have entered the game!
✨🪟


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd3990e and 270b1ad.

📒 Files selected for processing (2)
  • electron/browser/components/portal-component-windows.ts (1 hunks)
  • vite/src/components/omnibox/main.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • vite/src/components/omnibox/main.tsx
  • electron/browser/components/portal-component-windows.ts
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🧹 Nitpick comments (22)
vite/src/main.tsx (1)

6-8: Consider adding a comment explaining StrictMode toggle

The StrictMode toggle is a useful feature for development and debugging, especially when working with portal components that may have complex rendering behaviors.

+// Toggle StrictMode for development - can help debug issues with portal components
 const STRICT_MODE_ENABLED = true;
vite/src/components/providers/spaces-provider.tsx (1)

124-137: Good use of portals for style injection.

Moving the style element to document.head using React's createPortal is a better approach than rendering it inline with the component tree. This separates style concerns from the component hierarchy.

For optimization, consider memoizing the stylesheet to prevent recreation on every render:

-  // Stylesheet Portal
-  const stylesheet = (
-    <style>
-      {currentSpace
-        ? `
-  :root {
-    --space-background-start: ${bgStart};
-    --space-background-end: ${bgEnd};
-  }
-`
-        : ""}
-    </style>
-  );
+  // Stylesheet Portal
+  const stylesheet = React.useMemo(() => (
+    <style>
+      {currentSpace
+        ? `
+  :root {
+    --space-background-start: ${bgStart};
+    --space-background-end: ${bgEnd};
+  }
+`
+        : ""}
+    </style>
+  ), [currentSpace, bgStart, bgEnd]);
electron/browser/components/omnibox.ts (1)

210-224: Good bounds validation to keep omnibox within window.

The implementation now properly ensures the omnibox stays within the parent window's bounds by clamping the coordinates. This prevents UI elements from being positioned off-screen.

Consider adding debug logging when bounds are adjusted to help with troubleshooting:

  if (bounds) {
    const windowBounds = parentWindow.getBounds();

    const newBounds: Electron.Rectangle = {
      x: Math.min(bounds.x, windowBounds.width - bounds.width),
      y: Math.min(bounds.y, windowBounds.height - bounds.height),
      width: bounds.width,
      height: bounds.height
    };

+   // Log if bounds were adjusted
+   if (newBounds.x !== bounds.x || newBounds.y !== bounds.y) {
+     debugPrint("OMNIBOX", `Adjusted bounds from (${bounds.x}, ${bounds.y}) to (${newBounds.x}, ${newBounds.y}) to keep within window`);
+   }

    omnibox.setBounds(newBounds);
  } else {
    omnibox.setBounds(null);
  }
vite/src/lib/utils.ts (1)

15-34: Improved clipboard implementation with fallback mechanism.

Good implementation of a fallback mechanism for clipboard operations. The code now tries the web API first and falls back to IPC if needed, with proper success tracking.

Consider adding type guard checks before calling the fallback:

if (!writeSuccess) {
+  if (typeof flow?.app?.writeTextToClipboard === 'function') {
    writeSuccess = await copyTextToClipboardFallback(text);
+  }
}
vite/src/components/browser-ui/sidebar/hover-detector.tsx (1)

26-35: Consider accessibility improvements for the hover detector.

The component creates an invisible interactive area that might cause issues for screen readers or keyboard navigation.

<div
  ref={ref}
  className={cn(
    "remove-app-drag absolute top-0 w-2 h-full overflow-hidden z-50",
    side === "left" ? "left-0" : "right-0"
  )}
+  aria-hidden="true"
+  role="none"
/>

Also consider whether the z-index of 50 might conflict with other high z-index elements in the application.

vite/src/hooks/use-sidebar-resize.tsx (1)

94-95: Well-implemented direction-aware calculation.

The direction inversion for right-side resizing is correctly implemented. The comment helps explain the purpose of the change.

Consider renaming the variable to something like directionAwareDelta to make it even clearer that this value accounts for the sidebar's position:

-// Calculate new width in pixels with right side inversion if needed
-const deltaWidth = isRightSide ? startX.current - e.clientX : e.clientX - startX.current;
+// Calculate direction-aware delta based on sidebar position
+const directionAwareDelta = isRightSide ? startX.current - e.clientX : e.clientX - startX.current;
electron/browser/window.ts (1)

184-184: Portal component windows initialization.

This replaces the previous glance modal system with the new portal-based component system for floating UI elements.

Consider adding a brief comment explaining what the initialization does, to make the code more self-documenting:

-initializePortalComponentWindows(this);
+// Initialize the portal component system for floating UI elements (popovers, sidebars, etc.)
+initializePortalComponentWindows(this);
vite/src/lib/flow/interfaces/browser/interface.ts (3)

24-27: Well-structured component window bounds API.

The setComponentWindowBounds method provides a clean API for positioning portal component windows.

Consider enhancing the documentation with more details:

/**
 * Sets the bounds of a component window
+ * @param componentId Unique identifier for the component window
+ * @param bounds Position and size of the component window
 */

29-32: Clear z-index control API.

The setComponentWindowZIndex method allows proper stacking of multiple portal component windows.

Consider enhancing the documentation with more details:

/**
 * Sets the z-index of a component window
+ * @param componentId Unique identifier for the component window
+ * @param zIndex Stacking order for the component window (higher values appear on top)
 */

34-37: Good visibility control API.

The setComponentWindowVisible method allows showing and hiding portal component windows without recreating them.

Consider enhancing the documentation with more details:

/**
 * Sets the visibility of a component window
+ * @param componentId Unique identifier for the component window
+ * @param visible Whether the component window should be visible
 */
electron/preload.ts (1)

302-305: Clipboard helper should surface errors and return a boolean.

app:write-text-to-clipboard could theoretically fail (for example on Wayland when the seat is locked).
Returning a Promise<boolean> – or at least swallowing errors and logging – would make this call site safer and debuggable instead of silently failing.

- writeTextToClipboard: (text: string) => {
-   return ipcRenderer.send("app:write-text-to-clipboard", text);
- }
+ writeTextToClipboard: async (text: string): Promise<boolean> => {
+   try {
+     await ipcRenderer.invoke("app:write-text-to-clipboard", text);
+     return true;
+   } catch (err) {
+     console.error("[clipboard] failed:", err);
+     return false;
+   }
+ }
vite/src/components/browser-ui/main.tsx (1)

27-31: side setting won’t react to runtime setting changes.

getSetting is called only during the initial render, so changing the Sidebar Side setting in the UI won’t move the sidebar until a full reload.
Wrapping the call in a useEffect or – easier – using the reactive accessor that the settings provider probably offers would keep the UI in sync.

vite/src/components/portal/popover.tsx (1)

33-57: Effective portal integration with animations.

The PortalPopoverContent component:

  1. Successfully integrates with the portal system using PortalComponent
  2. Correctly positions content using portal context coordinates
  3. Implements smooth fade-out animation with AnimatePresence
  4. Properly styles the popover arrow

One suggestion to consider:

Consider extracting the animation configuration into constants or props to make it more customizable:

-        <motion.div initial={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.15 }}>
+        <motion.div 
+          initial={{ opacity: 1 }} 
+          exit={{ opacity: 0 }} 
+          transition={{ duration: props.animationDuration ?? 0.15 }}>
vite/src/hooks/use-copy-styles.ts (1)

106-128: Robust style change detection with MutationObserver.

The implementation properly:

  1. Performs initial style copying
  2. Sets up a MutationObserver to detect style changes
  3. Configures the observer with appropriate options
  4. Checks if the container is still valid before applying changes
  5. Cleans up the observer on unmount or when the container window changes

Consider adding error handling for edge cases:

 // Initial style copy
-copyStyles();
+try {
+  copyStyles();
+} catch (error) {
+  console.error("Failed to copy styles to portal:", error);
+}

 // Set up a MutationObserver to watch for style changes in the main document
 const styleObserver = new MutationObserver(() => {
   if (containerWin && !containerWin.closed) {
-    copyStyles();
+    try {
+      copyStyles();
+    } catch (error) {
+      console.error("Failed to update styles in portal:", error);
+    }
   }
 });
vite/src/components/portal/portal.tsx (2)

8-11: ID generation is prone to collision & debugging pain

Math.random().toString(36) gives only ~1 M distinct 8-char strings.
Replacing it with crypto.randomUUID() (Electron/Chromium ≥ 92) or a nanoid
eliminates collision risk and makes logs/searches easier.


60-67: window.open lacks feature flags & initial sizing

Without width, height, noopener, noreferrer or toolbar=0, the popup
behaves inconsistently across platforms (and may inherit the opener’s JS
context, defeating isolation).

Consider:

-const containerWin = window.open("about:blank", windowName, `componentId=${newComponentId}`);
+const features = [
+  `popup`,
+  `noopener`,
+  `noreferrer`,
+  `width=${Math.round(widthInPixels)}`,
+  `height=${Math.round(heightInPixels)}`,
+];
+const containerWin = window.open("about:blank", windowName, features.join(","));
vite/src/hooks/use-css-size-to-pixels.tsx (1)

78-88: Observer may stay attached if cssSizeString loses %

parentObserver is created only when the string initially contains %.
If later renders switch to a non-percentage value the observer continues to
run unnecessarily. Store the observer in a ref and disconnect whenever the
condition becomes false.

vite/src/hooks/use-bounding-rect.tsx (1)

20-48: updateRect runs outside React’s batching

requestAnimationFrame(updateRect) is good, but inside updateRect you invoke
setRect potentially many times in quick succession because scroll, resize and
mutation events fire frequently. Wrapping the body of updateRect with
unstable_batchedUpdates (React DOM export) or throttling at the event
handler level would reduce re-renders.

vite/src/lib/css.ts (2)

55-65: Returning 0 on invalid input can mask bugs

The early-exit branch converts malformed strings and even server-side rendering (no window) into a valid numeric result (0). This makes silent failures hard to detect downstream.

Consider returning NaN (and documenting that) or throwing for clearly invalid input; callers can then decide how to degrade gracefully.

-    console.warn(`cssSizeToPixels: Invalid input "${cssSizeString}". Returning 0.`);
-    return 0;
+    console.warn(`cssSizeToPixels: Invalid input "${cssSizeString}".`);
+    return Number.NaN;

172-195: Constant-allocate % property lookup tables

widthProps/heightProps arrays are rebuilt on every invocation, allocating new arrays and hampering engine optimisation. Moving them outside the function (or making them const Sets) eliminates per-call allocations and speeds up hot paths, especially if this util is used in layout-intensive code like resize observers.

-      const widthProps = [
+      // hoist outside cssSizeToPixels:
+      // const WIDTH_PROPS = new Set([...]);
+      const widthProps = WIDTH_PROPS;
docs/components/portal.md (2)

5-6: Tiny wording nit – drop “of”

“rendered outside of the main DOM hierarchy”
The phrase “outside the main DOM hierarchy” is already clear. Removing “of” tightens the prose.

-The Portal component allows content to be rendered outside of the main DOM hierarchy
+The Portal component allows content to be rendered outside the main DOM hierarchy
🧰 Tools
🪛 LanguageTool

[style] ~5-~5: This phrase is redundant. Consider using “outside”.
Context: ...component allows content to be rendered outside of the main DOM hierarchy into a separate ...

(OUTSIDE_OF)


91-107: List punctuation is inconsistent

A few bullet descriptions end with periods while most others do not (e.g., lines 91 & 105). Standardising punctuation improves readability—pick one style (period or none) and apply it consistently.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~91-~91: Loose punctuation mark.
Context: ...ns - initializePortalComponentWindows: Sets up IPC handlers and manages compon...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~105-~105: Loose punctuation mark.
Context: ... interface:set-component-window-bounds: Updates position and dimensions of comp...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~105-~105: You might be missing the article “the” here.
Context: ...e:set-component-window-bounds: Updates position and dimensions of component windows - ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9fedd7 and 599e570.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (42)
  • docs/components/portal.md (1 hunks)
  • docs/references/view-indexes.md (1 hunks)
  • electron/browser/components/glance-modal.ts (0 hunks)
  • electron/browser/components/omnibox.ts (1 hunks)
  • electron/browser/components/portal-component-windows.ts (1 hunks)
  • electron/browser/tabs/tab.ts (0 hunks)
  • electron/browser/utility/hot-reload.ts (1 hunks)
  • electron/browser/view-manager.ts (2 hunks)
  • electron/browser/window.ts (3 hunks)
  • electron/ipc/app/app.ts (2 hunks)
  • electron/modules/basic-settings.ts (3 hunks)
  • electron/modules/output.ts (1 hunks)
  • electron/preload.ts (2 hunks)
  • vite/src/App.tsx (0 hunks)
  • vite/src/components/browser-ui/browser-action.tsx (3 hunks)
  • vite/src/components/browser-ui/browser-content.tsx (2 hunks)
  • vite/src/components/browser-ui/browser-sidebar.tsx (3 hunks)
  • vite/src/components/browser-ui/main.tsx (4 hunks)
  • vite/src/components/browser-ui/sidebar/content/space-sidebar.tsx (1 hunks)
  • vite/src/components/browser-ui/sidebar/header/action-buttons.tsx (1 hunks)
  • vite/src/components/browser-ui/sidebar/header/navigation-buttons.tsx (4 hunks)
  • vite/src/components/browser-ui/sidebar/header/window-controls.tsx (1 hunks)
  • vite/src/components/browser-ui/sidebar/hover-detector.tsx (1 hunks)
  • vite/src/components/browser-ui/sidebar/spaces-switcher.tsx (1 hunks)
  • vite/src/components/portal/popover.tsx (1 hunks)
  • vite/src/components/portal/portal.tsx (1 hunks)
  • vite/src/components/providers/spaces-provider.tsx (3 hunks)
  • vite/src/components/settings/sections/general/basic-settings-cards.tsx (1 hunks)
  • vite/src/components/ui/popover.tsx (3 hunks)
  • vite/src/components/ui/resizable-sidebar.tsx (3 hunks)
  • vite/src/hooks/use-bounding-rect.tsx (1 hunks)
  • vite/src/hooks/use-copy-styles.ts (1 hunks)
  • vite/src/hooks/use-css-size-to-pixels.tsx (1 hunks)
  • vite/src/hooks/use-sidebar-resize.tsx (4 hunks)
  • vite/src/index.css (1 hunks)
  • vite/src/lib/css.ts (1 hunks)
  • vite/src/lib/flow/interfaces/app/app.ts (1 hunks)
  • vite/src/lib/flow/interfaces/browser/interface.ts (2 hunks)
  • vite/src/lib/utils.ts (1 hunks)
  • vite/src/main.tsx (1 hunks)
  • vite/src/routes/glance-modal/page.tsx (0 hunks)
  • vite/src/routes/glance-modal/route.tsx (0 hunks)
💤 Files with no reviewable changes (5)
  • vite/src/App.tsx
  • vite/src/routes/glance-modal/route.tsx
  • vite/src/routes/glance-modal/page.tsx
  • electron/browser/tabs/tab.ts
  • electron/browser/components/glance-modal.ts
🧰 Additional context used
🧬 Code Graph Analysis (13)
vite/src/components/browser-ui/sidebar/header/action-buttons.tsx (1)
vite/src/components/ui/resizable-sidebar.tsx (1)
  • SidebarGroup (722-722)
vite/src/lib/flow/interfaces/browser/interface.ts (1)
vite/src/lib/flow/types.ts (1)
  • PageBounds (1-6)
vite/src/components/browser-ui/sidebar/header/navigation-buttons.tsx (4)
vite/src/components/providers/spaces-provider.tsx (1)
  • useSpaces (19-25)
vite/src/lib/utils.ts (1)
  • cn (5-7)
vite/src/components/portal/popover.tsx (1)
  • PortalPopover (59-62)
vite/src/components/ui/popover.tsx (1)
  • PopoverTrigger (44-44)
vite/src/components/settings/sections/general/basic-settings-cards.tsx (1)
vite/src/components/ui/card.tsx (1)
  • CardContent (56-56)
vite/src/components/browser-ui/browser-content.tsx (2)
vite/src/hooks/use-bounding-rect.tsx (1)
  • useBoundingRect (8-116)
vite/src/lib/flow/types.ts (1)
  • PageBounds (1-6)
vite/src/components/ui/resizable-sidebar.tsx (1)
vite/src/lib/utils.ts (1)
  • cn (5-7)
electron/browser/components/portal-component-windows.ts (3)
electron/browser/window.ts (2)
  • TabbedBrowserWindow (28-249)
  • destroy (206-237)
electron/modules/output.ts (1)
  • debugPrint (19-25)
electron/browser/view-manager.ts (1)
  • destroy (45-60)
vite/src/components/browser-ui/main.tsx (6)
vite/src/components/ui/resizable-sidebar.tsx (2)
  • useSidebar (742-742)
  • SidebarInset (728-728)
vite/src/components/ui/sidebar.tsx (2)
  • useSidebar (675-675)
  • SidebarInset (661-661)
vite/src/components/providers/settings-provider.tsx (1)
  • useSettings (13-19)
vite/src/components/browser-ui/browser-sidebar.tsx (1)
  • BrowserSidebar (157-266)
vite/src/lib/utils.ts (1)
  • cn (5-7)
vite/src/components/browser-ui/sidebar/hover-detector.tsx (1)
  • SidebarHoverDetector (5-35)
vite/src/hooks/use-bounding-rect.tsx (1)
vite/src/components/portal/portal.tsx (1)
  • usePortalContext (26-29)
vite/src/components/browser-ui/sidebar/hover-detector.tsx (2)
vite/src/components/browser-ui/main.tsx (1)
  • SidebarSide (18-18)
vite/src/lib/utils.ts (1)
  • cn (5-7)
vite/src/components/portal/popover.tsx (2)
vite/src/components/ui/popover.tsx (2)
  • Popover (44-44)
  • PopoverContent (44-44)
vite/src/components/portal/portal.tsx (2)
  • usePortalContext (26-29)
  • PortalComponent (43-159)
vite/src/components/browser-ui/browser-action.tsx (3)
vite/src/components/portal/popover.tsx (1)
  • PortalPopover (59-62)
vite/src/lib/utils.ts (1)
  • cn (5-7)
vite/src/components/browser-ui/browser-sidebar.tsx (1)
  • SIDEBAR_HOVER_COLOR (32-33)
vite/src/hooks/use-css-size-to-pixels.tsx (1)
vite/src/lib/css.ts (1)
  • cssSizeToPixels (50-260)
🪛 LanguageTool
docs/components/portal.md

[style] ~5-~5: This phrase is redundant. Consider using “outside”.
Context: ...component allows content to be rendered outside of the main DOM hierarchy into a separate ...

(OUTSIDE_OF)


[uncategorized] ~91-~91: Loose punctuation mark.
Context: ...ns - initializePortalComponentWindows: Sets up IPC handlers and manages compon...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~105-~105: Loose punctuation mark.
Context: ... interface:set-component-window-bounds: Updates position and dimensions of comp...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~105-~105: You might be missing the article “the” here.
Context: ...e:set-component-window-bounds: Updates position and dimensions of component windows - ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[style] ~154-~154: Consider an alternative adverb to strengthen your wording.
Context: ...c CSS features - Window objects must be properly cleaned up to prevent resource leaks - ...

(PROPERLY_THOROUGHLY)

🔇 Additional comments (59)
vite/src/index.css (1)

2-2: Minor syntax update to align with project standards.

The quote style for the tailwindcss-animate plugin was changed from single to double quotes, which aligns with common CSS quoting conventions and maintains consistency with the other @plugin directive on line 3.

electron/modules/basic-settings.ts (3)

42-42: Setting name now visible in UI.

Making the sidebar collapse mode setting name visible in the UI improves clarity for users when accessing sidebar settings.


57-74: Good implementation of the new sidebar side setting.

The new sidebar side setting is well-structured with clear options. Marking the "Right" option as experimental is a good practice to set appropriate user expectations for a feature that may still be evolving.


127-129: Well-organized settings card update.

The settings card has been appropriately updated with a more general title and subtitle that encompasses both sidebar settings. The settings array properly includes both the new sidebarSide and existing sidebarCollapseMode options.

vite/src/components/browser-ui/sidebar/header/action-buttons.tsx (1)

158-158: Added horizontal padding improves UI spacing.

The added px-1 class provides better horizontal spacing within the sidebar group, improving the visual appearance of the navigation controls.

vite/src/components/settings/sections/general/basic-settings-cards.tsx (1)

49-49: Improved layout with flex layout classes 👍

Adding flex layout classes to CardContent creates a more consistent vertical spacing between settings items, improving the visual organization of the settings cards.

electron/modules/output.ts (1)

13-14: Added debug area for portal components

This addition is well-structured and follows the established pattern for debug areas. The new debug flag will be useful for troubleshooting the newly introduced portal component system.

electron/browser/utility/hot-reload.ts (1)

42-42: Increased minimum throttling timeout for better stability

Increasing the minimum timeout from 100ms to 300ms should help reduce resource contention during hot-reloading. This is a reasonable adjustment that balances development speed with system stability.

vite/src/lib/flow/interfaces/app/app.ts (1)

21-24: Added clipboard write functionality

This is a clean extension to the FlowAppAPI interface with proper documentation. The method signature is simple and clear, following the pattern of other methods in this interface.

vite/src/components/browser-ui/sidebar/content/space-sidebar.tsx (1)

47-47: Good adjustment to prevent initial animation flash

Setting initial={false} on AnimatePresence prevents unwanted animations when the sidebar first loads, creating a smoother user experience for content that's already present on mount.

electron/ipc/app/app.ts (2)

1-1: Correctly imported clipboard API from Electron

Good addition of the clipboard module import alongside the existing app module.


11-13: Well-implemented clipboard write handler

The IPC handler for clipboard writing is clean and follows Electron's standard patterns. This is essential functionality for the portal component system to interact with the system clipboard across windows.

vite/src/components/browser-ui/sidebar/spaces-switcher.tsx (1)

22-22: Improved icon color contrast and consistency

The updated color classes provide better contrast in both light and dark modes while maintaining visual hierarchy between active and inactive states.

vite/src/main.tsx (2)

1-1: Good import renaming for clarity

Renaming StrictMode to ReactStrictMode improves code clarity, especially with the conditional usage pattern.


10-14: Clean implementation of conditional StrictMode

The conditional wrapping using either ReactStrictMode or Fragment is a clean approach that maintains the same component structure regardless of the StrictMode setting.

vite/src/components/providers/spaces-provider.tsx (1)

149-149: Good implementation of portal for stylesheet.

Using createPortal to inject styles into document.head is the correct approach for global styles.

vite/src/components/browser-ui/sidebar/header/window-controls.tsx (3)

1-7: LGTM - Component setup with hook integration.

The component properly uses the useBoundingRect hook to manage window control positioning.


8-15: LGTM - Window button positioning implementation.

The effect correctly updates window button position whenever the titlebar bounds change.


26-27: LGTM - Simple div element for positioning reference.

The component renders a minimal div with appropriate sizing and positioning.

vite/src/components/ui/popover.tsx (3)

5-5: LGTM - Import Fragment for conditionally disabling portal.

Good addition of the Fragment import to support the new portal conditional rendering.


19-22: LGTM - Portal rendering flexibility with backward compatibility.

The addition of the optional portal prop with a default value of true maintains backward compatibility while allowing for more flexible rendering strategies.


25-36: Good implementation of conditional portal wrapping.

The component now properly wraps its content in either a Portal or Fragment based on the prop value.

vite/src/components/browser-ui/browser-content.tsx (4)

1-1: Updated imports to use the new bounding rect hook.

Good removal of unnecessary imports and addition of the useBoundingRect hook import.

Also applies to: 5-5


12-12: Good simplification with useBoundingRect hook.

Using the useBoundingRect hook reduces code complexity by abstracting the dimension tracking logic.


14-24: Well-refactored effect for updating page bounds.

The effect is correctly simplified to use the rect value from the hook and only runs when needed. The code is now cleaner while maintaining the same functionality.


35-38: Properly updated debug display to use rect from hook.

The debug display code is correctly updated to use the new rect object. Good conditional check for both the debug flag and the rect existence.

vite/src/components/browser-ui/browser-action.tsx (2)

6-6: Updated imports for portal-based popover components.

Good update to the imports, keeping only the PopoverTrigger from UI popover while adding the new PortalPopover from the portal components.

Also applies to: 12-12


165-165: Replaced popover implementation with portal-based components.

The switch to portal-based popover components is a good improvement. This will help prevent CSS inheritance issues and improve stacking context management by rendering content in a separate DOM node.

Also applies to: 171-171, 201-202

vite/src/components/browser-ui/sidebar/hover-detector.tsx (3)

1-4: Good imports for the new SidebarHoverDetector component.

The imports are clean and appropriate for the component's functionality.


5-11: Well-structured component with clean props interface.

The component definition is well structured with clear props typing and good use of useCallback for event handler optimization.


12-24: Properly implemented event listener with cleanup.

The event listener is correctly set up with proper cleanup in the effect's return function, which prevents memory leaks.

vite/src/hooks/use-sidebar-resize.tsx (3)

12-12: Good addition of right-side support parameter.

The new isRightSide property enables the sidebar to be positioned and resized from either the left or right side of the window, which aligns with the sidebar positioning feature mentioned in the PR objectives.


43-43: Clear default value implementation.

Setting isRightSide to false by default ensures backward compatibility with existing code that doesn't specify this parameter.


155-165: Properly updated dependencies array.

The dependencies array correctly includes the new isRightSide parameter to ensure the effect is rerun when this property changes.

electron/browser/window.ts (2)

12-12: Good import of portal component windows initialization.

This import brings in the new portal system initialization, replacing the previous glance modal approach.


77-78: Proactive window button visibility handling.

Hiding the window buttons before component mount prevents UI flickering where window buttons might briefly appear before being controlled by the UI components.

vite/src/components/browser-ui/sidebar/header/navigation-buttons.tsx (3)

7-10: Good migration to portal-based popover system.

The new imports support the transition from dropdown menus to the portal-based popover system, enabling floating UI elements that can render outside the DOM hierarchy.


40-40: Theme awareness implementation.

Adding space theme awareness ensures visual consistency between the main UI and popovers.


69-70: Well-implemented theme class injection.

Using the cn utility to conditionally apply the dark theme class based on the current space theme is a clean approach.

vite/src/lib/flow/interfaces/browser/interface.ts (1)

1-1: Good type import organization.

Importing PageBounds from flow types promotes code reuse and type consistency across the application.

vite/src/components/ui/resizable-sidebar.tsx (3)

228-230: Improved sidebar visibility for all screen sizes.

The sidebar is now visible by default on all screen sizes by replacing the "hidden md:block" classes with a dynamic class name using the cn utility. This change aligns with the portal component system by making the sidebar more consistent across different display contexts.


302-304: Added right-side support for sidebar resizing.

The isRightSide prop with a default value of false enables the sidebar to be positioned and resized from either the left or right side of the screen. This is a valuable enhancement for the portal components system.


315-316: Properly passing new resize parameters to the hook.

The implementation correctly passes both the setIsDraggingRail and isRightSide parameters to the useSidebarResize hook, enabling side-specific dragging behavior.

vite/src/components/portal/popover.tsx (5)

1-6: Good choice of dependencies for the portal popover system.

The imports are well-organized and include all necessary dependencies for creating a portal-based popover: positioning context, UI components, React hooks, and animation libraries.


7-12: Well-defined context type for popover state management.

The PopoverContextType interface clearly defines the contract for the popover state management with proper TypeScript typing.


14-31: Clean implementation of controlled/uncontrolled component pattern.

The PortalPopoverRoot component correctly implements both controlled and uncontrolled usage patterns by:

  1. Using internal state when props aren't provided
  2. Respecting external state when provided
  3. Properly passing state to the context and underlying component

This follows React best practices for flexible component API design.


59-62: Clean object export pattern.

Using the object pattern for PortalPopover export provides a clean, organized API that groups related components together while maintaining their separation of concerns.


64-71: Helpful error for hook usage.

The usePopover hook includes proper context validation with a descriptive error message when used outside of a PortalPopover.Root component, which will help developers use the API correctly.

electron/browser/view-manager.ts (4)

1-5: Enhanced type safety with WebContentsView.

Refining the type from generic View to specific WebContentsView improves type safety and makes the API more precise for the portal component system's needs.


12-16: Automatic cleanup on view destruction prevents memory leaks.

Adding an event listener to the webContents.destroyed event that automatically triggers view removal is an excellent enhancement to prevent memory leaks and simplify client code.


20-26: Flexible view removal with parent handling option.

The enhanced removeView method with the optional dontRemoveFromParent parameter allows for more flexible cleanup scenarios, particularly when a view is already being removed elsewhere (like during the destruction event).


41-43: Type consistency in getViewZIndex.

Updating getViewZIndex to accept WebContentsView maintains type consistency throughout the class API.

vite/src/hooks/use-copy-styles.ts (3)

3-6: Well-documented custom hook.

The JSDoc comment clearly explains the purpose of the hook, making it easy for other developers to understand and use.


7-17: Proper hook structure with dependency array.

The hook follows React best practices by:

  1. Using useEffect with a properly defined dependency array
  2. Including an early return when the container window is null
  3. Defining local variables within the effect scope

22-105: Comprehensive style synchronization logic.

The style copying implementation:

  1. Handles both <style> and <link> elements correctly
  2. Matches existing styles to prevent duplicates
  3. Updates attributes when they differ
  4. Removes styles that don't exist in the main document
  5. Properly clones nodes with their attributes

This thorough approach ensures consistent styling between the main window and portal windows.

vite/src/components/portal/portal.tsx (2)

93-95: useCopyStyles should be guarded against a null window

When the first render runs, containerWinRef.current is null, so the hook
executes with an invalid argument. If the hook doesn’t handle that internally
it will throw.

-// Use the hook for style copying
-useCopyStyles(containerWinRef.current);
+if (containerWinRef.current) {
+  useCopyStyles(containerWinRef.current);
+}

120-131: Verify that flow.interface is always available

The calls to flow.interface.* run on every prop change. If the component is
rendered in a non-Electron context (SSR, unit tests, storybook), these calls
will explode. Please add a runtime guard or mock.

vite/src/lib/css.ts (1)

164-205: Missing fall-through for % when parent width/height is auto

If the parent’s computed width/height is auto, parsePixelValue returns NaN and the function falls back to 0. This is reasonable, but callers have no way of distinguishing unresolvable from zero. Consider bubbling up NaN or adding an optional defaultValue parameter so consumers can handle this case more explicitly.

vite/src/components/browser-ui/browser-sidebar.tsx (1)

251-258: Potential prop-type mismatch: width passed as number

PortalComponent docs (and typings in portal.tsx) indicate width expects a CSS string ("300px" etc.). Here a numeric width from useSidebar() is forwarded directly. If PortalComponent still enforces a string, this will break type-checking and runtime conversion inside cssSizeToPixels.

Please verify:

  1. Is width a number (e.g., 300) or a CSS string?
  2. Does PortalComponent accept number | string?

Adjust as needed, e.g.:

-        width={width}
+        width={`${width}px`}

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

♻️ Duplicate comments (2)
vite/src/components/browser-ui/browser-sidebar.tsx (2)

56-85: ⚠️ Potential issue

Fix timer cleanup logic in useSidebarHover hook

The current implementation has a logical issue where it attempts to clear a timeout from within its own callback, which doesn't prevent memory leaks or state updates after unmount. The timeout should be cleared before setting a new one.

Apply this fix:

function useSidebarHover(setIsHoveringSidebar: (isHovering: boolean) => void) {
  const isHoveringSidebarRef = useRef(false);
  const timeoutIdRef = useRef<NodeJS.Timeout | null>(null);

  const handleMouseEnter = useCallback(() => {
    isHoveringSidebarRef.current = true;
+   if (timeoutIdRef.current) {
+     clearTimeout(timeoutIdRef.current);
+   }
    timeoutIdRef.current = setTimeout(() => {
-     if (timeoutIdRef.current) {
-       clearTimeout(timeoutIdRef.current);
-     }
      if (isHoveringSidebarRef.current) {
        setIsHoveringSidebar(true);
      }
    }, 100);
  }, [setIsHoveringSidebar]);

  const handleMouseLeave = useCallback(() => {
    isHoveringSidebarRef.current = false;
+   if (timeoutIdRef.current) {
+     clearTimeout(timeoutIdRef.current);
+   }
    timeoutIdRef.current = setTimeout(() => {
-     if (timeoutIdRef.current) {
-       clearTimeout(timeoutIdRef.current);
-     }
      if (!isHoveringSidebarRef.current) {
        setIsHoveringSidebar(false);
      }
    }, 100);
  }, [setIsHoveringSidebar]);

  return { handleMouseEnter, handleMouseLeave };
}

191-197: ⚠️ Potential issue

Numeric x values should include px for motion spring

The sideOffset is constructed as a string without the "px" unit. This can cause animation issues as Motion may not interpret bare numbers in strings correctly.

Convert to a number (preferred) or append "px":

-const sideOffset = side === "left" ? `-${width}` : `${width}`;
+const sideOffset: number = side === "left" ? -width : width;
 const animationProps = {
   initial: { x: sideOffset, originX: side === "left" ? 0 : 1 },
   animate: { x: 0 },
   exit: { x: sideOffset },
   transition: { type: "spring", damping: 30, stiffness: 400 }
 };
🧹 Nitpick comments (4)
vite/src/components/providers/minimal-toast-provider.tsx (4)

27-81: Consider accessibility improvements for the toast container.

The toast implementation works well, but is missing accessibility attributes that would make it more usable for screen readers.

 <motion.div
   key={currentMessage}
   initial={{ opacity: 0, scale: 0.9 }}
   animate={{ opacity: 1, scale: 1 }}
   exit={{ opacity: 0, scale: 0.9 }}
   transition={{ duration: 0.3 }}
-  className="box-border border border-border bg-space-background-start rounded-lg w-full h-full flex items-center justify-center"
+  className="box-border border border-border bg-space-background-start rounded-lg w-full h-full flex items-center justify-center"
+  role="alert"
+  aria-live="polite"
   onClick={removeToast}
 >

48-55: Consider more flexible positioning for the toast.

The current width/height values of "10%" and "6%" may lead to inconsistent sizing across different viewport sizes. A fixed size or more adaptable approach might improve consistency.

 <PortalComponent
   visible={isVisible}
   x={sidebarSide === "left" ? "100vw" : "0vw"}
   y={0}
-  width={"10%"}
-  height={"6%"}
+  width={"auto"}
+  height={"auto"}
   anchorX={sidebarSide === "left" ? "right" : "left"}
 >

83-113: Add cleanup for timeout on component unmount.

The MinimalToastProvider should clean up any pending timeouts when it unmounts to prevent potential memory leaks.

export function MinimalToastProvider({ children, sidebarSide }: ToastProviderProps) {
  const [currentMessage, setCurrentMessage] = useState<string | null>(null);
  const timeoutIdRef = useRef<NodeJS.Timeout | null>(null);

+ useEffect(() => {
+   // Cleanup function to clear timeout on unmount
+   return () => {
+     if (timeoutIdRef.current) {
+       clearTimeout(timeoutIdRef.current);
+     }
+   };
+ }, []);

  const removeToast = () => {
    // Remove timeout
    if (timeoutIdRef.current) {
      clearTimeout(timeoutIdRef.current);
      timeoutIdRef.current = null;
    }

    // Remove message
    setCurrentMessage(null);
  };

98-105: Consider adding support for multiple toast messages.

The current implementation replaces any existing toast with a new one. For a more robust notification system, you might want to consider a queue-based approach that can display multiple notifications.

This is an optional enhancement for future consideration. The current implementation makes sense for a minimal toast provider, but if you need to support multiple notifications in the future, you would need to modify the state to store an array of messages rather than a single message.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1166459 and cd3990e.

📒 Files selected for processing (7)
  • docs/references/view-indexes.md (1 hunks)
  • vite/src/components/browser-ui/browser-sidebar.tsx (2 hunks)
  • vite/src/components/browser-ui/main.tsx (4 hunks)
  • vite/src/components/browser-ui/sidebar/header/address-bar/copy-link-button.tsx (3 hunks)
  • vite/src/components/browser-ui/sidebar/header/window-controls.tsx (1 hunks)
  • vite/src/components/omnibox/main.tsx (1 hunks)
  • vite/src/components/providers/minimal-toast-provider.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • vite/src/components/omnibox/main.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • docs/references/view-indexes.md
  • vite/src/components/browser-ui/sidebar/header/window-controls.tsx
  • vite/src/components/browser-ui/main.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
vite/src/components/browser-ui/sidebar/header/address-bar/copy-link-button.tsx (1)
vite/src/components/providers/minimal-toast-provider.tsx (1)
  • useToast (14-20)
🔇 Additional comments (10)
vite/src/components/browser-ui/sidebar/header/address-bar/copy-link-button.tsx (3)

3-3: Good addition of the useToast hook import.

This import properly brings in the toast functionality from the new minimal toast provider, allowing for user feedback when copy actions occur.


56-57: Good destructuring pattern for the toast hook.

The destructuring syntax for useToast is clean and follows React best practices.


69-69: Great user feedback enhancement with toast notification.

Adding a toast notification after successful clipboard operations improves user experience by providing clear feedback. This complements the visual indicator (check icon) that's already implemented.

vite/src/components/providers/minimal-toast-provider.tsx (2)

1-7: Clean import structure with good organization.

The imports are well-organized, bringing in the necessary dependencies for the portal component, React functionality, animations, and utilities.


8-20: Well-implemented context and hook pattern.

The toast context and hook follow React best practices with proper error handling when used outside a provider. This enforces correct usage throughout the application.

vite/src/components/browser-ui/browser-sidebar.tsx (5)

20-23: Well-structured import organization

Good job on organizing imports by functionality - adding the portal components, animation libraries, and window controls necessary for the new floating sidebar feature.


35-53: Good extraction of animation logic into custom hook

The useSidebarAnimation hook effectively manages mounting/unmounting logic for animated components, improving separation of concerns and reusability.


87-123: Good component extraction for improved modularity

Breaking down the sidebar into SidebarFooterContent and SidebarHeaderContent components enhances maintainability and readability by separating concerns.


177-188: Improved event listener handling

Good implementation of the sidebar toggle event listener with proper cleanup in the useEffect return function, ensuring no memory leaks.


258-270: Well-implemented portal component integration

The conditional rendering using PortalComponent for the floating variant is a clean approach that properly handles positioning based on the sidebar side.

@iamEvanYT iamEvanYT merged commit 01edf86 into main Apr 28, 2025
1 check passed
@iamEvanYT iamEvanYT deleted the evan/portal-components branch April 28, 2025 23:56
@coderabbitai coderabbitai bot mentioned this pull request Jun 23, 2025
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