Skip to content

Feat/implement dashboard v0#6

Merged
damnthonyy merged 7 commits intodevelopfrom
feat/implement-dashboard-v0
Mar 15, 2026
Merged

Feat/implement dashboard v0#6
damnthonyy merged 7 commits intodevelopfrom
feat/implement-dashboard-v0

Conversation

@damnthonyy
Copy link
Copy Markdown
Member

@damnthonyy damnthonyy commented Mar 14, 2026

PR Type

feature

Summary

Dashboard v0 for Robocoop: UI components and main dashboard screen.

Description

  • Context: First version of the robot control dashboard (manual control, camera, tasks, metrics/alerts, battery).
  • What: UI components (button, card, badge, slider, switch, tabs, etc.) and dashboard modules from the example, theme in globals.css, accessibility and typing fixes (readonly props, carousel section/aria-label, context useMemo, ComponentRef).
  • How to test: pnpm dev → check header, camera, manual control, task/metrics/alert tabs, battery chart.

What's Changed

  • UI and dashboard components added
  • Main dashboard page and theme (globals.css)
  • Accessibility and type fixes; lint clean

Screen

Capture d’écran 2026-03-14 à 02 53 22

Will

Relates to #5


Closes #5

@damnthonyy damnthonyy added the feature new functionality label Mar 14, 2026
@damnthonyy
Copy link
Copy Markdown
Member Author

/review

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Mar 14, 2026

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Carousel reInit leak🐞 Bug ⛯ Reliability
Description
Carousel subscribes to Embla’s reInit event but never unsubscribes it, so handlers can
accumulate and onSelect can fire multiple times over the component’s lifetime. This can degrade
performance and lead to duplicated state updates.
Code

src/components/ui/carousel.tsx[R96-104]

+  React.useEffect(() => {
+    if (!api) return;
+    onSelect(api);
+    api.on('reInit', onSelect);
+    api.on('select', onSelect);
+
+    return () => {
+      api?.off('select', onSelect);
+    };
Evidence
The effect registers both reInit and select listeners, but the cleanup only removes the select
listener, leaving reInit subscribed.

src/components/ui/carousel.tsx[96-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Carousel` registers an Embla `reInit` listener but does not remove it during cleanup. Over time (re-mounts, api changes, re-inits), this can accumulate listeners and trigger duplicated `onSelect` calls.
### Issue Context
The effect subscribes to two events (`reInit`, `select`) but only unsubscribes one (`select`).
### Fix Focus Areas
- src/components/ui/carousel.tsx[96-105]
### Expected fix
Update the cleanup to also call `api?.off('reInit', onSelect)` (and keep the `select` unsubscription).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. CardTitle ref type wrong 🐞 Bug ✓ Correctness
Description
CardTitle forwards a ref typed as HTMLParagraphElement but renders an ``, making the forwarded
ref type incorrect for consumers and breaking type-safety for ref usage.
Code

src/components/ui/card.tsx[R32-38]

+const CardTitle = React.forwardRef<
+  HTMLParagraphElement,
+  React.HTMLAttributes<HTMLHeadingElement>
+>(({ className, ...props }, ref) => (
+  <h3
+    ref={ref}
+    className={cn(
Evidence
The component declares CardTitle with a paragraph-element ref type while attaching that ref to an
h3 heading element, so any consumer using the forwarded ref will receive the wrong element type.

src/components/ui/card.tsx[32-44]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CardTitle` is declared with a forwarded ref type of `HTMLParagraphElement` but renders an `&amp;amp;lt;h3&amp;amp;gt;` element. This makes the ref type incorrect for consumers and breaks ref type-safety.
## Issue Context
`CardTitle` is part of the shared UI primitives and may be used with refs across the app.
## Fix Focus Areas
- src/components/ui/card.tsx[32-44]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Icon buttons unlabeled 🐞 Bug ✓ Correctness
Description
ManualControl renders multiple icon-only `` controls (arrows/power) without an accessible name (no
aria-label or visually-hidden text), so assistive technologies can’t determine their purpose. This
breaks basic keyboard/screen-reader usability of manual controls.
Code

src/components/dashboard/manual-control.tsx[R70-108]

+        <div className="grid grid-cols-3 gap-2 pt-4 w-48 mx-auto">
+          <div />
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <ArrowUp className="h-6 w-6" />
+          </Button>
+          <div />
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <ArrowLeft className="h-6 w-6" />
+          </Button>
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <Power className="h-6 w-6" />
+          </Button>
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <ArrowRight className="h-6 w-6" />
+          </Button>
+          <div />
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <ArrowDown className="h-6 w-6" />
+          </Button>
Evidence
The directional/power buttons contain only icon components (no text), and no aria-label is
provided; the Button component forwards props so adding aria-label (or sr-only text) will fix the
accessible name.

src/components/dashboard/manual-control.tsx[70-108]
src/components/ui/button.tsx[40-49]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The manual control directional/power buttons are icon-only and currently lack an accessible name, making them unusable for screen-reader users.
### Issue Context
These buttons render only Lucide icons and do not pass `aria-label` or include visually hidden text.
### Fix Focus Areas
- src/components/dashboard/manual-control.tsx[70-108]
### Expected fix
Add `aria-label` per control (e.g., &amp;quot;Avancer&amp;quot;, &amp;quot;Reculer&amp;quot;, &amp;quot;Gauche&amp;quot;, &amp;quot;Droite&amp;quot;, &amp;quot;Stop&amp;quot;) or include an `sr-only` text node inside each button.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Tooltip hides zero values 🐞 Bug ✓ Correctness
Description
ChartTooltipContent only renders the numeric value when item.value is truthy, so valid 0
values are omitted from the tooltip output.
Code

src/components/ui/chart.tsx[R235-239]

+                    {item.value && (
+                      <span className="text-foreground font-mono font-medium tabular-nums">
+                        {item.value.toLocaleString()}
+                      </span>
+                    )}
Evidence
The tooltip uses a truthiness check ({item.value && ...}), which evaluates to false when
item.value is 0, preventing display of legitimate zero values.

src/components/ui/chart.tsx[229-239]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The chart tooltip hides valid `0` values because it uses a truthiness check (`item.value &amp;amp;amp;&amp;amp;amp; ...`).
## Issue Context
This affects `ChartTooltipContent` display only (tooltip output), but it can mislead users when a series legitimately reaches zero.
## Fix Focus Areas
- src/components/ui/chart.tsx[235-239]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment thread src/components/ui/card.tsx
@damnthonyy
Copy link
Copy Markdown
Member Author

/improve

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Mar 14, 2026

Persistent review updated to latest commit daaa909

Comment thread src/components/ui/carousel.tsx
Comment thread src/components/dashboard/task-manager.tsx
@KelianHalleray KelianHalleray self-requested a review March 15, 2026 10:06
@damnthonyy damnthonyy marked this pull request as ready for review March 15, 2026 13:22
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Dashboard v0: Complete UI component library and robot control dashboard

✨ Enhancement

Grey Divider

Walkthroughs

Description
• **Complete UI component library**: 50+ reusable UI components built with Radix UI, Recharts, and
  other libraries (buttons, cards, forms, dialogs, menus, navigation, etc.)
• **Dashboard v0 implementation**: Main dashboard page with integrated modules for robot control
  (manual control, camera feed, task management, metrics/alerts)
• **Design system**: Comprehensive theme with CSS custom properties, color palette (primary,
  secondary, destructive, success, warning), and Tailwind configuration
• **Robot control features**: Manual control module with autonomy toggle, speed slider, directional
  buttons, and emergency stop; task manager with delivery/guidance tabs; metrics and alerts display
  with battery chart
• **Responsive design**: Mobile detection hook, sidebar with mobile sheet integration, responsive
  grid layouts
• **Accessibility improvements**: ARIA labels, keyboard navigation, semantic HTML, proper form
  handling with react-hook-form
• **Dependencies**: Added 40+ packages for UI components, form handling, animations, and charting
• **Build improvements**: Updated lint scripts and ESLint configuration
Diagram
flowchart LR
  A["UI Components<br/>50+ components"] --> B["Dashboard Page"]
  C["Design System<br/>Theme & tokens"] --> B
  D["Dashboard Modules<br/>Manual Control<br/>Camera Feed<br/>Task Manager<br/>Metrics/Alerts"] --> B
  E["Dependencies<br/>Radix UI, Recharts<br/>react-hook-form"] --> A
  E --> D
  B --> F["Robot Control<br/>Interface"]
Loading

Grey Divider

File Changes

1. src/components/ui/use-mobile.ts ✨ Enhancement +21/-0

Mobile detection hook for responsive layouts

• New hook useIsMobile() that detects mobile viewport using media queries
• Tracks window width against 768px breakpoint
• Returns boolean state with event listener cleanup

src/components/ui/use-mobile.ts


2. src/lib/utils.ts ✨ Enhancement +7/-0

Class name merging utility function

• New utility function cn() for merging Tailwind CSS classes
• Combines clsx and tailwind-merge for conflict resolution
• Follows shadcn pattern for class composition

src/lib/utils.ts


3. src/app/globals.css ⚙️ Configuration changes +63/-2

Design system theme and color tokens

• Expanded CSS custom properties with comprehensive design tokens
• Added color palette (primary, secondary, destructive, success, warning)
• Added dashboard-specific tokens and chart colors
• Configured Tailwind theme mappings for colors and border radius

src/app/globals.css


View more (61)
4. src/components/ui/sidebar.tsx ✨ Enhancement +724/-0

Comprehensive sidebar navigation component

• Complete sidebar component system with 20+ sub-components
• Supports multiple variants (sidebar, floating, inset) and collapsible modes
• Includes mobile responsiveness with Sheet integration
• Context-based state management for sidebar open/closed state
• Keyboard shortcut support (Cmd/Ctrl+B)

src/components/ui/sidebar.tsx


5. src/components/ui/chart.tsx ✨ Enhancement +353/-0

Recharts wrapper with theming support

• Chart container component wrapping Recharts library
• Dynamic CSS variable injection for theme-aware colors
• Tooltip and legend content components with customization
• Helper function for payload configuration extraction

src/components/ui/chart.tsx


6. src/components/ui/menubar.tsx ✨ Enhancement +276/-0

Menubar UI component with Radix integration

• Menubar component system based on Radix UI primitives
• Supports menu items, checkboxes, radio groups, and submenus
• Includes separators, labels, and keyboard shortcuts
• Destructive variant support for menu items

src/components/ui/menubar.tsx


7. src/components/ui/context-menu.tsx ✨ Enhancement +252/-0

Context menu component with Radix UI

• Context menu component system using Radix UI primitives
• Supports nested submenus, checkboxes, and radio items
• Includes separators, labels, and keyboard shortcuts
• Destructive variant for menu items

src/components/ui/context-menu.tsx


8. src/components/ui/dropdown-menu.tsx ✨ Enhancement +257/-0

Dropdown menu component system

• Dropdown menu component system based on Radix UI
• Supports groups, checkboxes, radio items, and submenus
• Includes separators, labels, and keyboard shortcuts
• Destructive variant support

src/components/ui/dropdown-menu.tsx


9. src/components/ui/navigation-menu.tsx ✨ Enhancement +168/-0

Navigation menu with Radix UI

• Navigation menu component using Radix UI primitives
• Supports viewport-based and non-viewport layouts
• Includes trigger, content, links, and indicator components
• Animated transitions and keyboard navigation

src/components/ui/navigation-menu.tsx


10. src/components/ui/carousel.tsx ✨ Enhancement +253/-0

Carousel component with Embla integration

• Carousel component using Embla Carousel library
• Supports horizontal and vertical orientations
• Includes previous/next navigation buttons with disabled states
• Keyboard arrow key navigation support

src/components/ui/carousel.tsx


11. src/components/ui/select.tsx ✨ Enhancement +185/-0

Select dropdown component

• Select dropdown component based on Radix UI primitives
• Supports groups, labels, separators, and scroll buttons
• Includes size variants (sm, default)
• Accessible with keyboard navigation

src/components/ui/select.tsx


12. src/components/ui/command.tsx ✨ Enhancement +177/-0

Command palette component

• Command palette component using cmdk library
• Includes dialog wrapper, input, list, groups, and items
• Search functionality with icon
• Keyboard shortcuts support

src/components/ui/command.tsx


13. src/components/ui/drawer.tsx ✨ Enhancement +132/-0

Drawer/modal component with Vaul

• Drawer component using Vaul library
• Supports multiple directions (top, bottom, left, right)
• Includes overlay, header, footer, and close button
• Animated transitions with direction-specific styling

src/components/ui/drawer.tsx


14. src/components/ui/sheet.tsx ✨ Enhancement +139/-0

Sheet side panel component

• Sheet component based on Radix UI dialog primitives
• Supports four directions (top, bottom, left, right)
• Includes overlay, header, footer, and close button
• Animated slide transitions

src/components/ui/sheet.tsx


15. src/components/dashboard/task-manager.tsx ✨ Enhancement +141/-0

Robot task management dashboard component

• Task manager component for robot task assignment
• Supports delivery and guidance task types with tabs
• Active task status display with progress animation
• Start/stop task controls with autonomous mode check

src/components/dashboard/task-manager.tsx


16. src/components/dashboard/metrics-and-alerts.tsx ✨ Enhancement +132/-0

Dashboard metrics and alerts display

• Metrics and alerts dashboard component
• Displays recent alerts with icons and timestamps
• Battery vs activity area chart using Recharts
• Summary cards for daily missions and distance metrics

src/components/dashboard/metrics-and-alerts.tsx


17. package.json Dependencies +49/-5

Dependencies and build script updates

• Updated lint scripts to use eslint directly instead of next lint
• Added 40+ dependencies for UI components (Radix UI, Recharts, etc.)
• Added form handling, animation, and utility libraries
• Reorganized devDependencies for clarity

package.json


18. src/components/ui/form.tsx ✨ Enhancement +168/-0

Form components with react-hook-form integration

• New form component wrapper using react-hook-form and Radix UI primitives
• Exports Form, FormField, FormItem, FormLabel, FormControl, FormDescription,
 FormMessage components
• Includes context-based field state management with useFormField hook
• Provides accessibility features with proper ARIA attributes and error handling

src/components/ui/form.tsx


19. src/components/ui/alert-dialog.tsx ✨ Enhancement +157/-0

Alert dialog UI component with Radix primitives

• New alert dialog component built on Radix UI primitives
• Exports composable subcomponents: AlertDialog, AlertDialogTrigger, AlertDialogContent,
 AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription,
 AlertDialogAction, AlertDialogCancel
• Includes animations and overlay styling
• Action and cancel buttons with predefined variants

src/components/ui/alert-dialog.tsx


20. src/components/ui/dialog.tsx ✨ Enhancement +135/-0

Dialog modal component with Radix primitives

• New dialog/modal component built on Radix UI primitives
• Exports composable subcomponents: Dialog, DialogTrigger, DialogContent, DialogHeader,
 DialogFooter, DialogTitle, DialogDescription
• Includes close button with icon and animations
• Portal-based rendering with overlay

src/components/ui/dialog.tsx


21. src/components/dashboard/manual-control.tsx ✨ Enhancement +122/-0

Manual robot control dashboard module

• New manual control dashboard module for robot control
• Features autonomy mode toggle, speed slider, directional buttons (up/down/left/right), and
 emergency stop button
• Buttons disabled when in autonomous mode
• Uses Switch, Slider, and Button UI components

src/components/dashboard/manual-control.tsx


22. src/components/ui/pagination.tsx ✨ Enhancement +127/-0

Pagination navigation component

• New pagination component with navigation controls
• Exports Pagination, PaginationContent, PaginationItem, PaginationLink,
 PaginationPrevious, PaginationNext, PaginationEllipsis
• Includes accessibility features with ARIA labels and semantic navigation
• Supports active state styling

src/components/ui/pagination.tsx


23. src/components/ui/calendar.tsx ✨ Enhancement +75/-0

Calendar date picker component

• New calendar component using react-day-picker library
• Customizable styling with Tailwind classes for months, days, navigation
• Supports range selection and outside day display
• Includes navigation buttons with chevron icons

src/components/ui/calendar.tsx


24. src/components/dashboard/dashboard.tsx ✨ Enhancement +77/-0

Main dashboard page component

• Main dashboard component orchestrating all dashboard modules
• Manages state for autonomous mode, speed, and active tasks
• Integrates Header, CameraFeed, ManualControl, TaskManager, MetricsAndAlerts components
• Includes toast notifications for task events and emergency stop
• Responsive grid layout with Tailwind CSS

src/components/dashboard/dashboard.tsx


25. src/components/ui/table.tsx ✨ Enhancement +116/-0

Table data display component

• New table component with semantic HTML structure
• Exports Table, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell,
 TableCaption
• Includes hover states and responsive overflow handling
• Proper styling for data display

src/components/ui/table.tsx


26. src/components/ui/breadcrumb.tsx ✨ Enhancement +109/-0

Breadcrumb navigation component

• New breadcrumb navigation component
• Exports Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage,
 BreadcrumbSeparator, BreadcrumbEllipsis
• Includes accessibility with ARIA labels and semantic structure
• Supports custom separators and ellipsis for long paths

src/components/ui/breadcrumb.tsx


27. src/components/ui/input-otp.tsx ✨ Enhancement +77/-0

OTP input component

• New OTP (One-Time Password) input component using input-otp library
• Exports InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator
• Includes animated caret and active state styling
• Supports disabled state and error validation

src/components/ui/input-otp.tsx


28. src/components/ui/card.tsx ✨ Enhancement +82/-0

Card container component

• New card component with subcomponents for layout
• Exports Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter
• Uses forwardRef for ref forwarding
• Includes white background and border styling

src/components/ui/card.tsx


29. src/components/ui/resizable.tsx ✨ Enhancement +56/-0

Resizable panel layout component

• New resizable panel component using react-resizable-panels library
• Exports ResizablePanelGroup, ResizablePanel, ResizableHandle
• Supports vertical and horizontal layouts with drag handles
• Optional grip icon for visual feedback

src/components/ui/resizable.tsx


30. src/components/ui/accordion.tsx ✨ Enhancement +66/-0

Accordion collapsible component

• New accordion component using Radix UI primitives
• Exports Accordion, AccordionItem, AccordionTrigger, AccordionContent
• Includes chevron icon animation and smooth transitions
• Supports keyboard navigation and accessibility

src/components/ui/accordion.tsx


31. src/components/ui/toggle-group.tsx ✨ Enhancement +73/-0

Toggle group button component

• New toggle group component for grouped toggle buttons
• Exports ToggleGroup, ToggleGroupItem
• Uses context to manage variant and size across items
• Supports outline variant with proper border styling

src/components/ui/toggle-group.tsx


32. src/components/ui/tooltip.tsx ✨ Enhancement +61/-0

Tooltip component with Radix primitives

• New tooltip component using Radix UI primitives
• Exports Tooltip, TooltipTrigger, TooltipContent, TooltipProvider
• Includes animations and arrow pointer
• Configurable delay duration and positioning

src/components/ui/tooltip.tsx


33. src/components/ui/alert.tsx ✨ Enhancement +66/-0

Alert notification component

• New alert component with variants (default, destructive)
• Exports Alert, AlertTitle, AlertDescription
• Supports icon display with grid layout
• Includes CSS variables for spacing and icon sizing

src/components/ui/alert.tsx


34. src/components/ui/button.tsx ✨ Enhancement +54/-0

Button component with variants

• New button component with multiple variants and sizes
• Exports Button, buttonVariants
• Supports variants: default, destructive, outline, secondary, ghost, link
• Includes sizes: default, sm, lg, icon with proper styling

src/components/ui/button.tsx


35. src/components/dashboard/header.tsx ✨ Enhancement +52/-0

Dashboard header with status indicators

• New dashboard header component displaying robot status
• Shows logo, robot name, connection status, battery level, and autonomy mode badge
• Uses Badge component for status indication
• Sticky positioning with responsive layout

src/components/dashboard/header.tsx


36. src/components/ui/tabs.tsx ✨ Enhancement +53/-0

Tabs navigation component

• New tabs component using Radix UI primitives
• Exports Tabs, TabsList, TabsTrigger, TabsContent
• Includes active state styling and smooth transitions
• Supports keyboard navigation

src/components/ui/tabs.tsx


37. src/components/ui/slider.tsx ✨ Enhancement +53/-0

Slider input component

• New slider component using Radix UI primitives
• Exports Slider, SliderTrack, SliderThumb
• Includes range display and disabled state styling
• Touch-friendly with proper focus states

src/components/ui/slider.tsx


38. src/components/ui/popover.tsx ✨ Enhancement +48/-0

Popover floating component

• New popover component using Radix UI primitives
• Exports Popover, PopoverTrigger, PopoverContent, PopoverAnchor
• Includes animations and portal rendering
• Configurable alignment and offset

src/components/ui/popover.tsx


39. src/components/ui/toggle.tsx ✨ Enhancement +47/-0

Toggle button component

• New toggle button component using Radix UI primitives
• Exports Toggle, toggleVariants
• Supports variants: default, outline with multiple sizes
• Includes on/off state styling and transitions

src/components/ui/toggle.tsx


40. src/components/ui/scroll-area.tsx ✨ Enhancement +58/-0

Scroll area component

• New scroll area component using Radix UI primitives
• Exports ScrollArea, ScrollBar
• Supports vertical and horizontal scrolling
• Includes custom scrollbar styling with thumb

src/components/ui/scroll-area.tsx


41. src/components/ui/hover-card.tsx ✨ Enhancement +44/-0

Hover card component

• New hover card component using Radix UI primitives
• Exports HoverCard, HoverCardTrigger, HoverCardContent
• Includes animations and portal rendering
• Configurable alignment and offset

src/components/ui/hover-card.tsx


42. src/components/dashboard/camera-feed.tsx ✨ Enhancement +38/-0

Camera feed dashboard module

• New camera feed dashboard module
• Displays simulated video feed with recording indicator
• Shows crosshair overlay and monitoring/live feed badge
• Responsive aspect ratio with dark background

src/components/dashboard/camera-feed.tsx


43. src/components/ui/radio-group.tsx ✨ Enhancement +45/-0

Radio group selection component

• New radio group component using Radix UI primitives
• Exports RadioGroup, RadioGroupItem
• Includes filled circle indicator for selected state
• Supports disabled state and accessibility features

src/components/ui/radio-group.tsx


44. src/components/ui/badge.tsx ✨ Enhancement +40/-0

Badge status indicator component

• New badge component with multiple variants
• Exports Badge, badgeVariants
• Supports variants: default, secondary, destructive, outline, success, warning
• Inline display with rounded styling

src/components/ui/badge.tsx


45. src/components/ui/checkbox.tsx ✨ Enhancement +32/-0

Checkbox input component

• New checkbox component using Radix UI primitives
• Exports Checkbox
• Includes checked state with icon indicator
• Supports disabled state and error validation

src/components/ui/checkbox.tsx


46. src/components/ui/avatar.tsx ✨ Enhancement +53/-0

Avatar image component

• New avatar component using Radix UI primitives
• Exports Avatar, AvatarImage, AvatarFallback
• Circular display with fallback support
• Responsive sizing with overflow handling

src/components/ui/avatar.tsx


47. src/components/ui/switch.tsx ✨ Enhancement +27/-0

Switch toggle component

• New switch toggle component using Radix UI primitives
• Exports Switch
• Includes animated thumb with checked/unchecked states
• Supports disabled state and focus ring styling

src/components/ui/switch.tsx


48. src/components/ui/input.tsx ✨ Enhancement +23/-0

Text input component

• New input field component
• Exports Input with InputProps type
• Includes file input styling and placeholder support
• Focus ring and disabled state styling

src/components/ui/input.tsx


49. src/components/ui/collapsible.tsx ✨ Enhancement +33/-0

Collapsible content component

• New collapsible component using Radix UI primitives
• Exports Collapsible, CollapsibleTrigger, CollapsibleContent
• Supports open/closed state management
• Minimal wrapper around Radix primitives

src/components/ui/collapsible.tsx


50. src/components/ui/progress.tsx ✨ Enhancement +31/-0

Progress bar component

• New progress bar component using Radix UI primitives
• Exports Progress
• Displays progress with animated indicator
• Supports custom value and styling

src/components/ui/progress.tsx


51. src/components/ui/label.tsx ✨ Enhancement +24/-0

Label form component

• New label component using Radix UI primitives
• Exports Label, labelVariants
• Includes disabled state styling
• Proper typography and spacing

src/components/ui/label.tsx


52. src/components/ui/textarea.tsx ✨ Enhancement +18/-0

Textarea input component

• New textarea component for multi-line text input
• Exports Textarea
• Includes field-sizing-content for dynamic height
• Focus ring and disabled state styling

src/components/ui/textarea.tsx


53. src/components/ui/separator.tsx ✨ Enhancement +28/-0

Separator divider component

• New separator component using Radix UI primitives
• Exports Separator
• Supports horizontal and vertical orientations
• Decorative or semantic rendering

src/components/ui/separator.tsx


54. src/components/ui/sonner.tsx ✨ Enhancement +25/-0

Toast notification component

• New toast notification wrapper using sonner library
• Exports Toaster component
• Integrates with next-themes for theme support
• Customizable styling with CSS variables

src/components/ui/sonner.tsx


55. src/app/page.tsx ✨ Enhancement +3/-7

Main page now renders dashboard

• Replaced placeholder content with Dashboard component import
• Simplified page to render main dashboard
• Removed previous test layout structure

src/app/page.tsx


56. eslint.config.mjs ⚙️ Configuration changes +2/-0

ESLint configuration ignore patterns

• Added coverage/** to eslint ignore patterns
• Added Remote Robot Control Dashboard/** to eslint ignore patterns

eslint.config.mjs


57. src/components/ui/skeleton.tsx +13/-0

Skeleton loading component

• New skeleton loading component
• Exports Skeleton
• Animated pulse effect for loading states
• Customizable styling

src/components/ui/skeleton.tsx


58. .prettierrc Additional files +2/-1

...

.prettierrc


59. pnpm-lock.yaml Additional files +2237/-148

...

pnpm-lock.yaml


60. sonar-project.properties Additional files +1/-0

...

sonar-project.properties


61. src/components/dashboard/.gitkeep Additional files +0/-0

...

src/components/dashboard/.gitkeep


62. src/components/ui/.gitkeep Additional files +0/-0

...

src/components/ui/.gitkeep


63. src/components/ui/aspect-ratio.tsx Additional files +11/-0

...

src/components/ui/aspect-ratio.tsx


64. tsconfig.json Additional files +1/-1

...

tsconfig.json


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Mar 15, 2026

Code Review by Qodo

🐞 Bugs (7) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Button implicit submit type 🐞 Bug ✓ Correctness ⭐ New
Description
Button renders a native <button> without setting type, so when used inside a <form> it
defaults to submit and can trigger unintended form submissions. This can cause incorrect
navigation/data submission when buttons are intended to be non-submitting UI controls.
Code

src/components/ui/button.tsx[R40-48]

+const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
+  ({ className, variant, size, asChild = false, ...props }, ref) => {
+    const Comp = asChild ? Slot : 'button';
+    return (
+      <Comp
+        className={cn(buttonVariants({ variant, size, className }))}
+        ref={ref}
+        {...props}
+      />
Evidence
The shared Button component chooses 'button' when asChild is false, but never sets a default
type attribute before spreading props, so callers that don’t explicitly pass type="button" will
get the platform default behavior inside forms.

src/components/ui/button.tsx[40-48]
Best Practice: HTML button element default type

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The shared `Button` component renders a native `&lt;button&gt;` without a default `type`, which can cause unintended form submissions.

### Issue Context
This component will be reused broadly; the safest default is `type=&quot;button&quot;` unless the user explicitly sets `type` (or uses `asChild`).

### Fix Focus Areas
- src/components/ui/button.tsx[40-48]

### Implementation notes
- When `Comp === &#x27;button&#x27;` and `props.type` is `undefined`, pass `type=&quot;button&quot;`.
- Preserve any explicit `type` passed by the caller.
- Do not set `type` when `asChild` is true (since the underlying element may not be a button).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Carousel reInit leak🐞 Bug ⛯ Reliability
Description
Carousel subscribes to Embla’s reInit event but never unsubscribes it, so handlers can
accumulate and onSelect can fire multiple times over the component’s lifetime. This can degrade
performance and lead to duplicated state updates.
Code

src/components/ui/carousel.tsx[R96-104]

+  React.useEffect(() => {
+    if (!api) return;
+    onSelect(api);
+    api.on('reInit', onSelect);
+    api.on('select', onSelect);
+
+    return () => {
+      api?.off('select', onSelect);
+    };
Evidence
The effect registers both reInit and select listeners, but the cleanup only removes the select
listener, leaving reInit subscribed.

src/components/ui/carousel.tsx[96-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Carousel` registers an Embla `reInit` listener but does not remove it during cleanup. Over time (re-mounts, api changes, re-inits), this can accumulate listeners and trigger duplicated `onSelect` calls.
### Issue Context
The effect subscribes to two events (`reInit`, `select`) but only unsubscribes one (`select`).
### Fix Focus Areas
- src/components/ui/carousel.tsx[96-105]
### Expected fix
Update the cleanup to also call `api?.off(&amp;amp;#x27;reInit&amp;amp;#x27;, onSelect)` (and keep the `select` unsubscription).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. CardTitle ref type wrong 🐞 Bug ✓ Correctness
Description
CardTitle forwards a ref typed as HTMLParagraphElement but renders an ``, making the forwarded
ref type incorrect for consumers and breaking type-safety for ref usage.
Code

src/components/ui/card.tsx[R32-38]

+const CardTitle = React.forwardRef<
+  HTMLParagraphElement,
+  React.HTMLAttributes<HTMLHeadingElement>
+>(({ className, ...props }, ref) => (
+  <h3
+    ref={ref}
+    className={cn(
Evidence
The component declares CardTitle with a paragraph-element ref type while attaching that ref to an
h3 heading element, so any consumer using the forwarded ref will receive the wrong element type.

src/components/ui/card.tsx[32-44]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CardTitle` is declared with a forwarded ref type of `HTMLParagraphElement` but renders an `&amp;amp;amp;lt;h3&amp;amp;amp;gt;` element. This makes the ref type incorrect for consumers and breaks ref type-safety.
## Issue Context
`CardTitle` is part of the shared UI primitives and may be used with refs across the app.
## Fix Focus Areas
- src/components/ui/card.tsx[32-44]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Chart CSS injection risk 🐞 Bug ⛨ Security ⭐ New
Description
ChartStyle interpolates id, config keys, and color values directly into a CSS string inserted
via dangerouslySetInnerHTML, so special characters in those values can break the style tag and
inject arbitrary CSS. This can lead to incorrect styling at best and a CSS-injection vector if any
of those fields are influenced by untrusted input.
Code

src/components/ui/chart.tsx[R81-100]

+  return (
+    <style
+      dangerouslySetInnerHTML={{
+        __html: Object.entries(THEMES)
+          .map(
+            ([theme, prefix]) => `
+${prefix} [data-chart=${id}] {
+${colorConfig
+  .map(([key, itemConfig]) => {
+    const color =
+      itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
+      itemConfig.color;
+    return color ? `  --color-${key}: ${color};` : null;
+  })
+  .join('\n')}
+}
+`
+          )
+          .join('\n'),
+      }}
Evidence
The <style> content is constructed via template literals and injected with
dangerouslySetInnerHTML, with id, key, and color inserted without escaping/quoting, which is
exactly the pattern that enables malformed CSS or injected rules when values contain CSS special
characters.

src/components/ui/chart.tsx[72-103]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`ChartStyle` uses `dangerouslySetInnerHTML` to inject a `&lt;style&gt;` tag built from `id` and `config` values without escaping/quoting, which can produce malformed CSS and enables CSS injection.

### Issue Context
Even if current call sites use trusted values, this is a reusable UI primitive and should be safe by construction.

### Fix Focus Areas
- src/components/ui/chart.tsx[72-103]

### Implementation notes
Preferred:
- Replace the style-tag injection with setting CSS variables on the container element (`&lt;div data-chart=... style={{&#x27;--color-foo&#x27;: value}}&gt;`), avoiding HTML/CSS string construction.

If keeping `&lt;style&gt;`:
- Quote the attribute selector: `[data-chart=&quot;${escapedId}&quot;]`.
- Ensure `key` is restricted to a safe character set for CSS custom property names.
- Sanitize `color` to a safe CSS color format (or reject anything else).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Sidebar functional update stale 🐞 Bug ⛯ Reliability ⭐ New
Description
SidebarProvider accepts functional updates for setOpen, but evaluates them against the captured
open value (value(open)), so consecutive updates in the same tick don’t see each other’s result
and can drop transitions. This makes setOpen(prev => !prev) semantics unreliable compared to
React’s state updater behavior.
Code

src/components/ui/sidebar.tsx[R76-89]

+  const setOpen = React.useCallback(
+    (value: boolean | ((value: boolean) => boolean)) => {
+      const openState = typeof value === 'function' ? value(open) : value;
+      if (setOpenProp) {
+        setOpenProp(openState);
+      } else {
+        _setOpen(openState);
+      }
+
+      // This sets the cookie to keep the sidebar state.
+      document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
+    },
+    [setOpenProp, open]
+  );
Evidence
The implementation computes openState from the closure variable open rather than from the actual
previous state value provided by React’s internal state queue; it also advertises functional-updater
usage by calling setOpen((open) => !open) in toggleSidebar. This mismatch is what allows
multiple sequential updates to collapse into a single update.

src/components/ui/sidebar.tsx[72-95]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`setOpen` supports functional updaters but evaluates them using the captured `open` value, which can drop state transitions when multiple updates occur before a re-render.

### Issue Context
The component already uses `setOpen((open) =&gt; !open)` in `toggleSidebar`, so `setOpen` should preserve correct functional-update semantics.

### Fix Focus Areas
- src/components/ui/sidebar.tsx[72-95]

### Implementation notes
- For uncontrolled mode: call `_setOpen(prev =&gt; { const next = typeof value === &#x27;function&#x27; ? value(prev) : value; /* set cookie */; return next; })`.
- For controlled mode: consider either disallowing functional updaters (type-level) or applying the updater to `openProp` at call time with clear documentation; ensure cookie writing matches the final state.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Icon buttons unlabeled 🐞 Bug ✓ Correctness
Description
ManualControl renders multiple icon-only `` controls (arrows/power) without an accessible name (no
aria-label or visually-hidden text), so assistive technologies can’t determine their purpose. This
breaks basic keyboard/screen-reader usability of manual controls.
Code

src/components/dashboard/manual-control.tsx[R70-108]

+        <div className="grid grid-cols-3 gap-2 pt-4 w-48 mx-auto">
+          <div />
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <ArrowUp className="h-6 w-6" />
+          </Button>
+          <div />
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <ArrowLeft className="h-6 w-6" />
+          </Button>
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <Power className="h-6 w-6" />
+          </Button>
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <ArrowRight className="h-6 w-6" />
+          </Button>
+          <div />
+          <Button
+            variant="secondary"
+            className="h-12 w-full"
+            disabled={isAutonomous}
+          >
+            <ArrowDown className="h-6 w-6" />
+          </Button>
Evidence
The directional/power buttons contain only icon components (no text), and no aria-label is
provided; the Button component forwards props so adding aria-label (or sr-only text) will fix the
accessible name.

src/components/dashboard/manual-control.tsx[70-108]
src/components/ui/button.tsx[40-49]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The manual control directional/power buttons are icon-only and currently lack an accessible name, making them unusable for screen-reader users.
### Issue Context
These buttons render only Lucide icons and do not pass `aria-label` or include visually hidden text.
### Fix Focus Areas
- src/components/dashboard/manual-control.tsx[70-108]
### Expected fix
Add `aria-label` per control (e.g., &amp;amp;quot;Avancer&amp;amp;quot;, &amp;amp;quot;Reculer&amp;amp;quot;, &amp;amp;quot;Gauche&amp;amp;quot;, &amp;amp;quot;Droite&amp;amp;quot;, &amp;amp;quot;Stop&amp;amp;quot;) or include an `sr-only` text node inside each button.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
7. Tooltip hides zero values 🐞 Bug ✓ Correctness
Description
ChartTooltipContent only renders the numeric value when item.value is truthy, so valid 0
values are omitted from the tooltip output.
Code

src/components/ui/chart.tsx[R235-239]

+                    {item.value && (
+                      <span className="text-foreground font-mono font-medium tabular-nums">
+                        {item.value.toLocaleString()}
+                      </span>
+                    )}
Evidence
The tooltip uses a truthiness check ({item.value && ...}), which evaluates to false when
item.value is 0, preventing display of legitimate zero values.

src/components/ui/chart.tsx[229-239]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The chart tooltip hides valid `0` values because it uses a truthiness check (`item.value &amp;amp;amp;amp;&amp;amp;amp;amp; ...`).
## Issue Context
This affects `ChartTooltipContent` display only (tooltip output), but it can mislead users when a series legitimately reaches zero.
## Fix Focus Areas
- src/components/ui/chart.tsx[235-239]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@damnthonyy
Copy link
Copy Markdown
Member Author

@KelianHalleray im waiting for you to init the server for remove the first mock

@damnthonyy damnthonyy merged commit d3e692c into develop Mar 15, 2026
2 checks passed
@damnthonyy damnthonyy deleted the feat/implement-dashboard-v0 branch March 15, 2026 13:25
Comment on lines +40 to +48
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : 'button';
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Button implicit submit type 🐞 Bug ✓ Correctness

Button renders a native <button> without setting type, so when used inside a <form> it
defaults to submit and can trigger unintended form submissions. This can cause incorrect
navigation/data submission when buttons are intended to be non-submitting UI controls.
Agent Prompt
### Issue description
The shared `Button` component renders a native `<button>` without a default `type`, which can cause unintended form submissions.

### Issue Context
This component will be reused broadly; the safest default is `type="button"` unless the user explicitly sets `type` (or uses `asChild`).

### Fix Focus Areas
- src/components/ui/button.tsx[40-48]

### Implementation notes
- When `Comp === 'button'` and `props.type` is `undefined`, pass `type="button"`.
- Preserve any explicit `type` passed by the caller.
- Do not set `type` when `asChild` is true (since the underlying element may not be a button).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature new functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants