This repository has no description
1<script lang="ts">
2 import Download from "$icon/download";
3 import FoldVertical from "$icon/fold-vertical";
4 import PanelLeft from "$icon/panel-left";
5 import SquareSplitHorizontal from "$icon/square-split-horizontal";
6 import SquareSplitVertical from "$icon/square-split-vertical";
7 import UnfoldVertical from "$icon/unfold-vertical";
8 import type { DiffStat } from "$lib/api/diff";
9 import type { DiffStyle } from "./pierre";
10 import Button from "$lib/components/ui/Button.svelte";
11 import ButtonGroup from "$lib/components/ui/ButtonGroup.svelte";
12 import type { Snippet } from "svelte";
13 import DiffStatPill from "./DiffStatPill.svelte";
14
15 interface Props {
16 stat?: DiffStat;
17 fileCount: number;
18 // side-by-side or stacked, persisted by the route in ?diff=
19 diffStyle?: DiffStyle;
20 // raw .patch/.diff targets, only present for full-hash refs
21 downloadUrls?: { patch: string; diff: string };
22 // the sidebar can be hidden to give diffs the room
23 filesOpen?: boolean;
24 onToggleFiles?: () => void;
25 allOpen?: boolean;
26 onSetAllOpen?: (open: boolean) => void;
27 // round/interdiff indicator slot, sits after the stats
28 center?: Snippet;
29 // subscription-toggle slot, pinned to the far end (pull review panel)
30 actions?: Snippet;
31 }
32
33 let {
34 stat,
35 fileCount,
36 diffStyle = "unified",
37 downloadUrls,
38 filesOpen = true,
39 onToggleFiles,
40 allOpen = true,
41 onSetAllOpen,
42 center,
43 actions
44 }: Props = $props();
45</script>
46
47<div
48 class="sticky top-[env(safe-area-inset-top)] z-10 flex h-12 items-center gap-2 bg-background-canvas py-2"
49>
50 {#if onToggleFiles}
51 <Button
52 size="sm"
53 icon={PanelLeft}
54 onclick={onToggleFiles}
55 aria-expanded={filesOpen}
56 title="Toggle file list"
57 class="hidden md:inline-flex"
58 />
59 {/if}
60
61 {#if stat}
62 <DiffStatPill {stat} />
63 {/if}
64 <span class="hidden typography-paragraph-small text-foreground-muted md:inline-flex">
65 {fileCount} changed file{fileCount === 1 ? "" : "s"}
66 </span>
67
68 {@render center?.()}
69
70 <div class="grow"></div>
71
72 {#if downloadUrls}
73 <!-- below md these crowd the topbar into page-level horizontal scroll -->
74 <ButtonGroup spaced class="hidden md:inline-flex">
75 <Button href={downloadUrls.patch as "/"} data-sveltekit-reload size="sm" icon={Download}
76 >.patch</Button
77 >
78 <Button href={downloadUrls.diff as "/"} data-sveltekit-reload size="sm" icon={Download}
79 >.diff</Button
80 >
81 </ButtonGroup>
82 {/if}
83
84 {#if onSetAllOpen}
85 <Button
86 size="sm"
87 icon={allOpen ? FoldVertical : UnfoldVertical}
88 onclick={() => onSetAllOpen(!allOpen)}
89 >
90 <span class="hidden md:inline">{allOpen ? "Collapse all" : "Expand all"}</span>
91 </Button>
92 {/if}
93
94 <ButtonGroup>
95 <Button
96 href={"?diff=unified" as "/"}
97 data-sveltekit-replacestate
98 data-sveltekit-noscroll
99 size="sm"
100 variant={diffStyle === "split" ? "ghost" : "default"}
101 icon={SquareSplitVertical}
102 aria-label="Unified diff"
103 title="Unified diff"
104 />
105 <Button
106 href={"?diff=split" as "/"}
107 data-sveltekit-replacestate
108 data-sveltekit-noscroll
109 size="sm"
110 variant={diffStyle === "split" ? "default" : "ghost"}
111 icon={SquareSplitHorizontal}
112 aria-label="Split diff"
113 title="Split diff"
114 />
115 </ButtonGroup>
116
117 {@render actions?.()}
118</div>