Files
GitLite/src/lib/components/RenameBranchDialog.svelte
T
Christoph d26d2ac982 refactor(dialogs): add unified dialog header chrome and opt-in markup
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.
2026-09-11 22:50:31 +02:00

103 lines
3.3 KiB
Svelte

<script lang="ts">
import { GitBranch, LoaderCircle, X } from "@lucide/svelte";
import type { GitBranch as GitBranchInfo } from "../types";
interface Props {
branch: GitBranchInfo;
isBusy: boolean;
onRename: (name: string) => void;
onClose: () => void;
}
let {
branch,
isBusy = false,
onRename = () => {},
onClose = () => {},
}: Props = $props();
let name = $state("");
function remoteName(branch: GitBranchInfo): string {
if (!branch.remote) return "";
const slash = branch.name.indexOf("/");
return slash > 0 ? branch.name.slice(0, slash) : branch.name;
}
function editableName(branch: GitBranchInfo): string {
if (!branch.remote) return branch.name;
const slash = branch.name.indexOf("/");
return slash >= 0 ? branch.name.slice(slash + 1) : branch.name;
}
let originalName = $derived(editableName(branch));
let remote = $derived(remoteName(branch));
$effect(() => {
name = originalName;
});
function submit(event: SubmitEvent) {
event.preventDefault();
const value = name.trim();
if (!value || value === originalName) return;
onRename(value);
}
</script>
<div
class="dialog-backdrop"
role="presentation"
>
<div class="dialog rename-branch-dialog" role="dialog" aria-modal="true" aria-label={branch.remote ? "Rename remote branch" : "Rename branch"} tabindex="-1">
<header class="dialog-header unified-dialog-header">
<span class="unified-dialog-icon" aria-hidden="true"><GitBranch size={18} /></span>
<div class="unified-dialog-text">
<span class="eyebrow">{branch.remote ? "Rename remote branch" : "Rename branch"}</span>
<h2 class="mt-0.5 text-ink text-base font-bold leading-tight">{branch.name}</h2>
</div>
<button class="dialog-close" type="button" onclick={onClose} title="Close">
<X size={18} aria-hidden="true" />
</button>
</header>
<form class="rename-branch-form" onsubmit={submit}>
<label class="new-branch-field">
<span>Branch name</span>
<div class:remote-branch-name-field={branch.remote}>
{#if branch.remote}<strong>{remote}/</strong>{/if}
<!-- svelte-ignore a11y_autofocus -->
<input
bind:value={name}
autocomplete="off"
spellcheck="false"
disabled={isBusy}
autofocus
/>
</div>
</label>
{#if branch.remote}
<p class="rename-remote-note">
Gitty creates <strong>{remote}/{name.trim() || "new-name"}</strong> and removes
<strong>{branch.name}</strong> in one atomic push. The operation stops if the remote changed in the meantime.
</p>
{/if}
<div class="new-branch-actions">
<button class="btn-secondary" type="button" onclick={onClose} disabled={isBusy}>
Cancel
</button>
<button class="btn-primary" type="submit" disabled={isBusy || name.trim().length === 0 || name.trim() === originalName}>
{#if isBusy}
<LoaderCircle class="spin" size={16} aria-hidden="true" />
{:else}
<GitBranch size={16} aria-hidden="true" />
{/if}
{branch.remote ? "Rename on remote" : "Rename"}
</button>
</div>
</form>
</div>
</div>