Skip to content
68 linesCodeBlameRaw
1import type { GithubRepoLink } from "@g1t/contracts";
2import { siGithub } from "simple-icons";
3
4import { TimeAgo } from "./ui";
5import { Button } from "./ui/button";
6import { Card } from "./ui/card";
7
8/** GitHub's mark (from Simple Icons), for the buttons that go there. */
9export function GithubMark({ className = "size-4" }: { className?: string }) {
10 return (
11 <svg viewBox="0 0 24 24" aria-hidden="true" fill="currentColor" className={className}>
12 <path d={siGithub.path} />
13 </svg>
14 );
15}
16
17/**
18 * "Continue with GitHub": a full page load to /auth/github, which sends the
19 * browser on to GitHub.
20 */
21export function ContinueWithGithub({ href, label = "Continue with GitHub" }: { href: string; label?: string }) {
22 return (
23 <Button asChild variant="outline" className="w-full">
24 <a href={href}>
25 <GithubMark />
26 {label}
27 </a>
28 </Button>
29 );
30}
31
32/** The rule between "Continue with GitHub" and the form below it. */
33export function OrDivider() {
34 return (
35 <div className="my-6 flex items-center gap-3 text-xs text-faint">
36 <span className="h-px grow bg-line" />
37 or
38 <span className="h-px grow bg-line" />
39 </div>
40 );
41}
42
43/**
44 * Where a repository's code was imported from on GitHub, on its overview,
45 * and when. A repository that stays in step with GitHub says so beside its
46 * name instead, and is managed under Settings → Mirroring.
47 */
48export function GithubLinkStrip({ link }: { link: GithubRepoLink }) {
49 return (
50 <Card tone="plain" radius="lg" className="flex flex-wrap items-center gap-x-3 gap-y-1 px-4 py-2.5 text-sm">
51 <span className="flex min-w-0 items-start gap-2 text-muted">
52 <GithubMark className="mt-0.5 size-4 shrink-0" />
53 <span className="min-w-0">
54 Imported from{" "}
55 <a href={`https://github.com/${link.fullName}`} className="font-mono break-all text-fg hover:text-accent" target="_blank" rel="noreferrer">
56 github.com/{link.fullName}
57 </a>
58 </span>
59 </span>
60 {link.syncedAt && (
61 <span className="text-xs text-faint">
62 copied <TimeAgo at={link.syncedAt} />
63 </span>
64 )}
65 {link.lastError && <p className="w-full text-xs text-warn">{link.lastError}</p>}
66 </Card>
67 );
68}