Vectrum
Sign In
52 lines · 1.8 KB · TypeScript
"use client";

import { useActionState } from "react";
import { Popover, Select } from "@unlocalhosted/metalui";
import type { FormState } from "@/app/actions/types";
import { BranchIcon, ChevronDownIcon, PlayIcon } from "@/components/icons";
import { Alert, Button } from "@/components/ui";

/** "Run workflow": a popover choosing the branch to run a `workflow_dispatch` workflow on. */
export function DispatchButton({
  action,
  branches,
  defaultBranch,
}: {
  action: (prev: FormState, formData: FormData) => Promise<FormState>;
  branches: string[];
  defaultBranch: string;
}) {
  const [state, formAction, pending] = useActionState(action, undefined);
  return (
    <Popover>
      <Popover.Trigger>
        <Button type="button" icon={<PlayIcon />}>
          Run workflow
          <span aria-hidden className="-mr-1 inline-grid opacity-70">
            <ChevronDownIcon width={12} height={12} />
          </span>
        </Button>
      </Popover.Trigger>
      <Popover.Content side="bottom" align="end" className="w-[300px]">
        <Popover.Title>Run this workflow</Popover.Title>
        <Popover.Body>
          <form action={formAction} className="flex flex-col gap-3">
            <label className="flex flex-col gap-1.5">
              <span className="type-ui text-ink">Branch</span>
              <Select
                name="branch"
                aria-label="Branch"
                defaultValue={defaultBranch}
                options={branches.map((b) => ({ value: b, label: b, lead: <BranchIcon /> }))}
              />
            </label>
            {state?.error && <Alert>{state.error}</Alert>}
            <Button variant="primary" icon={<PlayIcon />} disabled={pending}>
              {pending ? "Starting…" : "Run Workflow"}
            </Button>
          </form>
        </Popover.Body>
      </Popover.Content>
    </Popover>
  );
}