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.
120 lines
4.6 KiB
Svelte
120 lines
4.6 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from "svelte";
|
|
import { Check, GitMerge, LoaderCircle, X } from "@lucide/svelte";
|
|
import type { AppLanguage, GitBranch, MergeStrategy } from "../types";
|
|
|
|
interface Props {
|
|
branch: GitBranch;
|
|
currentBranch: string;
|
|
isBusy: boolean;
|
|
language: AppLanguage;
|
|
onMerge: (strategy: MergeStrategy) => void;
|
|
onClose: () => void;
|
|
}
|
|
|
|
let {
|
|
branch,
|
|
currentBranch,
|
|
isBusy = false,
|
|
language = "en",
|
|
onMerge = () => {},
|
|
onClose = () => {},
|
|
}: Props = $props();
|
|
|
|
let strategy = $state<MergeStrategy>("default");
|
|
const isGerman = $derived(language === "de");
|
|
const options = $derived([
|
|
{
|
|
value: "default" as const,
|
|
label: isGerman ? "Standard" : "Default",
|
|
description: isGerman ? "Git wählt Fast-forward oder erstellt einen Merge-Commit." : "Git chooses fast-forward or creates a merge commit.",
|
|
},
|
|
{
|
|
value: "squash" as const,
|
|
label: "Squash",
|
|
description: isGerman ? "Fasst alle Änderungen zu einem neuen Commit zusammen." : "Combines all changes into one new commit.",
|
|
},
|
|
{
|
|
value: "ff-only" as const,
|
|
label: "Fast-forward only",
|
|
description: isGerman ? "Bricht ab, wenn ein Merge-Commit erforderlich wäre." : "Stops if a merge commit would be required.",
|
|
},
|
|
{
|
|
value: "no-ff" as const,
|
|
label: "No fast-forward",
|
|
description: isGerman ? "Erstellt immer einen eigenen Merge-Commit." : "Always creates a dedicated merge commit.",
|
|
},
|
|
]);
|
|
|
|
function submit(event: SubmitEvent) {
|
|
event.preventDefault();
|
|
if (!isBusy) onMerge(strategy);
|
|
}
|
|
|
|
function handleKeydown(event: KeyboardEvent) {
|
|
if (event.key === "Escape" && !isBusy) onClose();
|
|
}
|
|
|
|
onMount(() => {
|
|
window.addEventListener("keydown", handleKeydown);
|
|
return () => window.removeEventListener("keydown", handleKeydown);
|
|
});
|
|
</script>
|
|
|
|
<div class="dialog-backdrop app-chrome-backdrop" role="presentation">
|
|
<div class="dialog merge-branch-dialog" role="dialog" aria-modal="true" aria-labelledby="merge-branch-title" tabindex="-1">
|
|
<header class="dialog-header merge-branch-header unified-dialog-header">
|
|
<div class="merge-branch-heading unified-dialog-heading">
|
|
<span class="merge-branch-icon unified-dialog-icon" aria-hidden="true"><GitMerge size={18} /></span>
|
|
<div class="unified-dialog-text">
|
|
<span class="eyebrow">{isGerman ? "Branches zusammenführen" : "Combine branches"}</span>
|
|
<h2 id="merge-branch-title">{isGerman ? "Merge konfigurieren" : "Configure merge"}</h2>
|
|
</div>
|
|
</div>
|
|
<button class="dialog-close" type="button" onclick={onClose} disabled={isBusy} title={isGerman ? "Schließen" : "Close"}>
|
|
<X size={18} aria-hidden="true" />
|
|
</button>
|
|
</header>
|
|
|
|
<form class="merge-branch-form" onsubmit={submit}>
|
|
<div class="merge-branch-route" aria-label={isGerman ? "Merge-Richtung" : "Merge direction"}>
|
|
<div>
|
|
<span>{isGerman ? "Quell-Branch" : "Source branch"}</span>
|
|
<strong>{branch.name}</strong>
|
|
</div>
|
|
<GitMerge size={18} aria-hidden="true" />
|
|
<div>
|
|
<span>{isGerman ? "In aktuellen Branch" : "Into current branch"}</span>
|
|
<strong>{currentBranch || "HEAD"}</strong>
|
|
</div>
|
|
</div>
|
|
|
|
<fieldset class="merge-strategy-fieldset" disabled={isBusy}>
|
|
<legend>{isGerman ? "Merge-Strategie" : "Merge strategy"}</legend>
|
|
<div class="merge-strategy-grid">
|
|
{#each options as option}
|
|
<label class:active={strategy === option.value} class="merge-strategy-option">
|
|
<input type="radio" name="merge-strategy" value={option.value} bind:group={strategy} />
|
|
<span class="merge-strategy-check" aria-hidden="true">
|
|
{#if strategy === option.value}<Check size={13} />{/if}
|
|
</span>
|
|
<span class="merge-strategy-copy">
|
|
<strong>{option.label}</strong>
|
|
<small>{option.description}</small>
|
|
</span>
|
|
</label>
|
|
{/each}
|
|
</div>
|
|
</fieldset>
|
|
|
|
<div class="merge-branch-actions">
|
|
<button class="btn-secondary" type="button" onclick={onClose} disabled={isBusy}>{isGerman ? "Abbrechen" : "Cancel"}</button>
|
|
<button class="btn-primary" type="submit" disabled={isBusy}>
|
|
{#if isBusy}<LoaderCircle class="spin" size={16} aria-hidden="true" />{:else}<GitMerge size={16} aria-hidden="true" />{/if}
|
|
{isGerman ? "Branch mergen" : "Merge branch"}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|