mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-02-01 06:53:36 +00:00
refactor(ui): migrate to shadcn/ui components and fix scroll issues
Migrate UI component library from custom implementations to shadcn/ui: - Add shadcn/ui primitives (Button, Card, Dialog, Input, etc.) - Replace custom styles with Tailwind CSS v4 theme configuration - Remove custom-theme.css in favor of globals.css with @theme directive Fix scroll overflow issues in multiple components: - ProjectSelector: "New Project" button no longer overlays project list - FolderBrowser: folder list now scrolls properly within modal - AgentCard: log modal content stays within bounds - ConversationHistory: conversation list scrolls correctly - KanbanColumn: feature cards scroll within fixed height - ScheduleModal: schedule form content scrolls properly Key technical changes: - Replace ScrollArea component with native overflow-y-auto divs - Add min-h-0 to flex containers to allow proper shrinking - Restructure dropdown layouts with flex-col for fixed footers New files: - ui/components.json (shadcn/ui configuration) - ui/src/components/ui/* (20 UI primitive components) - ui/src/lib/utils.ts (cn utility for class merging) - ui/tsconfig.app.json (app-specific TypeScript config) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { useEffect, useCallback } from 'react'
|
||||
import { CheckCircle2, XCircle, Loader2, ExternalLink } from 'lucide-react'
|
||||
import { useSetupStatus, useHealthCheck } from '../hooks/useProjects'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent } from '@/components/ui/card'
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
|
||||
|
||||
interface SetupWizardProps {
|
||||
onComplete: () => void
|
||||
@@ -26,98 +29,100 @@ export function SetupWizard({ onComplete }: SetupWizardProps) {
|
||||
}, [checkAndComplete])
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[var(--color-neo-bg)] flex items-center justify-center p-4">
|
||||
<div className="neo-card w-full max-w-lg p-8">
|
||||
<h1 className="font-display text-3xl font-bold text-center mb-2">
|
||||
Setup Wizard
|
||||
</h1>
|
||||
<p className="text-center text-[var(--color-neo-text-secondary)] mb-8">
|
||||
Let's make sure everything is ready to go
|
||||
</p>
|
||||
<div className="min-h-screen bg-background flex items-center justify-center p-4">
|
||||
<Card className="w-full max-w-lg">
|
||||
<CardContent className="p-8">
|
||||
<h1 className="font-display text-3xl font-bold text-center mb-2">
|
||||
Setup Wizard
|
||||
</h1>
|
||||
<p className="text-center text-muted-foreground mb-8">
|
||||
Let's make sure everything is ready to go
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
{/* API Health */}
|
||||
<SetupItem
|
||||
label="Backend Server"
|
||||
description="FastAPI server is running"
|
||||
status={healthError ? 'error' : isApiHealthy ? 'success' : 'loading'}
|
||||
/>
|
||||
<div className="space-y-4">
|
||||
{/* API Health */}
|
||||
<SetupItem
|
||||
label="Backend Server"
|
||||
description="FastAPI server is running"
|
||||
status={healthError ? 'error' : isApiHealthy ? 'success' : 'loading'}
|
||||
/>
|
||||
|
||||
{/* Claude CLI */}
|
||||
<SetupItem
|
||||
label="Claude CLI"
|
||||
description="Claude Code CLI is installed"
|
||||
status={
|
||||
setupLoading
|
||||
? 'loading'
|
||||
: setupError
|
||||
? 'error'
|
||||
: setupStatus?.claude_cli
|
||||
? 'success'
|
||||
: 'error'
|
||||
}
|
||||
helpLink="https://docs.anthropic.com/claude/claude-code"
|
||||
helpText="Install Claude Code"
|
||||
/>
|
||||
{/* Claude CLI */}
|
||||
<SetupItem
|
||||
label="Claude CLI"
|
||||
description="Claude Code CLI is installed"
|
||||
status={
|
||||
setupLoading
|
||||
? 'loading'
|
||||
: setupError
|
||||
? 'error'
|
||||
: setupStatus?.claude_cli
|
||||
? 'success'
|
||||
: 'error'
|
||||
}
|
||||
helpLink="https://docs.anthropic.com/claude/claude-code"
|
||||
helpText="Install Claude Code"
|
||||
/>
|
||||
|
||||
{/* Credentials */}
|
||||
<SetupItem
|
||||
label="Anthropic Credentials"
|
||||
description="API credentials are configured"
|
||||
status={
|
||||
setupLoading
|
||||
? 'loading'
|
||||
: setupError
|
||||
? 'error'
|
||||
: setupStatus?.credentials
|
||||
? 'success'
|
||||
: 'error'
|
||||
}
|
||||
helpLink="https://console.anthropic.com/account/keys"
|
||||
helpText="Get API Key"
|
||||
/>
|
||||
{/* Credentials */}
|
||||
<SetupItem
|
||||
label="Anthropic Credentials"
|
||||
description="API credentials are configured"
|
||||
status={
|
||||
setupLoading
|
||||
? 'loading'
|
||||
: setupError
|
||||
? 'error'
|
||||
: setupStatus?.credentials
|
||||
? 'success'
|
||||
: 'error'
|
||||
}
|
||||
helpLink="https://console.anthropic.com/account/keys"
|
||||
helpText="Get API Key"
|
||||
/>
|
||||
|
||||
{/* Node.js */}
|
||||
<SetupItem
|
||||
label="Node.js"
|
||||
description="Node.js is installed (for UI dev)"
|
||||
status={
|
||||
setupLoading
|
||||
? 'loading'
|
||||
: setupError
|
||||
? 'error'
|
||||
: setupStatus?.node
|
||||
? 'success'
|
||||
: 'warning'
|
||||
}
|
||||
helpLink="https://nodejs.org"
|
||||
helpText="Install Node.js"
|
||||
optional
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Continue Button */}
|
||||
{isReady && (
|
||||
<button
|
||||
onClick={onComplete}
|
||||
className="neo-btn neo-btn-success w-full mt-8"
|
||||
>
|
||||
Continue to Dashboard
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Error Message */}
|
||||
{(healthError || setupError) && (
|
||||
<div className="mt-6 p-4 bg-[var(--color-neo-error-bg)] text-[var(--color-neo-error-text)] border-3 border-[var(--color-neo-error-border)]">
|
||||
<p className="font-bold mb-2">Setup Error</p>
|
||||
<p className="text-sm">
|
||||
{healthError
|
||||
? 'Cannot connect to the backend server. Make sure to run start_ui.py first.'
|
||||
: 'Failed to check setup status.'}
|
||||
</p>
|
||||
{/* Node.js */}
|
||||
<SetupItem
|
||||
label="Node.js"
|
||||
description="Node.js is installed (for UI dev)"
|
||||
status={
|
||||
setupLoading
|
||||
? 'loading'
|
||||
: setupError
|
||||
? 'error'
|
||||
: setupStatus?.node
|
||||
? 'success'
|
||||
: 'warning'
|
||||
}
|
||||
helpLink="https://nodejs.org"
|
||||
helpText="Install Node.js"
|
||||
optional
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Continue Button */}
|
||||
{isReady && (
|
||||
<Button
|
||||
onClick={onComplete}
|
||||
className="w-full mt-8 bg-green-500 hover:bg-green-600 text-white"
|
||||
>
|
||||
Continue to Dashboard
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* Error Message */}
|
||||
{(healthError || setupError) && (
|
||||
<Alert variant="destructive" className="mt-6">
|
||||
<AlertTitle>Setup Error</AlertTitle>
|
||||
<AlertDescription>
|
||||
{healthError
|
||||
? 'Cannot connect to the backend server. Make sure to run start_ui.py first.'
|
||||
: 'Failed to check setup status.'}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -140,31 +145,31 @@ function SetupItem({
|
||||
optional,
|
||||
}: SetupItemProps) {
|
||||
return (
|
||||
<div className="flex items-start gap-4 p-4 bg-[var(--color-neo-bg)] border-3 border-[var(--color-neo-border)]">
|
||||
<div className="flex items-start gap-4 p-4 bg-background border-2 border-border rounded-lg">
|
||||
{/* Status Icon */}
|
||||
<div className="flex-shrink-0 mt-1">
|
||||
{status === 'success' ? (
|
||||
<CheckCircle2 size={24} className="text-[var(--color-neo-done)]" />
|
||||
<CheckCircle2 size={24} className="text-green-500" />
|
||||
) : status === 'error' ? (
|
||||
<XCircle size={24} className="text-[var(--color-neo-danger)]" />
|
||||
<XCircle size={24} className="text-destructive" />
|
||||
) : status === 'warning' ? (
|
||||
<XCircle size={24} className="text-[var(--color-neo-pending)]" />
|
||||
<XCircle size={24} className="text-yellow-500" />
|
||||
) : (
|
||||
<Loader2 size={24} className="animate-spin text-[var(--color-neo-progress)]" />
|
||||
<Loader2 size={24} className="animate-spin text-primary" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-display font-bold">{label}</span>
|
||||
<span className="font-display font-bold text-foreground">{label}</span>
|
||||
{optional && (
|
||||
<span className="text-xs text-[var(--color-neo-text-secondary)]">
|
||||
<span className="text-xs text-muted-foreground">
|
||||
(optional)
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm text-[var(--color-neo-text-secondary)]">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{description}
|
||||
</p>
|
||||
{(status === 'error' || status === 'warning') && helpLink && (
|
||||
@@ -172,7 +177,7 @@ function SetupItem({
|
||||
href={helpLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 mt-2 text-sm text-[var(--color-neo-accent)] hover:underline"
|
||||
className="inline-flex items-center gap-1 mt-2 text-sm text-primary hover:underline"
|
||||
>
|
||||
{helpText} <ExternalLink size={12} />
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user