StartAppButton
uses window
Start an app (startApp, as tcm dev): it's listed as running, and opens, once it listens.
import { refresh } from "#codebase/tcmts/react"; import { toasts } from "#codebase/tcmts/share"; import { startApp } from "#codebase/tcmts/studio"; import { useState } from "react"; import { Button } from "react-aria-components"; export function StartAppButton({ name }: { name: string }) { const [busy, setBusy] = useState(false); return ( <Button className="btn small" isPending={busy} onPress={async () => { setBusy(true); try { const at = await startApp(name); if (/^https?:/.test(at)) { toasts.add( { title: `${name} is running`, description: at, tone: "ok" }, { timeout: 5000 }, ); window.open(at, "_blank", "noopener"); } else toasts.add({ title: `${name} is ${at}` }, { timeout: 8000 }); refresh(); } catch (e) { toasts.add( { title: `Couldn't start ${name}`, description: (e as Error).message, tone: "bad" }, { timeout: 12000 }, ); } setBusy(false); }} > {busy ? "Starting…" : "Start"} </Button> ); }