mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-01-31 06:42:06 +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,5 +1,12 @@
|
||||
import { useEffect, useCallback } from 'react'
|
||||
import { X, Keyboard } from 'lucide-react'
|
||||
import { Keyboard } from 'lucide-react'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
|
||||
interface Shortcut {
|
||||
key: string
|
||||
@@ -20,10 +27,11 @@ const shortcuts: Shortcut[] = [
|
||||
]
|
||||
|
||||
interface KeyboardShortcutsHelpProps {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export function KeyboardShortcutsHelp({ onClose }: KeyboardShortcutsHelpProps) {
|
||||
export function KeyboardShortcutsHelp({ isOpen, onClose }: KeyboardShortcutsHelpProps) {
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape' || e.key === '?') {
|
||||
@@ -35,59 +43,49 @@ export function KeyboardShortcutsHelp({ onClose }: KeyboardShortcutsHelpProps) {
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||
}, [handleKeyDown])
|
||||
if (isOpen) {
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||
}
|
||||
}, [isOpen, handleKeyDown])
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
|
||||
onClick={onClose}
|
||||
>
|
||||
<div
|
||||
className="neo-card p-6 max-w-md w-full mx-4"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Keyboard size={20} className="text-neo-accent" />
|
||||
<h2 className="font-display text-lg font-bold">Keyboard Shortcuts</h2>
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="neo-btn p-1.5"
|
||||
aria-label="Close"
|
||||
>
|
||||
<X size={16} />
|
||||
</button>
|
||||
</div>
|
||||
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<Keyboard size={20} className="text-primary" />
|
||||
Keyboard Shortcuts
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
{/* Shortcuts list */}
|
||||
<ul className="space-y-2">
|
||||
<ul className="space-y-1">
|
||||
{shortcuts.map((shortcut) => (
|
||||
<li
|
||||
key={shortcut.key}
|
||||
className="flex items-center justify-between py-2 border-b border-neo-border/30 last:border-0"
|
||||
className="flex items-center justify-between py-2 border-b border-border/50 last:border-0"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<kbd className="px-2 py-1 text-sm font-mono bg-neo-bg rounded border border-neo-border shadow-neo-sm min-w-[2rem] text-center">
|
||||
<div className="flex items-center gap-3">
|
||||
<kbd className="px-2 py-1 text-xs font-mono bg-muted rounded border border-border min-w-[2rem] text-center">
|
||||
{shortcut.key}
|
||||
</kbd>
|
||||
<span className="text-neo-text">{shortcut.description}</span>
|
||||
<span className="text-sm">{shortcut.description}</span>
|
||||
</div>
|
||||
{shortcut.context && (
|
||||
<span className="text-xs text-neo-muted">{shortcut.context}</span>
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{shortcut.context}
|
||||
</Badge>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{/* Footer */}
|
||||
<p className="text-xs text-neo-muted text-center mt-6">
|
||||
<p className="text-xs text-muted-foreground text-center pt-2">
|
||||
Press ? or Esc to close
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user