/ src / components / auth / setup-wizard / step-path.tsx
step-path.tsx
  1  'use client'
  2  
  3  import { ONBOARDING_PATHS } from '@/lib/setup-defaults'
  4  import type { StepPathProps } from './types'
  5  import { StepShell, SkipLink } from './shared'
  6  import { formatAgentCount, getStarterKitsForPath } from './utils'
  7  
  8  export function StepPath({
  9    onboardingPath,
 10    starterKitId,
 11    intentText,
 12    onPathChange,
 13    onStarterKitChange,
 14    onIntentTextChange,
 15    onContinue,
 16    onBack,
 17    onSkip,
 18  }: StepPathProps) {
 19    const visibleStarterKits = getStarterKitsForPath(onboardingPath)
 20  
 21    return (
 22      <StepShell wide>
 23        <h1 className="font-display text-[36px] font-800 leading-[1.05] tracking-[-0.04em] mb-3">
 24          Choose Your Start
 25        </h1>
 26        <p className="text-[15px] text-text-2 mb-2">
 27          Pick the setup path that matches how much guidance you want.
 28        </p>
 29        <p className="text-[13px] text-text-3 mb-7">
 30          You can still edit providers, prompts, tools, and agent details before finishing setup.
 31        </p>
 32  
 33        <div className="grid gap-3 md:grid-cols-3 text-left mb-6">
 34          {ONBOARDING_PATHS.map((path) => {
 35            const active = path.id === onboardingPath
 36            return (
 37              <button
 38                key={path.id}
 39                type="button"
 40                onClick={() => onPathChange(path.id)}
 41                className={`rounded-[18px] border px-5 py-4 text-left transition-all duration-200 cursor-pointer ${
 42                  active
 43                    ? 'border-accent-bright/35 bg-accent-soft shadow-[0_0_24px_rgba(99,102,241,0.12)]'
 44                    : 'border-white/[0.08] bg-surface hover:border-accent-bright/20 hover:bg-white/[0.04]'
 45                }`}
 46              >
 47                <div className="flex items-start justify-between gap-3">
 48                  <div className="text-[15px] font-display font-700 text-text">{path.title}</div>
 49                  {path.badge ? (
 50                    <span className={`rounded-full px-2 py-1 text-[10px] font-700 uppercase tracking-[0.12em] ${
 51                      active ? 'bg-accent-bright text-black' : 'bg-white/[0.05] text-text-3/80'
 52                    }`}>
 53                      {path.badge}
 54                    </span>
 55                  ) : null}
 56                </div>
 57                <p className="mt-2 text-[13px] leading-relaxed text-text-2">{path.description}</p>
 58                <p className="mt-3 text-[12px] leading-relaxed text-text-3/72">{path.detail}</p>
 59              </button>
 60            )
 61          })}
 62        </div>
 63  
 64        {onboardingPath === 'intent' && (
 65          <div className="mb-6 rounded-[18px] border border-white/[0.08] bg-surface px-5 py-4 text-left">
 66            <label className="block text-[12px] font-700 uppercase tracking-[0.12em] text-text-3/60 mb-2">
 67              What Are You Setting Up SwarmClaw To Do?
 68            </label>
 69            <textarea
 70              value={intentText}
 71              onChange={(event) => onIntentTextChange(event.target.value)}
 72              rows={3}
 73              placeholder="e.g. Help me run product research every week, summarize findings, and turn them into follow-up tasks."
 74              className="w-full rounded-[14px] border border-white/[0.08] bg-bg px-4 py-3 text-[14px] text-text outline-none transition-all duration-200 resize-none placeholder:text-text-3/45 focus:border-accent-bright/30 focus:shadow-[0_0_30px_rgba(99,102,241,0.1)]"
 75            />
 76            <p className="mt-2 text-[12px] leading-relaxed text-text-3/72">
 77              This is used only to seed the starter prompts. It does not auto-classify your workflow.
 78            </p>
 79          </div>
 80        )}
 81  
 82        <div className="rounded-[20px] border border-white/[0.08] bg-surface p-5 text-left">
 83          <div className="flex flex-wrap items-start justify-between gap-3">
 84            <div>
 85              <div className="text-[11px] font-700 uppercase tracking-[0.12em] text-text-3/55">Starting Shape</div>
 86              <div className="mt-1 text-[13px] text-text-3/72">
 87                Start from a broad team shape instead of a niche preset. You can still edit every agent before setup finishes.
 88              </div>
 89            </div>
 90            <div className="rounded-full border border-white/[0.08] bg-white/[0.03] px-3 py-1 text-[11px] font-700 uppercase tracking-[0.12em] text-text-3/70">
 91              {visibleStarterKits.length} options
 92            </div>
 93          </div>
 94  
 95          <div className="mt-4 grid gap-3 md:grid-cols-2 xl:grid-cols-3">
 96            {visibleStarterKits.map((kit) => {
 97              const active = starterKitId === kit.id
 98              return (
 99                <button
100                  key={kit.id}
101                  type="button"
102                  onClick={() => onStarterKitChange(kit.id)}
103                  className={`rounded-[18px] border px-4 py-4 text-left transition-all duration-200 cursor-pointer ${
104                    active
105                      ? 'border-accent-bright/35 bg-accent-soft shadow-[0_0_24px_rgba(99,102,241,0.12)]'
106                      : 'border-white/[0.08] bg-white/[0.02] hover:border-accent-bright/20 hover:bg-white/[0.04]'
107                  }`}
108                >
109                  <div className="flex items-start justify-between gap-3">
110                    <div className="text-[15px] font-display font-700 text-text">{kit.name}</div>
111                    <span className={`rounded-full px-2 py-1 text-[10px] font-700 uppercase tracking-[0.12em] ${
112                      active ? 'bg-accent-bright text-black' : 'bg-white/[0.05] text-text-3/80'
113                    }`}>
114                      {kit.badge || formatAgentCount(kit.agents.length)}
115                    </span>
116                  </div>
117                  <p className="mt-2 text-[13px] leading-relaxed text-text-2">{kit.description}</p>
118                  <p className="mt-3 text-[12px] leading-relaxed text-text-3/72">{kit.detail}</p>
119                  {kit.agents.length > 0 ? (
120                    <div className="mt-4 flex flex-wrap gap-2">
121                      {kit.agents.map((agent) => (
122                        <span
123                          key={agent.id}
124                          className="rounded-full border border-white/[0.08] bg-white/[0.03] px-2.5 py-1 text-[11px] text-text-2"
125                        >
126                          {agent.name}
127                        </span>
128                      ))}
129                    </div>
130                  ) : (
131                    <div className="mt-4 rounded-[12px] border border-dashed border-white/[0.06] bg-white/[0.02] px-3 py-2 text-[11px] text-text-3/70">
132                      Finish setup without starter agents.
133                    </div>
134                  )}
135                </button>
136              )
137            })}
138          </div>
139        </div>
140  
141        <div className="mt-6 flex items-center justify-center gap-3">
142          <button
143            onClick={onBack}
144            className="px-6 py-3.5 rounded-[14px] border border-white/[0.08] bg-transparent text-text-2 text-[14px] font-display font-500 cursor-pointer hover:bg-white/[0.03] transition-all duration-200"
145          >
146            Back
147          </button>
148          <button
149            onClick={onContinue}
150            className="px-8 py-3.5 rounded-[14px] border-none bg-accent-bright text-white text-[15px] font-display font-600 cursor-pointer hover:brightness-110 active:scale-[0.97] transition-all duration-200 shadow-[0_6px_28px_rgba(99,102,241,0.3)]"
151          >
152            Continue to Providers
153          </button>
154        </div>
155  
156        <SkipLink onClick={onSkip} />
157      </StepShell>
158    )
159  }