ReleaseButton
uses useState
Release a package from the studio (makeRelease), asking first, since a release names a point of history for good;
then the page shows it among the releases made, and a toast says so (or why not).
import { refresh } from "#codebase/tcmts/react"; import { toasts } from "#codebase/tcmts/share"; import { makeRelease } from "#codebase/tcmts/studio"; import { useState } from "react"; import { Button, Dialog, DialogTrigger, Heading, Popover } from "react-aria-components"; export function ReleaseButton({ name, version }: { name: string; version: string }) { const [busy, setBusy] = useState(false); return ( <DialogTrigger> <Button className="btn primary" isPending={busy}> {busy ? "Releasing…" : `Release ${version}`} </Button> <Popover className="menu-pop getit" placement="bottom end" offset={6}> <Dialog className="getit-body" aria-label={`Release ${name} ${version}`}> {({ close }) => ( <> <Heading slot="title" className="getit-title"> Release {name} {version}? </Heading> <p> It names this point of {name}'s history {version} for good, with these notes. It can't be made again, or changed. </p> <div className="actions"> <Button className="btn" onPress={close}> Not yet </Button> <Button className="btn primary" onPress={async () => { close(); setBusy(true); try { toasts.add({ title: await makeRelease(name), tone: "ok" }, { timeout: 6000 }); refresh(); } catch (e) { toasts.add( { title: `Couldn't release ${name}`, description: (e as Error).message, tone: "bad", }, { timeout: 10000 }, ); } setBusy(false); }} > Release {version} </Button> </div> </> )} </Dialog> </Popover> </DialogTrigger> ); }