fix(ui): project dialog improvements, onboarding cleanup, scroll-area fix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,7 @@ import { PROJECT_COLORS } from "@paperclip/shared";
|
|||||||
import { cn } from "../lib/utils";
|
import { cn } from "../lib/utils";
|
||||||
import { MarkdownEditor, type MarkdownEditorRef } from "./MarkdownEditor";
|
import { MarkdownEditor, type MarkdownEditorRef } from "./MarkdownEditor";
|
||||||
import { StatusBadge } from "./StatusBadge";
|
import { StatusBadge } from "./StatusBadge";
|
||||||
|
import { ChoosePathButton } from "./PathInstructionsModal";
|
||||||
|
|
||||||
const projectStatuses = [
|
const projectStatuses = [
|
||||||
{ value: "backlog", label: "Backlog" },
|
{ value: "backlog", label: "Backlog" },
|
||||||
@@ -333,12 +334,15 @@ export function NewProjectDialog() {
|
|||||||
{(workspaceSetup === "local" || workspaceSetup === "both") && (
|
{(workspaceSetup === "local" || workspaceSetup === "both") && (
|
||||||
<div className="rounded-md border border-border p-2">
|
<div className="rounded-md border border-border p-2">
|
||||||
<label className="mb-1 block text-xs text-muted-foreground">Local folder (full path)</label>
|
<label className="mb-1 block text-xs text-muted-foreground">Local folder (full path)</label>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
className="w-full rounded border border-border bg-transparent px-2 py-1 text-xs font-mono outline-none"
|
className="w-full rounded border border-border bg-transparent px-2 py-1 text-xs font-mono outline-none"
|
||||||
value={workspaceLocalPath}
|
value={workspaceLocalPath}
|
||||||
onChange={(e) => setWorkspaceLocalPath(e.target.value)}
|
onChange={(e) => setWorkspaceLocalPath(e.target.value)}
|
||||||
placeholder="/absolute/path/to/workspace"
|
placeholder="/absolute/path/to/workspace"
|
||||||
/>
|
/>
|
||||||
|
<ChoosePathButton />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{(workspaceSetup === "repo" || workspaceSetup === "both") && (
|
{(workspaceSetup === "repo" || workspaceSetup === "both") && (
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { cn } from "../lib/utils";
|
|||||||
import { getUIAdapter } from "../adapters";
|
import { getUIAdapter } from "../adapters";
|
||||||
import { defaultCreateValues } from "./agent-config-defaults";
|
import { defaultCreateValues } from "./agent-config-defaults";
|
||||||
import { AsciiArtAnimation } from "./AsciiArtAnimation";
|
import { AsciiArtAnimation } from "./AsciiArtAnimation";
|
||||||
|
import { ChoosePathButton } from "./PathInstructionsModal";
|
||||||
import {
|
import {
|
||||||
Building2,
|
Building2,
|
||||||
Bot,
|
Bot,
|
||||||
@@ -63,7 +64,6 @@ export function OnboardingWizard() {
|
|||||||
const [command, setCommand] = useState("");
|
const [command, setCommand] = useState("");
|
||||||
const [args, setArgs] = useState("");
|
const [args, setArgs] = useState("");
|
||||||
const [url, setUrl] = useState("");
|
const [url, setUrl] = useState("");
|
||||||
const [cwdPickerNotice, setCwdPickerNotice] = useState<string | null>(null);
|
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
const [taskTitle, setTaskTitle] = useState("Create your CEO HEARTBEAT.md");
|
const [taskTitle, setTaskTitle] = useState("Create your CEO HEARTBEAT.md");
|
||||||
@@ -94,7 +94,6 @@ export function OnboardingWizard() {
|
|||||||
setCommand("");
|
setCommand("");
|
||||||
setArgs("");
|
setArgs("");
|
||||||
setUrl("");
|
setUrl("");
|
||||||
setCwdPickerNotice(null);
|
|
||||||
setTaskTitle("Create your CEO HEARTBEAT.md");
|
setTaskTitle("Create your CEO HEARTBEAT.md");
|
||||||
setTaskDescription("You're the CEO of the company, make sure you have a file agents/ceo/HEARTBEAT.md that tells you your core loop. You MUST use the Paperclip SKILL.");
|
setTaskDescription("You're the CEO of the company, make sure you have a file agents/ceo/HEARTBEAT.md that tells you your core loop. You MUST use the Paperclip SKILL.");
|
||||||
setCreatedCompanyId(null);
|
setCreatedCompanyId(null);
|
||||||
@@ -415,44 +414,8 @@ export function OnboardingWizard() {
|
|||||||
value={cwd}
|
value={cwd}
|
||||||
onChange={(e) => setCwd(e.target.value)}
|
onChange={(e) => setCwd(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<button
|
<ChoosePathButton />
|
||||||
type="button"
|
|
||||||
className="inline-flex items-center rounded-md border border-border px-2 py-0.5 text-xs text-muted-foreground hover:bg-accent/50 transition-colors shrink-0"
|
|
||||||
onClick={async () => {
|
|
||||||
try {
|
|
||||||
setCwdPickerNotice(null);
|
|
||||||
// @ts-expect-error -- showDirectoryPicker is not in all TS lib defs yet
|
|
||||||
const handle = await window.showDirectoryPicker({ mode: "read" });
|
|
||||||
const pickedPath =
|
|
||||||
typeof handle === "object" &&
|
|
||||||
handle !== null &&
|
|
||||||
typeof (handle as { path?: unknown }).path === "string"
|
|
||||||
? String((handle as { path: string }).path)
|
|
||||||
: "";
|
|
||||||
if (pickedPath) {
|
|
||||||
setCwd(pickedPath);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const selectedName =
|
|
||||||
typeof handle === "object" &&
|
|
||||||
handle !== null &&
|
|
||||||
typeof (handle as { name?: unknown }).name === "string"
|
|
||||||
? String((handle as { name: string }).name)
|
|
||||||
: "selected folder";
|
|
||||||
setCwdPickerNotice(
|
|
||||||
`Directory picker only exposed "${selectedName}". Paste the absolute path manually.`,
|
|
||||||
);
|
|
||||||
} catch {
|
|
||||||
// user cancelled or API unsupported
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Choose
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
{cwdPickerNotice && (
|
|
||||||
<p className="mt-1 text-xs text-amber-400">{cwdPickerNotice}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-xs text-muted-foreground mb-1 block">
|
<label className="text-xs text-muted-foreground mb-1 block">
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
import { ExternalLink, Github, Plus, Trash2, X } from "lucide-react";
|
import { ExternalLink, Github, Plus, Trash2, X } from "lucide-react";
|
||||||
|
import { ChoosePathButton } from "./PathInstructionsModal";
|
||||||
|
|
||||||
interface ProjectPropertiesProps {
|
interface ProjectPropertiesProps {
|
||||||
project: Project;
|
project: Project;
|
||||||
@@ -384,12 +385,15 @@ export function ProjectProperties({ project, onUpdate }: ProjectPropertiesProps)
|
|||||||
</div>
|
</div>
|
||||||
{workspaceMode === "local" && (
|
{workspaceMode === "local" && (
|
||||||
<div className="space-y-1.5 rounded-md border border-border p-2">
|
<div className="space-y-1.5 rounded-md border border-border p-2">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
className="w-full rounded border border-border bg-transparent px-2 py-1 text-xs font-mono outline-none"
|
className="w-full rounded border border-border bg-transparent px-2 py-1 text-xs font-mono outline-none"
|
||||||
value={workspaceCwd}
|
value={workspaceCwd}
|
||||||
onChange={(e) => setWorkspaceCwd(e.target.value)}
|
onChange={(e) => setWorkspaceCwd(e.target.value)}
|
||||||
placeholder="/absolute/path/to/workspace"
|
placeholder="/absolute/path/to/workspace"
|
||||||
/>
|
/>
|
||||||
|
<ChoosePathButton />
|
||||||
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ function ScrollArea({
|
|||||||
return (
|
return (
|
||||||
<ScrollAreaPrimitive.Root
|
<ScrollAreaPrimitive.Root
|
||||||
data-slot="scroll-area"
|
data-slot="scroll-area"
|
||||||
className={cn("relative flex flex-col", className)}
|
className={cn("relative flex flex-col overflow-hidden", className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ScrollAreaPrimitive.Viewport
|
<ScrollAreaPrimitive.Viewport
|
||||||
|
|||||||
Reference in New Issue
Block a user