Introduce a shared dialog header style (.unified-dialog-header) in app.css and opt dialog components into the new chrome by updating their header markup. Headers now use unified-dialog-icon and unified-dialog-text elements (and import the matching Lucide icons where needed), which standardizes icon placement, title/eyebrow layout, close button styling and responsive behavior. The Command Palette layout was adjusted to include the new header and its grid rows. The CSS is explicitly opt-in (so page/section headers remain unchanged) and includes hover/focus styles and a theme-sensitive close color variable. This commit is a UI refactor only — no API or behavior logic changes.
140 lines
6.1 KiB
Svelte
140 lines
6.1 KiB
Svelte
<script lang="ts">
|
|
import { ArrowRight, GitCompare, Info, LoaderCircle, X } from "@lucide/svelte";
|
|
import type { GitBranch, GitCommit } from "../types";
|
|
import SelectMenu from "./SelectMenu.svelte";
|
|
|
|
interface Props {
|
|
commits: GitCommit[];
|
|
branches: GitBranch[];
|
|
compareFrom: string;
|
|
compareTo: string;
|
|
canCompare: boolean;
|
|
isBusy: boolean;
|
|
operation: string;
|
|
language?: "en" | "de";
|
|
onCompareFromChange: (val: string) => void;
|
|
onCompareToChange: (val: string) => void;
|
|
onCompare: () => void;
|
|
onClose: () => void;
|
|
}
|
|
|
|
let {
|
|
commits = [],
|
|
branches = [],
|
|
compareFrom = "",
|
|
compareTo = "",
|
|
canCompare = false,
|
|
isBusy = false,
|
|
operation = "",
|
|
language = "en",
|
|
onCompareFromChange = () => {},
|
|
onCompareToChange = () => {},
|
|
onCompare = () => {},
|
|
onClose = () => {},
|
|
}: Props = $props();
|
|
|
|
let isGerman = $derived(language === "de");
|
|
|
|
function commitOptionLabel(item: GitCommit): string {
|
|
return `${item.short_hash} - ${item.summary}`;
|
|
}
|
|
|
|
function branchValue(branch: GitBranch): string {
|
|
return branch.remote ? `refs/remotes/${branch.name}` : `refs/heads/${branch.name}`;
|
|
}
|
|
|
|
let localBranches = $derived(branches.filter((branch) => !branch.remote));
|
|
let remoteBranches = $derived(branches.filter((branch) => branch.remote));
|
|
let targetCount = $derived(branches.length + commits.length);
|
|
let compareOptions = $derived([
|
|
...localBranches.map((branch) => ({
|
|
value: branchValue(branch),
|
|
label: `${branch.name}${branch.current ? (isGerman ? " (aktuell)" : " (current)") : ""}`,
|
|
group: isGerman ? "Lokale Branches" : "Local branches",
|
|
})),
|
|
...remoteBranches.map((branch) => ({
|
|
value: branchValue(branch),
|
|
label: branch.name,
|
|
group: isGerman ? "Remote-Branches" : "Remote branches",
|
|
})),
|
|
...commits.map((item) => ({
|
|
value: item.hash,
|
|
label: commitOptionLabel(item),
|
|
group: "Commits",
|
|
})),
|
|
]);
|
|
|
|
function handleSubmit(event: SubmitEvent) {
|
|
event.preventDefault();
|
|
onCompare();
|
|
}
|
|
</script>
|
|
|
|
<div
|
|
class="dialog-backdrop"
|
|
role="presentation"
|
|
>
|
|
<div class="dialog compare-select-dialog" role="dialog" aria-modal="true" aria-label={isGerman ? "Branches oder Commits vergleichen" : "Compare branches or commits"} tabindex="-1">
|
|
<header class="compare-dialog-head unified-dialog-header">
|
|
<div class="compare-dialog-title unified-dialog-heading">
|
|
<span class="compare-dialog-mark unified-dialog-icon"><GitCompare size={18} aria-hidden="true" /></span>
|
|
<div class="unified-dialog-text">
|
|
<h2>{isGerman ? "Branches oder Commits vergleichen" : "Compare branches or commits"}</h2>
|
|
<p>{isGerman ? "Zwei Repository-Stände direkt gegenüberstellen" : "Review two repository states side by side"}</p>
|
|
</div>
|
|
</div>
|
|
<button class="dialog-close" type="button" onclick={onClose} title={isGerman ? "Schließen" : "Close"} aria-label={isGerman ? "Vergleich schließen" : "Close comparison"}>
|
|
<X size={18} aria-hidden="true" />
|
|
</button>
|
|
</header>
|
|
|
|
<form class="compare-select-shell" onsubmit={handleSubmit}>
|
|
<div class="compare-select-body">
|
|
{#if targetCount < 2}
|
|
<div class="blank-state">{isGerman ? "Für einen Vergleich werden mindestens zwei Branches oder Commits benötigt." : "At least two branches or commits are needed to compare."}</div>
|
|
{:else}
|
|
<section class="compare-target-panel">
|
|
<div class="compare-target-heading">
|
|
<h3>{isGerman ? "Vergleichsbereich" : "Comparison range"}</h3>
|
|
<p>{isGerman ? "Wähle Ausgangspunkt und Ziel des Vergleichs." : "Choose the starting point and target for the comparison."}</p>
|
|
</div>
|
|
<div class="compare-form">
|
|
<label class="compare-field">
|
|
<span>{isGerman ? "Ausgangsbasis" : "Base"}</span>
|
|
<SelectMenu class="compare-target-select" value={compareFrom} options={compareOptions} placeholder={isGerman ? "Branch oder Commit wählen" : "Select a branch or commit"} showSelectedGroup disabled={isBusy} onChange={onCompareFromChange} />
|
|
</label>
|
|
|
|
<span class="compare-arrow-shell"><ArrowRight size={18} aria-hidden="true" /></span>
|
|
|
|
<label class="compare-field">
|
|
<span>{isGerman ? "Vergleichen mit" : "Compare with"}</span>
|
|
<SelectMenu class="compare-target-select" value={compareTo} options={compareOptions} placeholder={isGerman ? "Branch oder Commit wählen" : "Select a branch or commit"} showSelectedGroup disabled={isBusy} onChange={onCompareToChange} />
|
|
</label>
|
|
</div>
|
|
</section>
|
|
|
|
{#if compareFrom && compareTo && compareFrom === compareTo}
|
|
<div class="compare-target-help compare-target-warning"><Info size={15} aria-hidden="true" /><span>{isGerman ? "Wähle zwei unterschiedliche Branches oder Commits." : "Select two different branches or commits to compare."}</span></div>
|
|
{:else}
|
|
<div class="compare-target-help"><Info size={15} aria-hidden="true" /><span>{isGerman ? "Verglichen werden die vollständigen Repository-Stände. Nicht committete Änderungen im Arbeitsverzeichnis sind nicht enthalten." : "The complete repository states are compared. Uncommitted working-tree changes are not included."}</span></div>
|
|
{/if}
|
|
{/if}
|
|
</div>
|
|
<footer class="compare-select-footer">
|
|
<span>{isGerman ? `${targetCount} Ziele verfügbar` : `${targetCount} targets available`}</span>
|
|
<div>
|
|
<button class="btn-secondary" type="button" onclick={onClose}>{isGerman ? "Abbrechen" : "Cancel"}</button>
|
|
<button class="btn-primary" type="submit" disabled={!canCompare || targetCount < 2}>
|
|
{#if operation === "Comparing revisions"}
|
|
<LoaderCircle class="spin" size={16} aria-hidden="true" />
|
|
{:else}
|
|
<GitCompare size={16} aria-hidden="true" />
|
|
{/if}
|
|
{isGerman ? "Vergleich öffnen" : "Open comparison"}
|
|
</button>
|
|
</div>
|
|
</footer>
|
|
</form>
|
|
</div>
|
|
</div>
|