-
Notifications
You must be signed in to change notification settings - Fork 284
feat(ui): comprehensive design system improvements #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ui): comprehensive design system improvements #67
Conversation
📝 WalkthroughWalkthroughAdds class-based dark mode with a persistent toggle and localStorage persistence; migrates many components from hard-coded colors to a CSS-variable-driven design system, updates fonts, tokens, shadows, and extensive global styles and animations. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant App as App (React)
participant LS as localStorage
participant DOM as document.documentElement
User->>App: Click dark mode toggle
App->>App: set darkMode state
App->>LS: write DARK_MODE_KEY
App->>DOM: add/remove "dark" class
App-->>User: UI updates via CSS variables
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (8)
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used📓 Path-based instructions (2)ui/src/**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
ui/src/styles/**/*.css📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (6)📓 Common learnings📚 Learning: 2026-01-10T08:23:04.021ZApplied to files:
📚 Learning: 2026-01-10T08:23:04.021ZApplied to files:
📚 Learning: 2026-01-10T08:23:04.021ZApplied to files:
📚 Learning: 2026-01-10T08:23:04.021ZApplied to files:
📚 Learning: 2026-01-10T08:23:04.021ZApplied to files:
🔇 Additional comments (28)
✏️ Tip: You can disable this entire section by setting Comment |
This PR addresses 53 design issues identified in the UI codebase, implementing a more consistent and polished neobrutalism design system. Typography: - Improved font stacks with proper fallbacks - Added font smoothing for crisp text rendering Color/Theme: - Added neutral scale (50-900) for consistent grays - Added semantic log level colors with dark mode variants - Added category colors for feature cards - Added GLM badge color variable - Full dark mode support for all new variables Design Tokens: - Spacing scale (xs to 2xl) - Z-index scale (dropdown to toast) - Border radius tokens - Inset shadow variants Animations: - New transition timing variables - New easing curves (bounce, smooth, out-back) - Slide-in animations (top/bottom/left) - Bounce, shake, scale-pop animations - Stagger delay utilities - Enhanced YOLO fire effect with parallax layers Components: - Button size variants (sm/lg/icon) and loading state - Input variants (error/disabled/textarea) - Badge color and size variants - Card elevation variants (elevated/flat/sunken) - Progress bar shimmer animation - Stronger modal backdrop with blur - Neobrutalist tooltips - Enhanced empty state with striped pattern Component Fixes: - Replaced hardcoded colors with CSS variables - Fixed ProgressDashboard percentage alignment - Improved ChatMessage role-specific styling - Consistent category badge colors in FeatureModal - Improved step input styling in forms Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2dea199 to
501719f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In `@ui/src/components/ChatMessage.tsx`:
- Line 173: In ChatMessage component replace the unused Tailwind class on the
small status span: change the className fragment that currently uses
"bg-neo-accent" to use the arbitrary value syntax "bg-[var(--color-neo-accent)]"
(the span element with className "inline-block w-2 h-4 ... animate-pulse") so it
matches the other neo-* color usages and resolves the missing utility.
In `@ui/src/components/DebugLogViewer.tsx`:
- Around line 276-289: The getLogColor function maps the 'info' (and default)
LogLevel to the wrong CSS variable; update the return for the info/default
branch in getLogColor to use 'text-[var(--color-neo-log-info)]' instead of
'text-[var(--color-neo-log-success)]' so the info level uses the proper
--color-neo-log-info variable.
In `@ui/src/components/TerminalTabs.tsx`:
- Around line 168-169: Replace the incorrect background token
bg-neo-text-secondary used for hover states in the TerminalTabs component with
the semantic hover surface token neo-hover-subtle: update the inactive tab hover
class (currently 'bg-neo-text-secondary' in the TerminalTabs JSX) and the new
terminal button hover class (the other occurrence around the new-terminal button
render) to use 'bg-neo-hover-subtle' (or the equivalent class for
neo-hover-subtle in your utility naming) so hover uses the design-system subtle
surface token instead of a text color.
In `@ui/src/styles/globals.css`:
- Around line 550-565: The shimmer pseudo-element is attached to
.neo-progress-bar::after but the actual fill element is .neo-progress-fill, so
the animation never applies; update the CSS selector to target
.neo-progress-fill::after (or include both .neo-progress-bar::after,
.neo-progress-fill::after) and ensure the pseudo-element
positioning/background/animation rules remain the same so the shimmer is applied
to the fill element.
- Around line 310-327: The spinner is invisible because .neo-btn-loading sets
color: transparent which makes currentColor transparent for
.neo-btn-loading::after; change the spinner to use an explicit color (or CSS
variable) instead of currentColor — e.g., update .neo-btn-loading::after to use
border: 2px solid var(--neo-spinner-color, `#fff`) and border-right-color:
transparent (or pick the appropriate theme color), or alternatively move color:
transparent to a child text element so the button keeps its original color for
the ::after; modify the rules for .neo-btn-loading and .neo-btn-loading::after
accordingly to ensure the spinner border uses a visible color while the button
text remains hidden.
🧹 Nitpick comments (8)
ui/tsconfig.tsbuildinfo (1)
1-1: Remove auto-generated build artifact from version control.
tsconfig.tsbuildinfois an auto-generated TypeScript incremental build cache file. It should not be committed as it:
- Gets regenerated on every build
- Causes unnecessary merge conflicts
- Provides no value in the repository
Add it to
.gitignore:+ # TypeScript build info + *.tsbuildinfoThen remove the file from tracking:
git rm --cached ui/tsconfig.tsbuildinfoui/src/styles/globals.css (1)
362-444: Considerwill-changefor performance optimization on the fire effect.The YOLO button runs three concurrent animations with filters and pseudo-elements. On lower-end devices, this could cause jank. Adding
will-change: transform, filtercan hint the browser to optimize rendering.Optional optimization
.neo-btn-yolo { position: relative; + will-change: transform, filter; background: radial-gradient(ellipse at 20% 80%, rgba(255, 200, 0, 0.4) 0%, transparent 50%),ui/src/components/AddFeatureForm.tsx (1)
169-175: Consider extracting the step badge to a reusable utility class.The step number badge styling looks good and aligns with the neobrutalism design. However, note that the inline
style={{ boxShadow: 'var(--shadow-neo-sm)' }}is used because Tailwind doesn't natively support CSS variable shadows.If this pattern is used elsewhere (e.g., EditFeatureForm), consider defining a utility class like
.neo-step-badgein globals.css to avoid duplication.ui/src/components/FeatureModal.tsx (1)
7-25: ExtractgetCategoryColorto a shared utility to avoid duplication.The comment on line 7 acknowledges this matches the FeatureCard pattern, indicating duplicated code. Consider extracting this function to a shared utility (e.g.,
ui/src/lib/utils.tsor a dedicatedcolors.ts).Additionally, the hardcoded hex colors here diverge from the CSS variable approach used elsewhere in this PR. Consider defining these as CSS variables (e.g.,
--color-neo-category-1through--color-neo-category-7) in globals.css to maintain consistency with the design system.♻️ Suggested extraction
Create a shared utility:
// ui/src/lib/categoryColors.ts const CATEGORY_COLORS = [ 'var(--color-neo-category-pink)', 'var(--color-neo-category-cyan)', 'var(--color-neo-category-green)', 'var(--color-neo-category-yellow)', 'var(--color-neo-category-orange)', 'var(--color-neo-category-purple)', 'var(--color-neo-category-blue)', ] as const export function getCategoryColor(category: string): string { let hash = 0 for (let i = 0; i < category.length; i++) { hash = category.charCodeAt(i) + ((hash << 5) - hash) } return CATEGORY_COLORS[Math.abs(hash) % CATEGORY_COLORS.length] }Then import and use in both FeatureCard and FeatureModal.
ui/src/App.tsx (1)
9-10: Consider grouping constants together for better code organization.The
DARK_MODE_KEYconstant is declared betweenSTORAGE_KEYand the component imports. Consider grouping both constants either before or after all imports for consistency.Suggested organization
import { useState, useEffect, useCallback } from 'react' import { useQueryClient } from '@tanstack/react-query' import { useProjects, useFeatures, useAgentStatus, useSettings } from './hooks/useProjects' import { useProjectWebSocket } from './hooks/useWebSocket' import { useFeatureSound } from './hooks/useFeatureSound' import { useCelebration } from './hooks/useCelebration' - -const STORAGE_KEY = 'autocoder-selected-project' -const DARK_MODE_KEY = 'autocoder-dark-mode' import { ProjectSelector } from './components/ProjectSelector' import { KanbanBoard } from './components/KanbanBoard' // ... other imports ... import { Loader2, Settings, Moon, Sun } from 'lucide-react' import type { Feature } from './lib/types' + +const STORAGE_KEY = 'autocoder-selected-project' +const DARK_MODE_KEY = 'autocoder-dark-mode' function App() {ui/src/components/ChatMessage.tsx (1)
163-163: Inconsistent class naming pattern.Line 163 uses
text-neo-text-secondary(Tailwind utility) while line 193 usestext-[var(--color-neo-text-secondary)](arbitrary value syntax). Consider using a consistent approach throughout the component for maintainability.Suggested fix for consistency
- <span className="text-xs text-neo-text-secondary block mt-1 text-center"> + <span className="text-xs text-[var(--color-neo-text-secondary)] block mt-1 text-center">ui/src/components/NewProjectModal.tsx (1)
318-326: Redundantneo-cardclass alongside explicit styling.The button elements include both the
neo-cardclass and explicit border/background declarations (border-3 border-[var(--color-neo-border)] bg-[var(--color-neo-card)]). Ifneo-cardalready defines these properties, this creates redundancy; if it defines different values, there may be specificity conflicts.Consider removing either the
neo-cardclass or the explicit declarations to keep styling maintainable.♻️ Suggested simplification
className=" w-full text-left p-4 - border-3 border-[var(--color-neo-border)] - bg-[var(--color-neo-card)] hover:translate-x-[-2px] hover:translate-y-[-2px] transition-all duration-150 disabled:opacity-50 disabled:cursor-not-allowed neo-card "Or alternatively, remove
neo-cardand keep explicit declarations for full control.Also applies to: 353-361
ui/src/components/QuestionOptions.tsx (1)
134-146: Consider extracting duplicated hover shadow logic.The
onMouseEnter/onMouseLeavehandlers for shadow transitions are duplicated between the regular options and the "Other" option. This adds complexity and could be simplified.Options to consider:
- Extract to a custom hook or helper function
- Use CSS-only approach with
hover:shadow-[var(--shadow-neo-lg)]if Tailwind supports it- Create a reusable
OptionButtoncomponent♻️ Example: Extract hover handlers
// Helper for shadow hover behavior const getShadowHandlers = (isSelected: boolean, disabled: boolean) => ({ style: { boxShadow: isSelected ? 'var(--shadow-neo-sm)' : 'var(--shadow-neo-md)', }, onMouseEnter: (e: React.MouseEvent<HTMLButtonElement>) => { if (!isSelected && !disabled) { e.currentTarget.style.boxShadow = 'var(--shadow-neo-lg)' } }, onMouseLeave: (e: React.MouseEvent<HTMLButtonElement>) => { if (!isSelected && !disabled) { e.currentTarget.style.boxShadow = 'var(--shadow-neo-md)' } }, })Also applies to: 190-202
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (25)
ui/src/App.tsxui/src/components/AddFeatureForm.tsxui/src/components/AssistantChat.tsxui/src/components/AssistantFAB.tsxui/src/components/AssistantPanel.tsxui/src/components/ChatMessage.tsxui/src/components/ConfirmDialog.tsxui/src/components/DebugLogViewer.tsxui/src/components/DevServerControl.tsxui/src/components/EditFeatureForm.tsxui/src/components/ExpandProjectChat.tsxui/src/components/FeatureCard.tsxui/src/components/FeatureModal.tsxui/src/components/FolderBrowser.tsxui/src/components/KanbanColumn.tsxui/src/components/NewProjectModal.tsxui/src/components/ProgressDashboard.tsxui/src/components/ProjectSelector.tsxui/src/components/QuestionOptions.tsxui/src/components/SettingsModal.tsxui/src/components/SetupWizard.tsxui/src/components/SpecCreationChat.tsxui/src/components/TerminalTabs.tsxui/src/styles/globals.cssui/tsconfig.tsbuildinfo
🧰 Additional context used
📓 Path-based instructions (2)
ui/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
ui/src/**/*.{ts,tsx}: Use TypeScript for React components in the UI (React 18 with TypeScript)
Use React Query (TanStack Query) for API calls and data fetching in the UI
Use Radix UI for component primitives in the React UI
Run ESLint to lint React UI code
Files:
ui/src/components/FeatureModal.tsxui/src/components/TerminalTabs.tsxui/src/components/SetupWizard.tsxui/src/components/ConfirmDialog.tsxui/src/components/ProgressDashboard.tsxui/src/components/AssistantFAB.tsxui/src/components/AssistantPanel.tsxui/src/components/EditFeatureForm.tsxui/src/components/DevServerControl.tsxui/src/components/NewProjectModal.tsxui/src/components/KanbanColumn.tsxui/src/components/FolderBrowser.tsxui/src/components/SettingsModal.tsxui/src/components/AssistantChat.tsxui/src/components/SpecCreationChat.tsxui/src/components/QuestionOptions.tsxui/src/components/DebugLogViewer.tsxui/src/components/ExpandProjectChat.tsxui/src/components/ProjectSelector.tsxui/src/App.tsxui/src/components/AddFeatureForm.tsxui/src/components/ChatMessage.tsxui/src/components/FeatureCard.tsx
ui/src/styles/**/*.css
📄 CodeRabbit inference engine (CLAUDE.md)
ui/src/styles/**/*.css: Use Tailwind CSS v4 for styling in React UI, with CSS variables defined in globals.css via@themedirective
React UI uses neobrutalism design system with CSS variables for color tokens: --color-neo-pending (yellow), --color-neo-progress (cyan), --color-neo-done (green)
React UI custom animations: animate-slide-in, animate-pulse-neo, animate-shimmer
Files:
ui/src/styles/globals.css
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : React UI uses neobrutalism design system with CSS variables for color tokens: --color-neo-pending (yellow), --color-neo-progress (cyan), --color-neo-done (green)
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : Use Tailwind CSS v4 for styling in React UI, with CSS variables defined in globals.css via theme directive
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : React UI uses neobrutalism design system with CSS variables for color tokens: --color-neo-pending (yellow), --color-neo-progress (cyan), --color-neo-done (green)
Applied to files:
ui/src/components/TerminalTabs.tsxui/src/components/SetupWizard.tsxui/src/components/ConfirmDialog.tsxui/src/components/AssistantFAB.tsxui/src/components/EditFeatureForm.tsxui/src/components/DevServerControl.tsxui/src/components/NewProjectModal.tsxui/src/components/KanbanColumn.tsxui/src/components/FolderBrowser.tsxui/src/components/SettingsModal.tsxui/src/components/SpecCreationChat.tsxui/src/components/QuestionOptions.tsxui/src/components/DebugLogViewer.tsxui/src/components/ExpandProjectChat.tsxui/src/styles/globals.cssui/src/components/ProjectSelector.tsxui/src/components/AddFeatureForm.tsxui/src/components/ChatMessage.tsxui/src/components/FeatureCard.tsx
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : Use Tailwind CSS v4 for styling in React UI, with CSS variables defined in globals.css via theme directive
Applied to files:
ui/src/components/SetupWizard.tsxui/src/components/ConfirmDialog.tsxui/src/components/NewProjectModal.tsxui/src/components/DebugLogViewer.tsxui/src/components/ExpandProjectChat.tsxui/src/styles/globals.cssui/src/components/ChatMessage.tsxui/src/components/FeatureCard.tsx
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/**/*.{ts,tsx} : Use TypeScript for React components in the UI (React 18 with TypeScript)
Applied to files:
ui/tsconfig.tsbuildinfoui/src/components/SpecCreationChat.tsxui/src/components/DebugLogViewer.tsxui/src/components/ExpandProjectChat.tsxui/src/App.tsx
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : React UI custom animations: animate-slide-in, animate-pulse-neo, animate-shimmer
Applied to files:
ui/src/components/NewProjectModal.tsxui/src/components/QuestionOptions.tsxui/src/styles/globals.cssui/src/components/ChatMessage.tsx
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/**/*.{ts,tsx} : Use Radix UI for component primitives in the React UI
Applied to files:
ui/src/components/DebugLogViewer.tsx
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Two-agent pattern: Initializer Agent reads app spec and creates features in first session; Coding Agent implements features one by one in subsequent sessions
Applied to files:
ui/src/App.tsx
🔇 Additional comments (49)
ui/src/styles/globals.css (2)
3-4: LGTM - Dark mode implementation follows Tailwind v4 best practices.The
@custom-variant darkdirective correctly enables class-based dark mode, and placing the.darkoverrides outside@layerensures proper specificity for theme variable overrides. Based on learnings, this aligns with the Tailwind CSS v4 approach for CSS variables defined via the@themedirective.Also applies to: 145-146
10-139: Comprehensive design token system with good organization.The
@themeblock establishes a well-structured token system covering colors, typography, shadows, transitions, spacing, z-index, and border radius. The neutral scale and semantic color tokens align with the neobrutalism design system documented in the learnings.ui/src/components/AssistantChat.tsx (1)
134-134: LGTM - Consistent theming for input area.The background color now uses the CSS variable token, ensuring proper dark mode support consistent with the design system migration.
ui/src/components/KanbanColumn.tsx (2)
43-45: LGTM - Proper contrast handling for colored backgrounds.Using
--color-neo-text-on-brightfor text on the colored column headers ensures readability regardless of theme. The badge styling with--color-neo-cardbackground provides visual separation from the header.
61-61: LGTM - Consistent text token usage on progress-colored button.The expand button text now uses
--color-neo-text-on-bright, matching the design system pattern for text on bright/saturated backgrounds.ui/src/components/DevServerControl.tsx (1)
93-96: LGTM - Consistent adoption of text-on-bright token.All three styled elements (crashed button, stop button, URL link) appropriately use
--color-neo-text-on-brightsince they're rendered on saturated backgrounds (--color-neo-dangerand--color-neo-progress). This ensures readable text in both light and dark modes.Also applies to: 113-116, 135-138
ui/src/components/AssistantFAB.tsx (2)
20-20: LGTM - Text color migrated to design token.The text color now uses
--color-neo-text-on-brightfor proper contrast on the cyan progress background, consistent with the design system migration.
14-27: Verify the intentional removal ofrounded-fullfrom the FAB.According to the summary, the FAB button was changed from circular (
rounded-full) to square. This is a noticeable visual change. Please confirm this aligns with the intended neobrutalism design direction.ui/src/components/SetupWizard.tsx (1)
111-111: LGTM! Good migration to semantic error tokens.The error container styling now correctly uses the semantic
--color-neo-error-*CSS variables, which aligns with the design system's approach for consistent theming and dark mode support. Based on learnings, this follows the neobrutalism design system with CSS variables for color tokens.ui/src/components/ProjectSelector.tsx (2)
68-68: LGTM! Proper theming for the dropdown trigger.Replacing
bg-whitewithbg-[var(--color-neo-card)]correctly enables dark mode support for this component.
110-112: LGTM! Good accessibility improvement for selected state.Adding
text-[var(--color-neo-text-on-bright)]ensures readable text contrast on the yellow pending background when an item is selected.ui/src/components/AddFeatureForm.tsx (1)
90-100: LGTM! Consistent error styling with enhanced UX.The error container correctly uses semantic error tokens, and the close button now has appropriate hover feedback with
hover:opacity-70 transition-opacity.ui/src/components/ConfirmDialog.tsx (1)
57-65: LGTM! Good theming implementation for the dialog header.The combination of inline styles for dynamic
backgroundColor(from variant) andboxShadow(from CSS variable) is appropriate here since the background color is computed at runtime. The icon and title text colors correctly use CSS variables for dark mode support.ui/src/components/FeatureModal.tsx (2)
82-87: LGTM! Dynamic category badge coloring.The badge correctly uses the computed category color with appropriate text contrast using
--color-neo-text-on-bright.
104-113: LGTM! Consistent error styling.The error message block uses the same semantic error tokens (
--color-neo-error-bg,--color-neo-error-text,--color-neo-error-border) as other components in this PR, maintaining design consistency.ui/src/components/EditFeatureForm.tsx (2)
108-118: LGTM! Error banner styling aligns with design system.The error container now uses semantic CSS variables (
--color-neo-error-bg,--color-neo-error-text,--color-neo-error-border) consistent with other components in this PR. The close button's hover opacity transition is a nice UX touch.
187-193: LGTM! Step indicator styling improvement.The step number badge now uses a consistent neobrutalist style with mono font, border, and shadow. Using
items-centerensures proper vertical alignment with the input field.ui/src/components/TerminalTabs.tsx (2)
183-184: LGTM! Input styling uses appropriate theme tokens.The inline rename input correctly uses
bg-neo-cardandtext-neo-textfor theme consistency.
225-226: LGTM! Context menu theming is well-implemented.The context menu properly uses
bg-neo-card, theme border variable, and CSS variable shadow (var(--shadow-neo-md)), aligning with the design system's approach to surface styling.ui/src/components/SettingsModal.tsx (3)
118-129: LGTM! Error state styling uses semantic tokens.The error container properly uses the new error color variables, and the retry button has an appropriate hover transition.
152-156: LGTM! Toggle switch uses appropriate surface token.Using
--color-neo-cardfor the off-state background is semantically correct for an interactive surface element.
190-194: LGTM! Model selection buttons use proper token-based styling.The active state uses accent color with text-on-bright, while inactive uses card background with hover-subtle—this is a clean implementation of the design system's interactive states.
ui/src/components/AssistantPanel.tsx (3)
34-40: LGTM! Panel container uses appropriate theme tokens.The panel correctly uses
bg-neo-cardfor the surface and applies the shadow via CSS variable. This approach maintains design system consistency while allowing centralized shadow definitions.
46-57: LGTM! Header styling properly uses semantic classes.The header uses semantic classes (
border-neo-border,bg-neo-progress) and appropriate text color tokens (text-neo-text-on-bright) for content on the progress-colored background.
59-72: LGTM! Close button styling is consistent with the design system.The close button properly uses card background, border tokens, and hover state with theme variables.
ui/src/App.tsx (3)
46-73: LGTM! Dark mode implementation follows best practices.The implementation correctly:
- Initializes state from localStorage with try-catch for environments where storage is unavailable
- Applies the
darkclass todocumentElement(standard Tailwind approach)- Persists preference with safe error handling
248-257: LGTM! Dark mode toggle is well-implemented.The toggle button is always visible, uses appropriate icons (Sun for dark mode, Moon for light mode), and has proper accessibility attributes.
195-197: LGTM! Root element styling uses semantic tokens.The root container and header properly use
bg-neo-bg,bg-neo-card,text-neo-text, andborder-neo-bordertokens for theme consistency.ui/src/components/ProgressDashboard.tsx (1)
39-46: LGTM!The inline-flex restructure cleanly separates the numeric percentage from the percent sign, enabling independent sizing while maintaining baseline alignment. The use of
--color-neo-text-secondaryfor the percent sign is consistent with the design system.ui/src/components/ChatMessage.tsx (1)
24-55: Clean role-based theming configuration.The roleConfig structure effectively maps roles to CSS variable-based tokens for colors and shadows. Using CSS variable strings for
shadowthat get applied via inlinestyleprops is a pragmatic approach when Tailwind doesn't have direct utility classes for custom shadow tokens.ui/src/components/FolderBrowser.tsx (3)
142-176: LGTM!The header and breadcrumb navigation styling correctly adopts the design system tokens. The use of semantic variables like
--color-neo-card,--color-neo-text, and--color-neo-text-mutedensures proper dark mode support.
202-256: LGTM!Directory listing styling is well-organized with consistent CSS variable usage for backgrounds, text colors, and interactive states. The entry styling properly distinguishes selected vs unselected states using the theme tokens.
302-312: LGTM!Footer section correctly uses card background and semantic text color tokens for the selected path display.
ui/src/components/FeatureCard.tsx (2)
10-29: LGTM!The category color function now correctly uses CSS variable references, enabling theme-aware category badges. The hash-based color selection ensures consistent colors per category while respecting the design system.
40-40: Tailwind utilities are properly configured.The component correctly uses Tailwind utility classes (
border-neo-done,text-neo-text-secondary,text-neo-progress,text-neo-done) which are automatically generated by Tailwind v4's@themedirective. The CSS variables (--color-neo-done,--color-neo-progress,--color-neo-text-secondary, etc.) are defined inglobals.csswithin the@themeblock and properly configure these utilities without needing explicit custom class definitions.ui/src/components/SpecCreationChat.tsx (4)
210-213: LGTM!Header styling correctly uses card background and text color tokens, consistent with other components in this PR.
247-258: Good adoption of semantic error tokens.The error banner now uses dedicated error tokens (
--color-neo-error-bg,--color-neo-error-text,--color-neo-error-border) rather than generic danger colors, providing better semantic clarity and easier theme customization.
317-318: Consistent shadow pattern.Using inline
style={{ boxShadow: 'var(--shadow-neo-sm)' }}matches the approach in ChatMessage.tsx for applying custom shadow tokens.
405-468: LGTM!The completion footer properly handles multiple states (starting, error, idle) with appropriate styling. The conditional background color based on
initializerStatusand consistent use of--color-neo-text-on-brightfor text on colored backgrounds ensures readability across all states.ui/src/components/DebugLogViewer.tsx (2)
319-443: LGTM!The header bar and tab styling correctly migrates to CSS variable tokens. Active/inactive states are properly differentiated, and hover transitions use consistent theme variables.
448-520: LGTM!Log content areas consistently use theme tokens for backgrounds, text colors, and hover states. Empty state messaging is properly styled with muted text colors.
ui/src/components/NewProjectModal.tsx (2)
215-220: LGTM!Header, label, and error state styling correctly uses semantic theme tokens. The consistent application of
--color-neo-error-bg/text/borderfor error states improves maintainability.Also applies to: 251-291
407-426: LGTM!The completion step styling with inline
boxShadowfor the icon container and themed background colors is well-implemented.ui/src/components/ExpandProjectChat.tsx (4)
185-217: LGTM!Header styling with connection indicators and feature count badges is well-implemented with appropriate theme tokens.
271-304: LGTM!Attachment preview styling with inline shadow and themed colors for the remove button follows the established patterns.
363-378: LGTM!Completion footer with themed background and close button styling is consistent with the design system.
155-181: No changes needed. The shorthand Tailwind classes liketext-neo-done,bg-neo-card, andborder-neo-borderare valid in Tailwind v4. The@themedirective in globals.css automatically generates utility classes from CSS variables, making bothtext-neo-doneandtext-[var(--color-neo-done)]equivalent syntax. The shorthand approach is actually the cleaner and intended method for Tailwind v4 with@theme. Mixed usage across the codebase represents a natural coexistence of both valid syntaxes rather than an inconsistency requiring alignment.Likely an incorrect or invalid review comment.
ui/src/components/QuestionOptions.tsx (2)
96-111: LGTM!Card container and question header styling with semantic theme tokens is well-implemented. The badge and text color usage follows the design system conventions.
148-170: LGTM!Checkbox/radio indicator styling correctly differentiates selected and unselected states using appropriate theme tokens.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
ui/src/components/ChatMessage.tsx (1)
153-166: Hardenwindow.openfor attachments (noopener,noreferrer).Clicking an attachment opens a new tab without
noopener, which can exposewindow.opener. Consider adding features.Proposed fix
- onClick={() => window.open(attachment.previewUrl, '_blank')} + onClick={() => window.open(attachment.previewUrl, '_blank', 'noopener,noreferrer')}ui/src/components/QuestionOptions.tsx (1)
119-123: Addtype="button"to option buttons to avoid accidental form submits.Proposed fix
- <button + <button type="button" key={optIdx} onClick={() => handleOptionClick(questionIdx, opt.label, q.multiSelect)} disabled={disabled} className={`- <button + <button type="button" onClick={() => handleOptionClick(questionIdx, 'Other', q.multiSelect)} disabled={disabled} className={`Also applies to: 176-179
🤖 Fix all issues with AI agents
In `@ui/tsconfig.tsbuildinfo`:
- Line 1: Remove the auto-generated ui/tsconfig.tsbuildinfo from version control
and stop tracking it: add tsconfig.tsbuildinfo (or the pattern
/ui/tsconfig.tsbuildinfo) to .gitignore, remove the file from the Git index so
it’s no longer tracked, and commit the .gitignore change and the removal so the
incremental build cache is not committed going forward.
♻️ Duplicate comments (4)
ui/src/components/ChatMessage.tsx (1)
173-174: Replacebg-neo-accentwith CSS var-backed utility (Tailwind class likely undefined).This looks like the same missing-utility issue previously called out; use the variable-backed pattern for consistency with the rest of the file.
Proposed fix
- <span className="inline-block w-2 h-4 bg-neo-accent ml-1 animate-pulse" /> + <span className="inline-block w-2 h-4 bg-[var(--color-neo-accent)] ml-1 animate-pulse" />ui/src/components/DebugLogViewer.tsx (1)
276-289: Fix incorrect log color mapping forinfo(should use--color-neo-log-info).
info(and default) currently returns--color-neo-log-success, which makes neutral logs look like success.Proposed fix
const getLogColor = (level: LogLevel): string => { switch (level) { case 'error': return 'text-[var(--color-neo-log-error)]' case 'warn': return 'text-[var(--color-neo-log-warning)]' case 'debug': return 'text-[var(--color-neo-log-debug)]' case 'info': default: - return 'text-[var(--color-neo-log-success)]' + return 'text-[var(--color-neo-log-info)]' } }ui/src/styles/globals.css (2)
310-327: Fix.neo-btn-loadingspinner invisibility (currentColorbecomes transparent).Proposed fix
.neo-btn-loading { position: relative; color: transparent; } .neo-btn-loading::after { content: ''; position: absolute; inset: 0; margin: auto; width: 1.25rem; height: 1.25rem; - border: 2px solid currentColor; + border: 2px solid var(--color-neo-border); border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; }
543-565: Fix progress shimmer selector (pseudo-element is attached to the wrong class).Proposed fix
/* Progress Bar Shimmer Effect */ - .neo-progress-bar::after { + .neo-progress-fill::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient( 90deg, transparent 0%, rgba(255,255,255,0.2) 50%, transparent 100% ); animation: shimmer 2s infinite; }
🧹 Nitpick comments (3)
ui/src/components/ChatMessage.tsx (1)
24-56: MakeroleConfigtype-safe (avoidundefinedconfig at runtime).
const config = roleConfig[role]assumesroleis always one of the keys. Consider typingroleConfigasRecord<ChatMessageType["role"], ...>(or guarding) so this can’t silently becomeundefinedif roles expand later.ui/src/styles/globals.css (1)
329-360: Consider tokenizing button variant colors (neo-btn-primary/success/warning/danger).These variants are still hard-coded hex values; if the intent is full theme control, consider using
--color-neo-accent/--color-neo-done/...so dark mode can override them consistently. Based on learnings, the design system is driven by CSS variables.ui/src/components/QuestionOptions.tsx (1)
123-147: Avoid DOM style mutation for hover shadow; prefer class-driven hover/state styling.Directly setting
e.currentTarget.style.boxShadowworks, but it’s harder to maintain and can fight React/state-driven styling. Consider using conditional classNames (or a tinyhoveredKeystate) and let CSS handle hover (hover:shadow-*equivalent via tokens).Also applies to: 179-203
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
ui/index.htmlui/src/App.tsxui/src/components/AddFeatureForm.tsxui/src/components/AssistantChat.tsxui/src/components/AssistantFAB.tsxui/src/components/AssistantPanel.tsxui/src/components/ChatMessage.tsxui/src/components/ConfirmDialog.tsxui/src/components/DebugLogViewer.tsxui/src/components/DevServerControl.tsxui/src/components/EditFeatureForm.tsxui/src/components/ExpandProjectChat.tsxui/src/components/FeatureCard.tsxui/src/components/FeatureModal.tsxui/src/components/FolderBrowser.tsxui/src/components/KanbanColumn.tsxui/src/components/NewProjectModal.tsxui/src/components/ProgressDashboard.tsxui/src/components/ProjectSelector.tsxui/src/components/QuestionOptions.tsxui/src/components/SettingsModal.tsxui/src/components/SetupWizard.tsxui/src/components/SpecCreationChat.tsxui/src/components/TerminalTabs.tsxui/src/styles/globals.cssui/tsconfig.tsbuildinfo
🚧 Files skipped from review as they are similar to previous changes (15)
- ui/src/components/ProgressDashboard.tsx
- ui/src/components/ProjectSelector.tsx
- ui/src/components/SettingsModal.tsx
- ui/src/components/TerminalTabs.tsx
- ui/src/components/SpecCreationChat.tsx
- ui/src/components/DevServerControl.tsx
- ui/src/components/SetupWizard.tsx
- ui/src/App.tsx
- ui/src/components/FolderBrowser.tsx
- ui/src/components/ExpandProjectChat.tsx
- ui/src/components/KanbanColumn.tsx
- ui/src/components/AssistantFAB.tsx
- ui/src/components/AssistantPanel.tsx
- ui/src/components/AddFeatureForm.tsx
- ui/src/components/FeatureModal.tsx
🧰 Additional context used
📓 Path-based instructions (2)
ui/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
ui/src/**/*.{ts,tsx}: Use TypeScript for React components in the UI (React 18 with TypeScript)
Use React Query (TanStack Query) for API calls and data fetching in the UI
Use Radix UI for component primitives in the React UI
Run ESLint to lint React UI code
Files:
ui/src/components/ConfirmDialog.tsxui/src/components/AssistantChat.tsxui/src/components/DebugLogViewer.tsxui/src/components/NewProjectModal.tsxui/src/components/EditFeatureForm.tsxui/src/components/ChatMessage.tsxui/src/components/QuestionOptions.tsxui/src/components/FeatureCard.tsx
ui/src/styles/**/*.css
📄 CodeRabbit inference engine (CLAUDE.md)
ui/src/styles/**/*.css: Use Tailwind CSS v4 for styling in React UI, with CSS variables defined in globals.css via@themedirective
React UI uses neobrutalism design system with CSS variables for color tokens: --color-neo-pending (yellow), --color-neo-progress (cyan), --color-neo-done (green)
React UI custom animations: animate-slide-in, animate-pulse-neo, animate-shimmer
Files:
ui/src/styles/globals.css
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : React UI uses neobrutalism design system with CSS variables for color tokens: --color-neo-pending (yellow), --color-neo-progress (cyan), --color-neo-done (green)
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : Use Tailwind CSS v4 for styling in React UI, with CSS variables defined in globals.css via theme directive
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : React UI uses neobrutalism design system with CSS variables for color tokens: --color-neo-pending (yellow), --color-neo-progress (cyan), --color-neo-done (green)
Applied to files:
ui/src/components/ConfirmDialog.tsxui/src/components/DebugLogViewer.tsxui/src/components/NewProjectModal.tsxui/src/styles/globals.cssui/src/components/EditFeatureForm.tsxui/src/components/ChatMessage.tsxui/src/components/QuestionOptions.tsxui/src/components/FeatureCard.tsx
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : Use Tailwind CSS v4 for styling in React UI, with CSS variables defined in globals.css via theme directive
Applied to files:
ui/src/components/DebugLogViewer.tsxui/src/styles/globals.cssui/src/components/ChatMessage.tsx
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/**/*.{ts,tsx} : Use TypeScript for React components in the UI (React 18 with TypeScript)
Applied to files:
ui/src/components/DebugLogViewer.tsxui/tsconfig.tsbuildinfo
📚 Learning: 2026-01-10T08:23:04.021Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.021Z
Learning: Applies to ui/src/styles/**/*.css : React UI custom animations: animate-slide-in, animate-pulse-neo, animate-shimmer
Applied to files:
ui/src/styles/globals.cssui/src/components/ChatMessage.tsxui/src/components/QuestionOptions.tsx
🔇 Additional comments (16)
ui/src/components/AssistantChat.tsx (1)
134-134: LGTM!The input area background correctly uses the CSS variable
--color-neo-cardinstead of the hardcodedbg-white, enabling proper dark mode support and maintaining consistency with the design system.ui/src/components/ConfirmDialog.tsx (1)
57-65: LGTM!The header icon styling correctly applies variant-specific colors and shadows using CSS variables. Using
--color-neo-text-on-brightensures proper contrast for the icon on colored backgrounds, which is good for accessibility. The title text color update to--color-neo-textenables proper dark mode support.ui/src/components/EditFeatureForm.tsx (2)
107-118: LGTM!The error message styling correctly uses semantic error tokens (
--color-neo-error-bg,--color-neo-error-text,--color-neo-error-border), which aligns with the design system and enables theme-aware error states. The close button's hover transition is a nice UX improvement.
187-193: LGTM!The step number badge redesign follows the neobrutalism design system with proper border, shadow, and mono font styling. The fixed dimensions (
w-10 h-10) ensure visual consistency across steps.ui/src/components/FeatureCard.tsx (3)
10-29: LGTM!The
getCategoryColorfunction correctly migrates from hardcoded hex values to CSS variable references. The documentation linking toglobals.cssis helpful for maintainability. The hashing algorithm ensures consistent color assignment per category.
67-84: Cleaner approach using semantic utility classes.Good improvement using semantic utility classes (
text-neo-progress,text-neo-done,text-neo-text-secondary) instead of inline variable references. This is more maintainable and readable.
40-40: No action needed. In Tailwind CSS v4, utilities likeborder-neo-doneare automatically generated from the--color-neo-doneCSS variable defined in the@themeblock. The utility class is implicitly defined and properly available.Likely an incorrect or invalid review comment.
ui/index.html (1)
10-10: > Likely an incorrect or invalid review comment.ui/src/components/ChatMessage.tsx (1)
70-73: Nice token-based theming + shadow tokenization.Moving backgrounds/text to CSS variables and centralizing shadows via
config.shadow/--shadow-neo-*is consistent with the design-system direction.Also applies to: 109-114
ui/src/components/DebugLogViewer.tsx (1)
319-321: Theme-token migration looks consistent across states (hover/active/empty/loading).The move to
--color-neo-*tokens for header, tabs, counts, empty states, hover rows, and loading messages is cohesive and should behave well in dark mode.Also applies to: 327-341, 354-356, 409-417, 448-458, 470-476, 507-515, 541-547
ui/src/components/NewProjectModal.tsx (3)
215-219: Tokenized headings + error state styling are consistent with the new system.Using
--color-neo-text*and--color-neo-error-*improves dark-mode correctness and keeps error styling uniform across steps.Also applies to: 251-252, 270-271, 288-290
318-339: Option cards: good alignment withneo-card+ shadow tokens.The option blocks now match the card system (border/shadow/tokens) while keeping interaction behavior.
Also applies to: 353-376
409-414: Completion icon container uses tokens cleanly.ui/src/styles/globals.css (2)
10-139: Design tokens + dark overrides are comprehensive and well-scoped.The variable coverage (colors, neutrals, log levels, typography, shadows, spacing/z-index/radius) plus
.darkoverrides should enable consistent theming across the app. Based on learnings, this matches the project’s Tailwind v4 +@themeapproach inglobals.css.Also applies to: 145-203, 205-223, 243-256, 269-292, 471-486, 501-531, 567-596, 616-636, 913-959, 983-995
3-5: ✓@custom-variant darksyntax is correct for Tailwind v4.The shorthand form
@custom-variant dark (&:where(.dark, .dark *));is valid and documented in Tailwind v4 for class-based dark mode. No changes needed.ui/src/components/QuestionOptions.tsx (1)
95-111: Card + header badge token updates look consistent.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
- ChatMessage: use CSS variable syntax for bg-neo-accent and text consistency - DebugLogViewer: fix info log level to use --color-neo-log-info - TerminalTabs: use neo-hover-subtle for hover states instead of text color - globals.css: fix shimmer effect selector to target .neo-progress-fill - globals.css: fix loading spinner visibility with explicit border color - globals.css: add will-change for .neo-btn-yolo performance - App.tsx: group constants after imports - NewProjectModal: remove redundant styling (neo-card provides these) - Add tsconfig.tsbuildinfo to .gitignore and remove from tracking Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Created features with XSS payloads (<script>, <img onerror>, <svg onload>) - Verified script tags are safely escaped and displayed as text - No alert dialogs executed, no XSS-related JavaScript errors - React's automatic escaping provides built-in XSS protection - Screenshots captured showing escaped content in Kanban board Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary
This PR addresses 53 design issues identified in the UI codebase, implementing a more consistent and polished neobrutalism design system.
Typography
Color/Theme System
--color-neo-log-error/warning/info/debug/success)Design Tokens
--space-xsto--space-2xl)--z-dropdownto--z-toast)--radius-sm/md/lg/full)Animations
--transition-fast/normal/slow/slower)--ease-bounce/smooth/out-back).stagger-1to.stagger-5)Component Improvements
neo-btn-sm/lg/icon) and loading stateComponent Fixes
Test plan
npm run build)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
UI Improvements
Chores
✏️ Tip: You can customize this high-level summary in your review settings.