Files
kandev/apps/web/components/task/mobile/mobile-terminal-row.tsx
T
2026-09-12 14:58:49 +02:00

88 lines
2.9 KiB
TypeScript

"use client";
import { IconTerminal2, IconX } from "@tabler/icons-react";
import { Button } from "@kandev/ui/button";
import { useTranslation } from "react-i18next";
import { useRef } from "react";
import { useResponsiveBreakpoint } from "@/hooks/use-responsive-breakpoint";
import type { Terminal } from "@/hooks/domains/session/use-terminals";
import { TerminalCloseInlineConfirmation } from "../terminal-close-inline-confirmation";
type MobileTerminalRowProps = {
terminal: Terminal;
isActive: boolean;
isRunning: boolean;
isConfirming: boolean;
onSelect: (id: string) => void;
onAskClose: (terminal: Terminal) => void;
onCancelClose: () => void;
onClose: () => void;
onConfirmClose: () => void | Promise<void>;
};
export function MobileTerminalRow({
terminal,
isActive,
isRunning,
isConfirming,
onSelect,
onAskClose,
onCancelClose,
onClose,
onConfirmClose,
}: MobileTerminalRowProps) {
const { t } = useTranslation();
const { isMobile } = useResponsiveBreakpoint();
const closeRef = useRef<HTMLButtonElement>(null);
return (
<div
data-testid={`mobile-terminal-row-${terminal.id}`}
className={`flex min-h-11 items-center gap-2 border px-2 rounded-md cursor-pointer select-none ${
isActive ? "border-primary/50 bg-card" : "border-transparent hover:bg-muted"
}`}
>
<button
type="button"
className="flex min-h-11 min-w-0 flex-1 cursor-pointer items-center gap-2 text-left"
onClick={() => onSelect(terminal.id)}
>
<IconTerminal2 className="h-4 w-4 text-muted-foreground shrink-0" />
<span className="text-sm truncate flex-1">{terminal.label}</span>
{isRunning && (!isConfirming || isMobile) && (
<span className="text-[10px] font-medium px-1.5 py-0.5 rounded bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 leading-none">
{t("task:running")}
</span>
)}
</button>
{terminal.closable && (
<>
<TerminalCloseInlineConfirmation
open={isConfirming}
terminalId={terminal.id}
terminalLabel={terminal.label}
focusReturnRef={closeRef}
density="touch"
testId="mobile-terminal-close-confirmation"
onCancel={onCancelClose}
onClose={onClose}
onConfirm={onConfirmClose}
/>
{(!isConfirming || isMobile) && (
<Button
ref={closeRef}
variant="ghost"
size="icon-sm"
aria-label={t("task:close2", { label: terminal.label })}
className="h-11 min-h-11 w-11 min-w-11 transition-[color,background-color,transform] duration-100 active:scale-[0.96]"
onClick={() => onAskClose(terminal)}
>
<IconX className="h-4 w-4" aria-hidden="true" />
</Button>
)}
</>
)}
</div>
);
}