- Refactored JSX elements to improve readability by collapsing multi-line props and attributes into single lines if their length permits. - Improved consistency in component imports by grouping and consolidating them. - No functional changes, purely restructuring for clarity and maintainability.
100 lines
3.3 KiB
TypeScript
100 lines
3.3 KiB
TypeScript
'use client';
|
|
|
|
/**
|
|
* Step 3: Client Mode Selection
|
|
*
|
|
* Allows users to choose how they want to interact with Syndarix agents.
|
|
* Skipped for script complexity projects.
|
|
*/
|
|
|
|
import { Check, CheckCircle2 } from 'lucide-react';
|
|
|
|
import { Separator } from '@/components/ui/separator';
|
|
import { cn } from '@/lib/utils';
|
|
import { SelectableCard } from '../SelectableCard';
|
|
import { clientModeOptions } from '../constants';
|
|
import type { WizardState, ClientMode } from '../types';
|
|
|
|
interface ClientModeStepProps {
|
|
state: WizardState;
|
|
updateState: (updates: Partial<WizardState>) => void;
|
|
}
|
|
|
|
export function ClientModeStep({ state, updateState }: ClientModeStepProps) {
|
|
const handleSelect = (clientMode: ClientMode) => {
|
|
updateState({ clientMode });
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div>
|
|
<h2 className="text-2xl font-bold">How Would You Like to Work?</h2>
|
|
<p className="mt-1 text-muted-foreground">
|
|
Choose how you want to interact with Syndarix agents.
|
|
</p>
|
|
</div>
|
|
|
|
<div
|
|
className="grid gap-6 md:grid-cols-2"
|
|
role="radiogroup"
|
|
aria-label="Client interaction mode options"
|
|
>
|
|
{clientModeOptions.map((option) => {
|
|
const Icon = option.icon;
|
|
const isSelected = state.clientMode === option.id;
|
|
|
|
return (
|
|
<SelectableCard
|
|
key={option.id}
|
|
selected={isSelected}
|
|
onClick={() => handleSelect(option.id)}
|
|
className="h-full"
|
|
aria-label={`${option.label}: ${option.description}`}
|
|
>
|
|
<div className="flex h-full flex-col space-y-4">
|
|
<div className="flex items-start justify-between">
|
|
<div
|
|
className={cn(
|
|
'flex h-12 w-12 items-center justify-center rounded-lg',
|
|
isSelected ? 'bg-primary text-primary-foreground' : 'bg-muted'
|
|
)}
|
|
>
|
|
<Icon className="h-6 w-6" aria-hidden="true" />
|
|
</div>
|
|
{isSelected && (
|
|
<div className="flex h-6 w-6 items-center justify-center rounded-full bg-primary text-primary-foreground">
|
|
<Check className="h-4 w-4" aria-hidden="true" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div>
|
|
<h3 className="text-lg font-semibold">{option.label}</h3>
|
|
<p className="mt-1 text-muted-foreground">{option.description}</p>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
<ul className="flex-1 space-y-2">
|
|
{option.details.map((detail) => (
|
|
<li key={detail} className="flex items-start gap-2 text-sm">
|
|
<CheckCircle2
|
|
className={cn(
|
|
'mt-0.5 h-4 w-4 shrink-0',
|
|
isSelected ? 'text-primary' : 'text-muted-foreground'
|
|
)}
|
|
aria-hidden="true"
|
|
/>
|
|
<span className="text-muted-foreground">{detail}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</SelectableCard>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|