This update introduces functionality for resizing various panels in the UI, including the left sidebar, branch panel, stash panel, and file history. It also adds state persistence for panel sizes and collapsed states using local storage, improving user experience by maintaining preferences across sessions. - Implemented resizing functionality for multiple UI panels - Added local storage support for panel dimensions and collapsed states - Enhanced accessibility features for panel controls
139 lines
4.3 KiB
Svelte
139 lines
4.3 KiB
Svelte
<script lang="ts">
|
|
import { Archive, ChevronDown, ChevronRight, Download, Trash2, Upload } from "@lucide/svelte";
|
|
import type { GitStash } from "../types";
|
|
|
|
interface Props {
|
|
stashes: GitStash[];
|
|
changedCount: number;
|
|
hasRepository: boolean;
|
|
isBusy: boolean;
|
|
onPush: (message: string, includeUntracked: boolean) => void;
|
|
onApply: (stash: GitStash) => void;
|
|
onPop: (stash: GitStash) => void;
|
|
onDrop: (stash: GitStash) => void;
|
|
collapsed?: boolean;
|
|
onToggleCollapsed?: () => void;
|
|
}
|
|
|
|
let {
|
|
stashes = [],
|
|
changedCount = 0,
|
|
hasRepository = false,
|
|
isBusy = false,
|
|
onPush = () => {},
|
|
onApply = () => {},
|
|
onPop = () => {},
|
|
onDrop = () => {},
|
|
collapsed = false,
|
|
onToggleCollapsed = () => {},
|
|
}: Props = $props();
|
|
|
|
let message = $state("");
|
|
let includeUntracked = $state(true);
|
|
|
|
function submitPush() {
|
|
onPush(message, includeUntracked);
|
|
message = "";
|
|
}
|
|
|
|
function stashTitle(stash: GitStash): string {
|
|
return stash.message || stash.selector;
|
|
}
|
|
</script>
|
|
|
|
<section class="panel stash-panel overflow-hidden" class:collapsed aria-label="Git stash">
|
|
<div class="section-head">
|
|
<div>
|
|
<span class="eyebrow">Stash</span>
|
|
<h2 class="mt-0.5 text-ink text-base font-bold leading-tight">Shelved changes</h2>
|
|
</div>
|
|
<div class="stash-head-actions">
|
|
<span class="pill pill-count">{stashes.length}</span>
|
|
<button
|
|
class="stash-toggle panel-collapse-toggle"
|
|
type="button"
|
|
onclick={onToggleCollapsed}
|
|
aria-expanded={!collapsed}
|
|
title={collapsed ? "Expand stash panel" : "Collapse stash panel"}
|
|
aria-label={collapsed ? "Expand stash panel" : "Collapse stash panel"}
|
|
>
|
|
{#if collapsed}
|
|
<ChevronRight size={14} aria-hidden="true" />
|
|
{:else}
|
|
<ChevronDown size={14} aria-hidden="true" />
|
|
{/if}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{#if collapsed}
|
|
<!-- collapsed -->
|
|
{:else if !hasRepository}
|
|
<div class="blank-state">No repository loaded.</div>
|
|
{:else}
|
|
<div class="stash-create">
|
|
<input
|
|
class="stash-input"
|
|
type="text"
|
|
bind:value={message}
|
|
placeholder="Optional message"
|
|
disabled={isBusy || changedCount === 0}
|
|
onkeydown={(event) => {
|
|
if (event.key === "Enter" && changedCount > 0 && !isBusy) submitPush();
|
|
}}
|
|
/>
|
|
<label class="stash-check">
|
|
<input type="checkbox" bind:checked={includeUntracked} disabled={isBusy || changedCount === 0} />
|
|
Untracked
|
|
</label>
|
|
<button
|
|
class="btn-sm stash-save-button"
|
|
type="button"
|
|
onclick={submitPush}
|
|
disabled={isBusy || changedCount === 0}
|
|
title="Save current working tree changes to a stash"
|
|
>
|
|
<Archive size={14} aria-hidden="true" />
|
|
Stash
|
|
</button>
|
|
</div>
|
|
|
|
{#if stashes.length === 0}
|
|
<div class="blank-state stash-empty">No stashes saved.</div>
|
|
{:else}
|
|
<div class="stash-list">
|
|
{#each stashes as stash (stash.selector)}
|
|
<article class="stash-row">
|
|
<div class="stash-row-main">
|
|
<strong title={stashTitle(stash)}>{stashTitle(stash)}</strong>
|
|
<span>
|
|
{stash.selector}
|
|
{#if stash.branch}
|
|
on {stash.branch}
|
|
{/if}
|
|
{#if stash.date}
|
|
- {stash.date}
|
|
{/if}
|
|
</span>
|
|
</div>
|
|
<div class="stash-actions">
|
|
<button class="btn-sm" type="button" onclick={() => onApply(stash)} disabled={isBusy} title="Apply stash and keep it">
|
|
<Download size={13} aria-hidden="true" />
|
|
Apply
|
|
</button>
|
|
<button class="btn-sm" type="button" onclick={() => onPop(stash)} disabled={isBusy} title="Apply stash and remove it if successful">
|
|
<Upload size={13} aria-hidden="true" />
|
|
Pop
|
|
</button>
|
|
<button class="btn-sm danger" type="button" onclick={() => onDrop(stash)} disabled={isBusy} title="Delete stash">
|
|
<Trash2 size={13} aria-hidden="true" />
|
|
Drop
|
|
</button>
|
|
</div>
|
|
</article>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
{/if}
|
|
</section>
|