Compact mobile navbar and improved UI for panels#4
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request enhances the mobile user experience by making the UI more compact and improving panel dragging functionality. The changes reduce padding, margins, and text sizes across mobile panels while maintaining usability. Key improvements include a dynamically sizing mobile navbar that becomes more compact when panels are open, and improved drag handles with better visual feedback.
Changes:
- Replaced viewport height from
h-screentoh-[100dvh]for better mobile browser compatibility - Reduced spacing and sizing across all mobile panels (Sidebar, RoutePanel, ChatWidget) for a more compact UI
- Implemented dynamic navbar sizing that compacts when panels are open
- Redesigned drag handles to be more subtle and improved draggable area functionality
- Shortened button labels ("Optimize Route" → "Optimize", "Clear All" → "Clear", "Sign In to Save" → "Sign In") for mobile
- Changed location item buttons to icon-only with improved layouts
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| todos.md | Added a new todo item for testing (A/B or QA) |
| frontend/app/page.js | Changed viewport height to use 100dvh for better mobile compatibility |
| frontend/app/components/Sidebar.js | Comprehensive compacting of mobile UI: reduced padding, smaller drag handle, redesigned location items with icon-only buttons, and compacted action buttons |
| frontend/app/components/Search.js | Shortened placeholder text for better mobile display |
| frontend/app/components/RoutePanel.js | Applied similar compacting changes as Sidebar with reduced padding and button sizing |
| frontend/app/components/MobileNav.js | Implemented dynamic sizing that makes navbar more compact when panels are open |
| frontend/app/components/ChatWidget.js | Reduced drag handle size and padding for more compact appearance |
| frontend/app/components/ChatInterface.js | Changed buttons to icon-only on mobile while keeping text labels on desktop |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <button | ||
| onClick={() => setStartLocation(index)} | ||
| className={`p-1.5 rounded transition-all ${startIndex === index | ||
| ? 'bg-green-600 text-white' | ||
| : 'bg-gray-100 text-gray-600 hover:bg-green-100' | ||
| }`} | ||
| title="Set as start" | ||
| > | ||
| {/* Flag icon for start */} | ||
| <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 21v-4m0 0V5a2 2 0 012-2h6.5l1 1H21l-3 6 3 6h-8.5l-1-1H5a2 2 0 00-2 2zm9-13.5V9" /> | ||
| </svg> | ||
| </button> |
There was a problem hiding this comment.
The "Set as start" button has a title attribute but is missing an aria-label attribute. Icon-only buttons should have aria-label for better accessibility, especially for screen reader users. Add aria-label="Set as start" to match the title.
| <button | ||
| onClick={() => setEndLocation(index)} | ||
| className={`p-1.5 rounded transition-all ${endIndex === index | ||
| ? 'bg-red-600 text-white' | ||
| : 'bg-gray-100 text-gray-600 hover:bg-red-100' | ||
| }`} | ||
| title="Set as end" | ||
| > | ||
| {/* Location pin icon for end */} | ||
| <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" /> | ||
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" /> | ||
| </svg> | ||
| </button> |
There was a problem hiding this comment.
The "Set as end" button has a title attribute but is missing an aria-label attribute. Icon-only buttons should have aria-label for better accessibility, especially for screen reader users. Add aria-label="Set as end" to match the title.
| <p className="font-medium text-gray-900 text-sm truncate">{location.name}</p> | ||
| {startIndex === index && ( | ||
| <span className="px-2 py-1 text-xs font-medium bg-green-100 text-green-800 rounded-full">Start</span> | ||
| <span className="px-1.5 py-0.5 text-[10px] font-medium bg-green-100 text-green-800 rounded shrink-0">S</span> |
There was a problem hiding this comment.
The badge text has been shortened from "Start" to just "S". While this saves space, it may reduce clarity for users. Consider adding an aria-label or title attribute to the span to provide the full text "Start" for accessibility and better user understanding.
| )} | ||
| {endIndex === index && ( | ||
| <span className="px-2 py-1 text-xs font-medium bg-red-100 text-red-800 rounded-full">End</span> | ||
| <span className="px-1.5 py-0.5 text-[10px] font-medium bg-red-100 text-red-800 rounded shrink-0">E</span> |
There was a problem hiding this comment.
The badge text has been shortened from "End" to just "E". While this saves space, it may reduce clarity for users. Consider adding an aria-label or title attribute to the span to provide the full text "End" for accessibility and better user understanding.
| setIsChatOpen, | ||
| chatHeight, | ||
| sidebarHeight, | ||
| routeHeight |
There was a problem hiding this comment.
The imported variables chatHeight, sidebarHeight, and routeHeight are destructured from useTrip() but are never used in the component. These should be removed to keep the code clean and avoid confusion.
| setIsChatOpen, | |
| chatHeight, | |
| sidebarHeight, | |
| routeHeight | |
| setIsChatOpen |
|
|
||
| {/* Divider */} | ||
| <div className="w-px bg-gray-200 my-2"></div> | ||
| <div className={`w-px bg-gray-200 transition-all duration-300 ${isFullPanelOpen ? 'my-2' : 'my-2'}`}></div> |
There was a problem hiding this comment.
The conditional expressions for both dividers are identical (isFullPanelOpen ? 'my-2' : 'my-2'), which means they always apply my-2 regardless of the panel state. If different spacing is needed based on panel state, the condition should be updated. Otherwise, the ternary operator should be removed and just use my-2 directly.
|
|
||
| {/* Divider */} | ||
| <div className="w-px bg-gray-200 my-2"></div> | ||
| <div className={`w-px bg-gray-200 transition-all duration-300 ${isFullPanelOpen ? 'my-2' : 'my-2'}`}></div> |
There was a problem hiding this comment.
The conditional expression is identical to line 97 (isFullPanelOpen ? 'my-2' : 'my-2'), which means it always applies my-2 regardless of the panel state. If different spacing is needed based on panel state, the condition should be updated. Otherwise, the ternary operator should be removed and just use my-2 directly.
|
|
||
| return ( | ||
| <nav className="md:hidden fixed bottom-0 left-0 right-0 z-50 pb-4 pt-2 px-3 flex items-center gap-3 bg-gradient-to-t from-white via-white to-transparent"> | ||
| <nav className={`md:hidden fixed bottom-0 left-0 right-0 z-50 px-3 flex items-center gap-2 bg-gradient-to-t from-white via-white to-transparent transition-all duration-300 ${isFullPanelOpen ? 'pb-2 pt-1' : 'pb-4 pt-2 gap-3'}`}> |
There was a problem hiding this comment.
The gap-2 class is specified in both the base classes and conditionally applied when !isFullPanelOpen. This creates redundancy - when the panel is closed, gap-2 would be applied, but then gap-3 is also added, which overrides it. The gap-2 should be removed from the base classes to avoid confusion.
| <nav className={`md:hidden fixed bottom-0 left-0 right-0 z-50 px-3 flex items-center gap-2 bg-gradient-to-t from-white via-white to-transparent transition-all duration-300 ${isFullPanelOpen ? 'pb-2 pt-1' : 'pb-4 pt-2 gap-3'}`}> | |
| <nav className={`md:hidden fixed bottom-0 left-0 right-0 z-50 px-3 flex items-center bg-gradient-to-t from-white via-white to-transparent transition-all duration-300 ${isFullPanelOpen ? 'pb-2 pt-1 gap-2' : 'pb-4 pt-2 gap-3'}`}> |
Enhance the mobile user interface by making the navbar more compact and improving the dragging functionality for panels. Resized various UI elements for better compactness and usability on mobile devices.