/** * Loading states specific to the pull request surface — the first list, a search under way, * and a detail panel opening — use bars in the geometry of the content they stand for, pulsing * on one composited layer. Diff loading uses the shared diff-panel skeleton instead. * * The bars share the app-wide `Skeleton` tone (`muted-foreground` at low alpha, which reads on * both themes) and the single `animate-skeleton` pulse, applied once on the container so any * number of bars costs one opacity animation. */ import type { PullRequestListEntry } from "@t3tools/contracts"; import { ArrowLeftIcon } from "lucide-react"; import { cn } from "~/lib/utils"; import { formatRelativeTimeLabel } from "~/timestampFormat"; import { pullRequestLabelColor } from "./pullRequestList.logic"; import { PullRequestActorLabel, PullRequestDiffStat, pullRequestChecksStatePresentation, resolvePullRequestState, } from "./pullRequestPresentation"; function GhostBar({ className }: { className?: string | undefined }) { return
; } /** Widths cycle rather than randomize, so the ghost renders the same on every pass. */ const TITLE_WIDTHS = ["w-3/5", "w-2/5", "w-1/2", "w-2/3", "w-2/5", "w-3/5", "w-1/2"]; const META_WIDTHS = ["w-2/5", "w-1/3", "w-2/5", "w-1/4", "w-1/3", "w-2/5", "w-1/3"]; /** Rows in the list's own grid — glyph, title over meta, time over diffstat. */ export function PullRequestListGhost({ rows = 7, caption, }: { rows?: number; /** Said where the group headers speak, for the states with something to say — a search. */ caption?: string; }) { return ({caption}
) : null} {Array.from({ length: rows }, (_, index) => ({seed.baseBranch}
{seed.headBranch}
) : (
<>