/* Copyright 2026 Marimo. All rights reserved. */
import { HardDriveDownloadIcon, PlayIcon } from "lucide-react";
import type { JSX } from "react";
import type { CellConfig, RuntimeState } from "@/core/network/types";
import {
getConnectionTooltip,
isAppInteractionDisabled,
} from "@/core/websocket/connection-utils";
import type { WebSocketState } from "@/core/websocket/types";
import { renderShortcut } from "../../shortcuts/renderShortcut";
import { ToolbarItem } from "./toolbar";
function computeColor({
connectionState,
needsRun,
loading,
inactive,
}: {
connectionState: WebSocketState;
needsRun: boolean;
loading: boolean;
inactive: boolean;
}) {
if (isAppInteractionDisabled(connectionState)) {
return "disabled";
}
if (needsRun && !loading) {
return "stale";
}
if (loading || inactive) {
return "disabled";
}
return "green";
}
export const RunButton = (props: {
edited: boolean;
status: RuntimeState;
needsRun: boolean;
connectionState: WebSocketState;
config: CellConfig;
onClick?: () => void;
}): JSX.Element => {
const { onClick, connectionState, needsRun, status, config, edited } = props;
const blockedStatus = status === "disabled-transitively";
const loading = status === "running" || status === "queued";
const inactive =
isAppInteractionDisabled(connectionState) ||
loading ||
(!config.disabled && blockedStatus && !edited);
const variant = computeColor({
connectionState,
needsRun,
loading,
inactive,
});
if (config.disabled) {
return (
);
}
if (!config.disabled && blockedStatus && !edited) {
return (
);
}
let tooltipMsg: React.ReactNode = "";
if (isAppInteractionDisabled(connectionState)) {
tooltipMsg = getConnectionTooltip(connectionState);
} else if (status === "queued") {
tooltipMsg = "This cell is already queued to run";
} else if (status === "running") {
tooltipMsg = "This cell is already running.";
} else {
tooltipMsg = renderShortcut("cell.run");
}
return (
);
};