ux: skip type selector — new project goes straight to name input

- CreateProjectFlow now defaults to setup/fresh mode; type selector never shown
- FreshIdeaSetup simplified to just project name + Start button
  (removed description field, 6-phase explanation copy, SetupHeader)

Made-with: Cursor
This commit is contained in:
2026-03-17 16:58:35 -07:00
parent f1b4622043
commit 532f851d1f
2 changed files with 18 additions and 35 deletions

View File

@@ -19,13 +19,13 @@ interface CreateProjectFlowProps {
type Step = "select-type" | "setup"; type Step = "select-type" | "setup";
export function CreateProjectFlow({ open, onOpenChange, workspace }: CreateProjectFlowProps) { export function CreateProjectFlow({ open, onOpenChange, workspace }: CreateProjectFlowProps) {
const [step, setStep] = useState<Step>("select-type"); const [step, setStep] = useState<Step>("setup");
const [mode, setMode] = useState<CreationMode | null>(null); const [mode, setMode] = useState<CreationMode | null>("fresh");
useEffect(() => { useEffect(() => {
if (open) { if (open) {
setStep("select-type"); setStep("setup");
setMode(null); setMode("fresh");
} }
}, [open]); }, [open]);
@@ -80,7 +80,7 @@ export function CreateProjectFlow({ open, onOpenChange, workspace }: CreateProje
background: "#fff", borderRadius: 16, background: "#fff", borderRadius: 16,
boxShadow: "0 12px 48px rgba(26,26,26,0.16)", boxShadow: "0 12px 48px rgba(26,26,26,0.16)",
width: "100%", width: "100%",
maxWidth: step === "select-type" ? 620 : 520, maxWidth: 520,
fontFamily: "Outfit, sans-serif", fontFamily: "Outfit, sans-serif",
pointerEvents: "all", pointerEvents: "all",
animation: "vibn-slideUp 0.18s cubic-bezier(0.4,0,0.2,1)", animation: "vibn-slideUp 0.18s cubic-bezier(0.4,0,0.2,1)",

View File

@@ -3,12 +3,11 @@
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { toast } from "sonner"; import { toast } from "sonner";
import { SetupHeader, FieldLabel, TextInput, PrimaryButton, type SetupProps } from "./setup-shared"; import { FieldLabel, TextInput, PrimaryButton, type SetupProps } from "./setup-shared";
export function FreshIdeaSetup({ workspace, onClose, onBack }: SetupProps) { export function FreshIdeaSetup({ workspace, onClose }: SetupProps) {
const router = useRouter(); const router = useRouter();
const [name, setName] = useState(""); const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const nameRef = useRef<HTMLInputElement>(null); const nameRef = useRef<HTMLInputElement>(null);
@@ -27,7 +26,7 @@ export function FreshIdeaSetup({ workspace, onClose, onBack }: SetupProps) {
slug: name.toLowerCase().replace(/[^a-z0-9]+/g, "-"), slug: name.toLowerCase().replace(/[^a-z0-9]+/g, "-"),
product: { name: name.trim() }, product: { name: name.trim() },
creationMode: "fresh", creationMode: "fresh",
sourceData: { description: description.trim() }, sourceData: {},
}), }),
}); });
if (!res.ok) { if (!res.ok) {
@@ -47,10 +46,15 @@ export function FreshIdeaSetup({ workspace, onClose, onBack }: SetupProps) {
return ( return (
<div style={{ padding: "32px 36px 36px" }}> <div style={{ padding: "32px 36px 36px" }}>
<SetupHeader <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 28 }}>
icon="✦" label="Fresh Idea" tagline="Start from scratch" <div style={{ fontSize: "1.15rem", fontWeight: 600, color: "#1a1a1a", fontFamily: "Newsreader, serif" }}>
accent="#4a3728" onBack={onBack} onClose={onClose} New project
/> </div>
<button
onClick={onClose}
style={{ background: "none", border: "none", cursor: "pointer", color: "#a09a90", fontSize: "1.1rem", padding: "2px 6px", lineHeight: 1 }}
>×</button>
</div>
<FieldLabel>Project name</FieldLabel> <FieldLabel>Project name</FieldLabel>
<TextInput <TextInput
@@ -62,29 +66,8 @@ export function FreshIdeaSetup({ workspace, onClose, onBack }: SetupProps) {
autoFocus autoFocus
/> />
<FieldLabel>One-line description <span style={{ color: "#b5b0a6", fontWeight: 400 }}>(optional)</span></FieldLabel>
<input
type="text"
value={description}
onChange={e => setDescription(e.target.value)}
placeholder="A short description to kick off the conversation"
style={{
width: "100%", padding: "11px 14px", marginBottom: 20,
borderRadius: 8, border: "1px solid #e0dcd4",
background: "#faf8f5", fontSize: "0.9rem",
fontFamily: "Outfit, sans-serif", color: "#1a1a1a",
outline: "none", boxSizing: "border-box",
}}
onFocus={e => (e.currentTarget.style.borderColor = "#1a1a1a")}
onBlur={e => (e.currentTarget.style.borderColor = "#e0dcd4")}
/>
<div style={{ fontSize: "0.75rem", color: "#a09a90", marginBottom: 20, lineHeight: 1.5, padding: "12px 14px", background: "#faf8f5", borderRadius: 8, border: "1px solid #f0ece4" }}>
Vibn will guide you through 6 discovery phases Big Picture, Users, Features, Business Model, Screens, and Risks building your product plan as you go.
</div>
<PrimaryButton onClick={handleCreate} disabled={!canCreate} loading={loading}> <PrimaryButton onClick={handleCreate} disabled={!canCreate} loading={loading}>
Start with Vibn Start
</PrimaryButton> </PrimaryButton>
</div> </div>
); );