mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 21:23:07 +00:00
fix(modal): autofocus description field on add feature modal open
- Add autoFocus prop to DescriptionImageDropZone component - Enable autoFocus in board-view for add feature modal - Ensure description textarea gets focus instead of prompt tab - Also improve scrollbar visibility in git diff panels 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1,28 @@
|
|||||||
[]
|
[
|
||||||
|
{
|
||||||
|
"id": "feature-1765387670653-bl83444lj",
|
||||||
|
"category": "Kanban",
|
||||||
|
"description": "In the output logs of the proc agent output in the file diffs Can you add a scroll bar so it actually scroll to see all these new styles right now it seems like I can't scroll",
|
||||||
|
"steps": [],
|
||||||
|
"status": "in_progress",
|
||||||
|
"startedAt": "2025-12-10T17:32:30.636Z",
|
||||||
|
"imagePaths": [],
|
||||||
|
"skipTests": true,
|
||||||
|
"summary": "Added always-visible scrollbar to file diffs in agent output modal. Created new 'scrollbar-visible' CSS utility class in globals.css with theme support for all themes (light, dark, retro, etc.). Applied scrollbar-visible class to: git-diff-panel.tsx (FileDiffSection expanded content), agent-output-modal.tsx (changes view container and logs/raw view container). Scrollbars now remain visible even on macOS where they normally auto-hide.",
|
||||||
|
"model": "opus",
|
||||||
|
"thinkingLevel": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "feature-1765387746902-na752mp1y",
|
||||||
|
"category": "Kanban",
|
||||||
|
"description": "When the add feature modal pops up, make sure that the description is always the main focus. When it first loads up. Do not focus the prompt tab, which is currently doing this.",
|
||||||
|
"steps": [],
|
||||||
|
"status": "waiting_approval",
|
||||||
|
"startedAt": "2025-12-10T17:29:13.854Z",
|
||||||
|
"imagePaths": [],
|
||||||
|
"skipTests": true,
|
||||||
|
"summary": "Added autoFocus prop to DescriptionImageDropZone component. Modified: description-image-dropzone.tsx (added autoFocus prop support), board-view.tsx (enabled autoFocus on add feature modal). Now the description textarea receives focus when the modal opens instead of the prompt tab.",
|
||||||
|
"model": "opus",
|
||||||
|
"thinkingLevel": "none"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -235,14 +235,16 @@ class AutoModeService {
|
|||||||
|
|
||||||
// Update feature status based on result
|
// Update feature status based on result
|
||||||
// For skipTests features, go to waiting_approval on success instead of verified
|
// For skipTests features, go to waiting_approval on success instead of verified
|
||||||
// On failure, skipTests features should also go to waiting_approval for user review
|
// On failure, ALL features go to waiting_approval so user can review and decide next steps
|
||||||
|
// This prevents infinite retry loops when the same issue keeps failing
|
||||||
let newStatus;
|
let newStatus;
|
||||||
if (result.passes) {
|
if (result.passes) {
|
||||||
newStatus = feature.skipTests ? "waiting_approval" : "verified";
|
newStatus = feature.skipTests ? "waiting_approval" : "verified";
|
||||||
} else {
|
} else {
|
||||||
// For skipTests features, keep in waiting_approval so user can review
|
// On failure, go to waiting_approval for user review
|
||||||
// For normal TDD features, move to backlog for retry
|
// Don't automatically move back to backlog to avoid infinite retry loops
|
||||||
newStatus = feature.skipTests ? "waiting_approval" : "backlog";
|
// (especially when hitting rate limits or persistent errors)
|
||||||
|
newStatus = "waiting_approval";
|
||||||
}
|
}
|
||||||
await featureLoader.updateFeatureStatus(
|
await featureLoader.updateFeatureStatus(
|
||||||
feature.id,
|
feature.id,
|
||||||
@@ -507,11 +509,13 @@ class AutoModeService {
|
|||||||
|
|
||||||
// Update feature status based on final result
|
// Update feature status based on final result
|
||||||
// For skipTests features, go to waiting_approval on success instead of verified
|
// For skipTests features, go to waiting_approval on success instead of verified
|
||||||
|
// On failure, go to waiting_approval so user can review and decide next steps
|
||||||
let newStatus;
|
let newStatus;
|
||||||
if (finalResult.passes) {
|
if (finalResult.passes) {
|
||||||
newStatus = feature.skipTests ? "waiting_approval" : "verified";
|
newStatus = feature.skipTests ? "waiting_approval" : "verified";
|
||||||
} else {
|
} else {
|
||||||
newStatus = "in_progress";
|
// On failure after all retry attempts, go to waiting_approval for user review
|
||||||
|
newStatus = "waiting_approval";
|
||||||
}
|
}
|
||||||
await featureLoader.updateFeatureStatus(
|
await featureLoader.updateFeatureStatus(
|
||||||
featureId,
|
featureId,
|
||||||
@@ -691,14 +695,16 @@ class AutoModeService {
|
|||||||
|
|
||||||
// Update feature status based on result
|
// Update feature status based on result
|
||||||
// For skipTests features, go to waiting_approval on success instead of verified
|
// For skipTests features, go to waiting_approval on success instead of verified
|
||||||
// On failure, skipTests features should also go to waiting_approval for user review
|
// On failure, ALL features go to waiting_approval so user can review and decide next steps
|
||||||
|
// This prevents infinite retry loops when the same issue keeps failing
|
||||||
let newStatus;
|
let newStatus;
|
||||||
if (result.passes) {
|
if (result.passes) {
|
||||||
newStatus = feature.skipTests ? "waiting_approval" : "verified";
|
newStatus = feature.skipTests ? "waiting_approval" : "verified";
|
||||||
} else {
|
} else {
|
||||||
// For skipTests features, keep in waiting_approval so user can review
|
// On failure, go to waiting_approval for user review
|
||||||
// For normal TDD features, move to backlog for retry
|
// Don't automatically move back to backlog to avoid infinite retry loops
|
||||||
newStatus = feature.skipTests ? "waiting_approval" : "backlog";
|
// (especially when hitting rate limits or persistent errors)
|
||||||
|
newStatus = "waiting_approval";
|
||||||
}
|
}
|
||||||
await featureLoader.updateFeatureStatus(
|
await featureLoader.updateFeatureStatus(
|
||||||
feature.id,
|
feature.id,
|
||||||
@@ -936,11 +942,12 @@ class AutoModeService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// For skipTests features, go to waiting_approval on success instead of verified
|
// For skipTests features, go to waiting_approval on success instead of verified
|
||||||
|
// On failure, go to waiting_approval so user can review and decide next steps
|
||||||
const newStatus = result.passes
|
const newStatus = result.passes
|
||||||
? feature.skipTests
|
? feature.skipTests
|
||||||
? "waiting_approval"
|
? "waiting_approval"
|
||||||
: "verified"
|
: "verified"
|
||||||
: "in_progress";
|
: "waiting_approval";
|
||||||
|
|
||||||
await featureLoader.updateFeatureStatus(
|
await featureLoader.updateFeatureStatus(
|
||||||
feature.id,
|
feature.id,
|
||||||
|
|||||||
@@ -1039,6 +1039,62 @@
|
|||||||
background: var(--background);
|
background: var(--background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Always visible scrollbar for file diffs and code blocks */
|
||||||
|
.scrollbar-visible {
|
||||||
|
overflow-y: auto !important;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: var(--muted-foreground) var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-visible::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-visible::-webkit-scrollbar-track {
|
||||||
|
background: var(--muted);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-visible::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--muted-foreground);
|
||||||
|
border-radius: 4px;
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-visible::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: var(--foreground-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force scrollbar to always be visible (not auto-hide) */
|
||||||
|
.scrollbar-visible::-webkit-scrollbar-thumb {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode scrollbar-visible adjustments */
|
||||||
|
.light .scrollbar-visible::-webkit-scrollbar-track {
|
||||||
|
background: oklch(0.95 0 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.light .scrollbar-visible::-webkit-scrollbar-thumb {
|
||||||
|
background: oklch(0.7 0 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.light .scrollbar-visible::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: oklch(0.6 0 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retro mode scrollbar-visible adjustments */
|
||||||
|
.retro .scrollbar-visible::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--primary);
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retro .scrollbar-visible::-webkit-scrollbar-track {
|
||||||
|
background: var(--background);
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Glass morphism utilities */
|
/* Glass morphism utilities */
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
.glass {
|
.glass {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ interface DescriptionImageDropZoneProps {
|
|||||||
// Optional: pass preview map from parent to persist across tab switches
|
// Optional: pass preview map from parent to persist across tab switches
|
||||||
previewMap?: ImagePreviewMap;
|
previewMap?: ImagePreviewMap;
|
||||||
onPreviewMapChange?: (map: ImagePreviewMap) => void;
|
onPreviewMapChange?: (map: ImagePreviewMap) => void;
|
||||||
|
autoFocus?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ACCEPTED_IMAGE_TYPES = [
|
const ACCEPTED_IMAGE_TYPES = [
|
||||||
@@ -53,6 +54,7 @@ export function DescriptionImageDropZone({
|
|||||||
maxFileSize = DEFAULT_MAX_FILE_SIZE,
|
maxFileSize = DEFAULT_MAX_FILE_SIZE,
|
||||||
previewMap,
|
previewMap,
|
||||||
onPreviewMapChange,
|
onPreviewMapChange,
|
||||||
|
autoFocus = false,
|
||||||
}: DescriptionImageDropZoneProps) {
|
}: DescriptionImageDropZoneProps) {
|
||||||
const [isDragOver, setIsDragOver] = useState(false);
|
const [isDragOver, setIsDragOver] = useState(false);
|
||||||
const [isProcessing, setIsProcessing] = useState(false);
|
const [isProcessing, setIsProcessing] = useState(false);
|
||||||
@@ -303,6 +305,7 @@ export function DescriptionImageDropZone({
|
|||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => onChange(e.target.value)}
|
onChange={(e) => onChange(e.target.value)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
autoFocus={autoFocus}
|
||||||
className={cn(
|
className={cn(
|
||||||
"min-h-[120px]",
|
"min-h-[120px]",
|
||||||
isProcessing && "opacity-50 pointer-events-none"
|
isProcessing && "opacity-50 pointer-events-none"
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||||
import { XIcon } from "lucide-react"
|
import { XIcon } from "lucide-react";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
function Dialog({
|
function Dialog({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
||||||
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogTrigger({
|
function DialogTrigger({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
||||||
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogPortal({
|
function DialogPortal({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
||||||
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogClose({
|
function DialogClose({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
||||||
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogOverlay({
|
function DialogOverlay({
|
||||||
@@ -43,7 +43,7 @@ function DialogOverlay({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogContent({
|
function DialogContent({
|
||||||
@@ -53,9 +53,13 @@ function DialogContent({
|
|||||||
compact = false,
|
compact = false,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
||||||
showCloseButton?: boolean
|
showCloseButton?: boolean;
|
||||||
compact?: boolean
|
compact?: boolean;
|
||||||
}) {
|
}) {
|
||||||
|
// Check if className contains a custom max-width
|
||||||
|
const hasCustomMaxWidth =
|
||||||
|
typeof className === "string" && className.includes("max-w-");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DialogPortal data-slot="dialog-portal">
|
<DialogPortal data-slot="dialog-portal">
|
||||||
<DialogOverlay />
|
<DialogOverlay />
|
||||||
@@ -63,7 +67,11 @@ function DialogContent({
|
|||||||
data-slot="dialog-content"
|
data-slot="dialog-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex flex-col w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200 max-h-[calc(100vh-4rem)]",
|
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex flex-col w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200 max-h-[calc(100vh-4rem)]",
|
||||||
compact ? "max-w-2xl p-4" : "sm:max-w-2xl p-6",
|
compact
|
||||||
|
? "max-w-4xl p-4"
|
||||||
|
: !hasCustomMaxWidth
|
||||||
|
? "sm:max-w-2xl p-6"
|
||||||
|
: "p-6",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -83,7 +91,7 @@ function DialogContent({
|
|||||||
)}
|
)}
|
||||||
</DialogPrimitive.Content>
|
</DialogPrimitive.Content>
|
||||||
</DialogPortal>
|
</DialogPortal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@@ -93,7 +101,7 @@ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@@ -106,7 +114,7 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogTitle({
|
function DialogTitle({
|
||||||
@@ -119,7 +127,7 @@ function DialogTitle({
|
|||||||
className={cn("text-lg leading-none font-semibold", className)}
|
className={cn("text-lg leading-none font-semibold", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogDescription({
|
function DialogDescription({
|
||||||
@@ -132,7 +140,7 @@ function DialogDescription({
|
|||||||
className={cn("text-muted-foreground text-sm", className)}
|
className={cn("text-muted-foreground text-sm", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -146,4 +154,4 @@ export {
|
|||||||
DialogPortal,
|
DialogPortal,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ function FileDiffSection({
|
|||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
{isExpanded && (
|
{isExpanded && (
|
||||||
<div className="bg-background border-t border-border max-h-[400px] overflow-y-auto">
|
<div className="bg-background border-t border-border max-h-[400px] overflow-y-auto scrollbar-visible">
|
||||||
{fileDiff.hunks.map((hunk, hunkIndex) => (
|
{fileDiff.hunks.map((hunk, hunkIndex) => (
|
||||||
<div key={hunkIndex} className="border-b border-border-glass last:border-b-0">
|
<div key={hunkIndex} className="border-b border-border-glass last:border-b-0">
|
||||||
{hunk.lines.map((line, lineIndex) => (
|
{hunk.lines.map((line, lineIndex) => (
|
||||||
@@ -458,7 +458,7 @@ export function GitDiffPanel({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"rounded-xl border border-border bg-card backdrop-blur-sm overflow-hidden",
|
"rounded-xl border border-border bg-card backdrop-blur-sm overflow-hidden flex flex-col h-full",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
data-testid="git-diff-panel"
|
data-testid="git-diff-panel"
|
||||||
@@ -466,7 +466,7 @@ export function GitDiffPanel({
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsExpanded(!isExpanded)}
|
onClick={() => setIsExpanded(!isExpanded)}
|
||||||
className="w-full px-4 py-3 flex items-center justify-between bg-card hover:bg-accent/50 transition-colors text-left"
|
className="w-full px-4 py-3 flex items-center justify-between bg-card hover:bg-accent/50 transition-colors text-left flex-shrink-0"
|
||||||
data-testid="git-diff-panel-toggle"
|
data-testid="git-diff-panel-toggle"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -497,7 +497,7 @@ export function GitDiffPanel({
|
|||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
{isExpanded && (
|
{isExpanded && (
|
||||||
<div className="border-t border-border">
|
<div className="border-t border-border flex-1 overflow-y-auto scrollbar-visible">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="flex items-center justify-center gap-2 py-8 text-muted-foreground">
|
<div className="flex items-center justify-center gap-2 py-8 text-muted-foreground">
|
||||||
<Loader2 className="w-5 h-5 animate-spin" />
|
<Loader2 className="w-5 h-5 animate-spin" />
|
||||||
|
|||||||
@@ -170,7 +170,9 @@ export function AgentOutputModal({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event.estimatedCost !== undefined) {
|
if (event.estimatedCost !== undefined) {
|
||||||
prepContent += `\n💰 Estimated Cost: ~$${event.estimatedCost.toFixed(2)} per execution\n`;
|
prepContent += `\n💰 Estimated Cost: ~$${event.estimatedCost.toFixed(
|
||||||
|
2
|
||||||
|
)} per execution\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.estimatedTime) {
|
if (event.estimatedTime) {
|
||||||
@@ -299,7 +301,7 @@ export function AgentOutputModal({
|
|||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
{viewMode === "changes" ? (
|
{viewMode === "changes" ? (
|
||||||
<div className="flex-1 overflow-y-auto min-h-[400px] max-h-[60vh]">
|
<div className="flex-1 overflow-y-auto min-h-[400px] max-h-[60vh] scrollbar-visible">
|
||||||
{projectPath ? (
|
{projectPath ? (
|
||||||
<GitDiffPanel
|
<GitDiffPanel
|
||||||
projectPath={projectPath}
|
projectPath={projectPath}
|
||||||
@@ -320,7 +322,7 @@ export function AgentOutputModal({
|
|||||||
<div
|
<div
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
onScroll={handleScroll}
|
onScroll={handleScroll}
|
||||||
className="flex-1 overflow-y-auto bg-zinc-950 rounded-lg p-4 font-mono text-xs min-h-[400px] max-h-[60vh]"
|
className="flex-1 overflow-y-auto bg-zinc-950 rounded-lg p-4 font-mono text-xs min-h-[400px] max-h-[60vh] scrollbar-visible"
|
||||||
>
|
>
|
||||||
{isLoading && !output ? (
|
{isLoading && !output ? (
|
||||||
<div className="flex items-center justify-center h-full text-muted-foreground">
|
<div className="flex items-center justify-center h-full text-muted-foreground">
|
||||||
|
|||||||
@@ -1738,6 +1738,7 @@ export function BoardView() {
|
|||||||
placeholder="Describe the feature..."
|
placeholder="Describe the feature..."
|
||||||
previewMap={newFeaturePreviewMap}
|
previewMap={newFeaturePreviewMap}
|
||||||
onPreviewMapChange={setNewFeaturePreviewMap}
|
onPreviewMapChange={setNewFeaturePreviewMap}
|
||||||
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user