Skip to content

refactor: Extract PathInput component from FileBrowserDialog & Improve UI/UX#262

Merged
webdevcody merged 5 commits intoAutoMaker-Org:mainfrom
illia1f:refactor/file-path-input
Dec 24, 2025
Merged

refactor: Extract PathInput component from FileBrowserDialog & Improve UI/UX#262
webdevcody merged 5 commits intoAutoMaker-Org:mainfrom
illia1f:refactor/file-path-input

Conversation

@illia1f
Copy link
Contributor

@illia1f illia1f commented Dec 24, 2025

Summary

Refactored the file browser dialog by extracting the path navigation UI into a reusable PathInput component, improving code organization and maintainability.

Changes

New Component: PathInput

Created apps/ui/src/components/ui/path-input.tsx with the following features:

  • Dual-mode interface: Breadcrumb navigation view and text input editing mode in a single unified component
  • Navigation controls: Home and back buttons for quick directory traversal
  • Click-to-edit UX: Click anywhere on the path to enable editing
  • Action buttons:
    • Pencil icon in breadcrumb mode to enter editing
    • "Go" button (→) in edit mode for navigation
  • Keyboard shortcuts:
    • Enter to navigate to path
    • Escape to cancel and exit edit mode
  • Error states: Red border indication when path is invalid
  • Accessibility: ARIA labels, semantic roles, improved focus management

Refactored FileBrowserDialog

  • Reduced component size from ~565 lines to ~380 lines (-32%)
  • Removed 3 state variables: pathInput, isEditing, pathInputRef
  • Removed 6+ handler functions now encapsulated in PathInput
  • Removed parseBreadcrumbs helper (moved to PathInput)
  • Eliminated duplicate input field - previously had separate breadcrumb display and always-visible input field, now uses single unified component

UI/UX Improvements

  • Responsive breadcrumbs: Horizontal scroll for long paths with truncation
  • Smooth transitions: Hover states and focus rings for better interaction feedback
  • Always-visible controls: Back button always visible (disabled when unavailable) for consistent layout
  • Better spacing: Increased touch targets (h-8), improved padding and gaps
  • Visual hierarchy: Clearer separation between navigation controls and path display

Screenshot

Breadcrumb mode (default view):
image_2025-12-24_19-26-46

Edit mode (with "→" button):
image_2025-12-24_19-25-51

Error state (red border):
image_2025-12-24_19-38-14

Summary by CodeRabbit

  • New Features

    • Added a reusable, accessible breadcrumb component set for path navigation.
    • Introduced an inline, editable PathInput with clickable breadcrumbs, Home and Parent navigation.
  • Improvements

    • Simplified file browser UI by removing the legacy manual path field and Go button; navigation now uses the PathInput.
    • Streamlined interactions: click breadcrumbs or press Enter to navigate, Escape to cancel; updated arrow glyphs for clarity.

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

…onent

- Removed unused state and imports from FileBrowserDialog.
- Replaced direct path input with a new PathInput component for improved navigation.
- Enhanced state management for path navigation and error handling.
- Updated UI elements for better user experience and code clarity.
- Changed the navigation instruction text in FileBrowserDialog to use an arrow symbol for clarity.
- Added an ArrowRight icon to the PathInput component's button for improved visual feedback when navigating to a path.
@coderabbitai
Copy link

coderabbitai bot commented Dec 24, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

This PR adds Breadcrumb and PathInput UI components and refactors FileBrowserDialog to use PathInput, removing the legacy manual path input, Go button, local path-input state, and related keyboard handling while preserving directory browsing behavior.

Changes

Cohort / File(s) Summary
Breadcrumb components (new)
apps/ui/src/components/ui/breadcrumb.tsx
Adds composable breadcrumb primitives: Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, BreadcrumbEllipsis with accessibility attributes and slot-friendly composition.
Path input component (new)
apps/ui/src/components/ui/path-input.tsx
Adds PathInput, parseBreadcrumbs, and types PathInputProps/BreadcrumbSegment. Implements breadcrumb rendering, Home/Parent buttons, inline editable path input, keyboard handling (Enter/Escape), focus/select-on-error, and Windows/POSIX parsing.
File browser dialog refactor
apps/ui/src/components/dialogs/file-browser-dialog.tsx
Replaces manual path UI with PathInput; removes pathInput state, refs, Go button, and key handlers; introduces handleNavigate/handleGoHome callbacks; updates initial load flow and some messaging/styling (scrollbar, arrow symbol).

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant PI as PathInput
    participant FBD as FileBrowserDialog
    participant API as Browse API

    User->>PI: Click breadcrumb / Home / Edit path
    alt Click breadcrumb or Home
        PI->>FBD: onNavigate(path) / onHome()
    else Edit + Enter
        PI->>PI: validate/parse input
        PI->>FBD: onNavigate(newPath)
    end

    FBD->>API: browseDirectory(path)
    API-->>FBD: Directory contents / error

    alt Success
        FBD->>FBD: update currentPath & file list
        FBD->>PI: update currentPath prop
        PI->>PI: re-render breadcrumbs
    else Error
        FBD->>PI: indicate error, request focus
        PI->>User: focus & select input for retry
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped the breadcrumb trail so neat,
Clicked Home, typed paths, and skipped a beat—
Carrots of folders lined in a row,
Entered a path, watched the files show,
A little hop, and onward I go!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 accurately summarizes the main changes: extracting a new PathInput component and refactoring FileBrowserDialog with UI/UX improvements.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9dee9fb and 60d4b5c.

📒 Files selected for processing (1)
  • apps/ui/src/components/ui/path-input.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/ui/src/components/ui/path-input.tsx

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

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @illia1f, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the file browser dialog by extracting its path navigation functionality into a new, highly reusable PathInput component. This change drastically simplifies the FileBrowserDialog component, improves code maintainability, and delivers a more intuitive and accessible user experience for path interaction, featuring a dual-mode display, navigation controls, and robust error handling.

Highlights

  • New PathInput Component: Introduced a dedicated, reusable PathInput component (apps/ui/src/components/ui/path-input.tsx) that encapsulates all path navigation logic and UI, supporting both breadcrumb and text input modes.
  • FileBrowserDialog Refactoring: Significantly reduced the complexity and line count of the FileBrowserDialog component (from ~565 to ~380 lines) by offloading path management, state variables, and handler functions to the new PathInput component.
  • Enhanced UI/UX for Path Navigation: Implemented a dual-mode interface for path navigation with responsive breadcrumbs, click-to-edit functionality, navigation controls (Home, Back, Go), keyboard shortcuts (Enter, Escape), and clear error states, improving overall user experience and accessibility.
  • Improved Code Organization: Centralized path parsing, state management, and interaction logic within PathInput, leading to cleaner, more modular, and maintainable code within the UI components.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This is an excellent refactoring that significantly improves the modularity and maintainability of the FileBrowserDialog by extracting the path handling logic into a new PathInput component. The new component is well-designed, with a clean API and good user experience features like click-to-edit and keyboard navigation. The code is clean and easy to follow.

I've found one minor bug related to handling the root path and a small performance optimization opportunity in the new PathInput component. My detailed comments are below. Overall, great work on this pull request!

Copy link

@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

🧹 Nitpick comments (5)
apps/ui/src/components/ui/path-input.tsx (3)

22-48: Unix root path returns empty breadcrumbs.

When currentPath is "/" (Unix root), split(/[/\\]/).filter(Boolean) yields an empty array, so no breadcrumbs are displayed. Users at the root directory won't see any path indication.

Consider handling the root case explicitly:

🔎 Proposed fix
 function parseBreadcrumbs(path: string): BreadcrumbSegment[] {
   if (!path) return [];
 
   const segments = path.split(/[/\\]/).filter(Boolean);
   const isWindows = segments[0]?.includes(':');
+
+  // Handle Unix root directory
+  if (!isWindows && segments.length === 0 && path === '/') {
+    return [{ name: '/', path: '/', isLast: true }];
+  }
 
   return segments.map((segment, index) => {

118-130: Consider using the generic FocusEvent type for better type safety.

The FocusEvent type without a generic defaults to FocusEvent<Element>. Using FocusEvent<HTMLInputElement> would provide more precise typing.

🔎 Proposed fix
   const handleInputBlur = useCallback(
-    (e: FocusEvent) => {
+    (e: FocusEvent<HTMLInputElement>) => {
       // Check if focus is moving to another element within this component
       if (containerRef.current?.contains(e.relatedTarget)) {
         return;
       }

228-238: Consider avoiding href="#" to prevent potential scroll artifacts.

Using href="#" can cause a brief scroll-to-top flash in some browsers before preventDefault takes effect. Since this is purely JS-driven navigation, consider using a button or a non-scrolling href.

🔎 Proposed fix
                       <BreadcrumbLink
-                        href="#"
+                        href=""
                         onClick={(e) => {
                           e.preventDefault();
                           handleBreadcrumbClick(crumb.path);
                         }}

Alternatively, refactor BreadcrumbLink to support asChild with a button.

apps/ui/src/components/dialogs/file-browser-dialog.tsx (1)

180-197: Inconsistent use of useCallback.

handleGoHome and handleNavigate are wrapped in useCallback, but handleSelectDirectory and handleSelectDrive are regular functions. Consider wrapping them for consistency, especially since they're passed as props to child elements.

🔎 Proposed fix
-  const handleSelectDirectory = (dir: DirectoryEntry) => {
-    browseDirectory(dir.path);
-  };
+  const handleSelectDirectory = useCallback(
+    (dir: DirectoryEntry) => {
+      browseDirectory(dir.path);
+    },
+    [browseDirectory]
+  );

   const handleGoHome = useCallback(() => {
     browseDirectory();
   }, [browseDirectory]);

   const handleNavigate = useCallback(
     (path: string) => {
       browseDirectory(path);
     },
     [browseDirectory]
   );

-  const handleSelectDrive = (drivePath: string) => {
-    browseDirectory(drivePath);
-  };
+  const handleSelectDrive = useCallback(
+    (drivePath: string) => {
+      browseDirectory(drivePath);
+    },
+    [browseDirectory]
+  );
apps/ui/src/components/ui/breadcrumb.tsx (1)

52-63: Consider accessibility implications of role="link" on a non-interactive element.

Using role="link" with aria-disabled="true" on a <span> may confuse screen reader users who expect interactive behavior. The aria-current="page" alone suffices to indicate the current page without implying interactivity.

🔎 Proposed fix
 function BreadcrumbPage({ className, ...props }: React.ComponentProps<'span'>) {
   return (
     <span
       data-slot="breadcrumb-page"
-      role="link"
-      aria-disabled="true"
       aria-current="page"
       className={cn('text-foreground font-normal', className)}
       {...props}
     />
   );
 }

Note: This follows the shadcn/ui pattern, so you may want to keep it for consistency with that ecosystem.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 91eeda3 and ccc7c6c.

📒 Files selected for processing (3)
  • apps/ui/src/components/dialogs/file-browser-dialog.tsx
  • apps/ui/src/components/ui/breadcrumb.tsx
  • apps/ui/src/components/ui/path-input.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
apps/ui/src/components/ui/breadcrumb.tsx (1)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/dialogs/file-browser-dialog.tsx (1)
apps/ui/src/components/ui/path-input.tsx (1)
  • PathInput (288-288)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (12)
apps/ui/src/components/ui/path-input.tsx (5)

1-14: LGTM!

Imports are well-organized, grouping React hooks, icons, and UI components appropriately.


50-67: LGTM!

Props interface is well-documented with JSDoc comments and appropriate optional/required designations.


84-99: LGTM!

The sync effect correctly preserves user input during editing, and the focus effect provides good UX by selecting text on error for easy correction.


257-280: LGTM!

The input section has proper accessibility attributes (aria-invalid, aria-label) and appropriate disabled states.


288-289: LGTM!

Clean exports of the component, helper function, and types for external consumption.

apps/ui/src/components/dialogs/file-browser-dialog.tsx (3)

1-14: LGTM!

Imports are cleaned up appropriately, removing unused imports and adding the new PathInput component.


247-255: LGTM!

The PathInput integration is clean. The error string is correctly converted to a boolean with !!error.


351-354: LGTM!

The instruction text update aligns well with the new PathInput UI that displays an arrow (→) button for navigation.

apps/ui/src/components/ui/breadcrumb.tsx (4)

7-9: LGTM!

The Breadcrumb component properly sets aria-label="breadcrumb" for accessibility.


11-22: LGTM!

Correctly uses an <ol> element for semantic list structure with proper styling.


65-92: LGTM!

Both BreadcrumbSeparator and BreadcrumbEllipsis handle accessibility correctly—separator is properly hidden from assistive technology, and ellipsis includes screen reader fallback text.


94-102: LGTM!

All components are properly exported for external use.

- Introduced useMemo for breadcrumb parsing to enhance performance.
- Updated breadcrumb rendering to utilize memoized values for improved efficiency.
- Added logic to correctly parse and return the root path for Unix-like systems in the breadcrumb segment function.
@Shironex Shironex added the Enhancement Improvements to existing functionality or UI. label Dec 24, 2025
@Shironex Shironex added Refactor A complete logic rewrite is requested or being performed for an issue. Ready-To-Merge A feature or bug has been improved/fixed and a final review is requested before merging. and removed Enhancement Improvements to existing functionality or UI. labels Dec 24, 2025
@webdevcody webdevcody merged commit 5418d04 into AutoMaker-Org:main Dec 24, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready-To-Merge A feature or bug has been improved/fixed and a final review is requested before merging. Refactor A complete logic rewrite is requested or being performed for an issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants