"use client"; import type { ReactNode } from "react"; import { IconChevronDown, IconPlus, IconRocket } from "@tabler/icons-react"; import { Button } from "@kandev/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@kandev/ui/dropdown-menu"; import { Tooltip, TooltipContent, TooltipTrigger } from "@kandev/ui/tooltip"; import { cn } from "@kandev/ui/lib/utils"; import { useTranslation } from "react-i18next"; /** * Split-button: primary "Implement" runs the plan inline in the current * session; the dropdown caret offers "Implement in fresh agent" which starts * a new session with a clean context window. `onClick(fresh)` is invoked * with `false` for the primary path and `true` for the fresh-agent path. */ type ImplementPlanButtonProps = { onClick: (fresh: boolean) => void | Promise; presentation?: "desktop" | "mobile"; disabled?: boolean; disabledReason?: string; framed?: boolean; testIds?: { root?: string; button?: string; menuTrigger?: string; freshItem?: string; }; }; type ImplementPlanPresentation = "desktop" | "mobile"; function legacyRootTestId(rootId: string) { return rootId === "implement-plan-control" ? undefined : "implement-plan-control"; } function controlSizeClass(presentation: ImplementPlanPresentation, framed?: boolean): string { if (presentation === "mobile") return "min-h-11 min-w-11"; if (framed) return "h-5"; return "h-7"; } function disabledInteractionClass(disabled?: boolean): string { return disabled ? "pointer-events-none cursor-not-allowed" : "cursor-pointer"; } function framedRootClass(framed?: boolean): string | undefined { return framed ? "border border-violet-400/35 bg-background/40 focus-within:ring-[2px] focus-within:ring-violet-400/25" : undefined; } const coarsePointerClass = "[@media(pointer:coarse)]:relative [@media(pointer:coarse)]:after:absolute [@media(pointer:coarse)]:after:-inset-3 [@media(pointer:coarse)]:after:content-['']"; function DisabledImplementTooltip({ disabledReason, children, }: { disabledReason: string; children: ReactNode; }) { return ( {children} {disabledReason} ); } // eslint-disable-next-line max-lines-per-function -- split-button markup stays together export function ImplementPlanButton({ onClick, presentation = "desktop", disabled, disabledReason, framed, testIds, }: ImplementPlanButtonProps) { const ids = { root: testIds?.root ?? "implement-plan-control", button: testIds?.button ?? "implement-plan-button", menuTrigger: testIds?.menuTrigger ?? "implement-plan-menu-trigger", freshItem: testIds?.freshItem ?? "implement-fresh-menu-item", }; const controlSize = controlSizeClass(presentation, framed); const splitButton = (
); if (!disabledReason) return splitButton; return ( {splitButton} ); } function ImplementPrimaryButton({ buttonId, controlSize, disabled, disabledReason, onClick, }: { buttonId: string; controlSize: string; disabled?: boolean; disabledReason?: string; onClick: (fresh: boolean) => void | Promise; }) { const { t } = useTranslation(); const button = ( ); if (disabledReason) return button; return ( {button} {t("task:implementThePlanInThisSession")} ); } function ImplementMenuButton({ controlSize, disabled, freshItemId, menuTriggerId, onClick, }: { controlSize: string; disabled?: boolean; freshItemId: string; menuTriggerId: string; onClick: (fresh: boolean) => void | Promise; }) { const { t } = useTranslation(); return ( onClick(true)} className="cursor-pointer" >
{t("task:implementInFreshAgent")}
{t("task:startsANewSessionWithA")}
); }