66 lines · 2.3 KB
import { useDemoTimeline } from "~/hooks/use-demo-timeline";
import { Badge } from "~/ui/Badge";
import { StatusDot } from "~/ui/StatusDot";
import { cn } from "~/utils/cn";
import { DemoWindow } from "../DemoWindow";

const STEPS = 4;
const INTERVAL_MS = 1200;

const DEPLOYS = [
  { ref: "pr-131", sha: "e5d2a90", url: "pr-131--docs--acme.sites.example", env: "preview", from: 1 },
  { ref: "main", sha: "b72d0e4", url: "docs.acme.example", env: "production", from: 2 },
  { ref: "main", sha: "7c1e04b", url: "docs.acme.example", env: "production", from: 0 },
] as const;

function liveSha(step: number): string {
  if (step >= STEPS) return "7c1e04b";
  return step >= STEPS - 1 ? "b72d0e4" : "7c1e04b";
}

export function HostingDemo({ className }: { className?: string }) {
  const step = useDemoTimeline(STEPS, INTERVAL_MS);
  const live = liveSha(step);
  return (
    <DemoWindow
      title="acme/docs · deployments"
      label="Deployments for a preview and production, then an instant rollback"
      className={className}
    >
      <ul className="divide-y divide-kumo-hairline">
        {DEPLOYS.map((deploy) => {
          const isLive = deploy.env === "production" && deploy.sha === live;
          const building = deploy.from === step;
          return (
            <li
              key={deploy.sha}
              className={cn(
                "flex items-center gap-3 px-4 py-3 transition-opacity",
                step >= deploy.from ? "opacity-100" : "opacity-0",
              )}