feat(repo-tabs): replace tab bar with workspace navigation
Replace the legacy repository tab bar with a compact workspace navigation that groups primary views and exposes a dedicated "Repositories" action. The repository list is shown only when the repository view is active and supports per-repo selection and closing. Also add a Repositories open handler in the app to select the active repo or prompt to choose a repository folder when none is available. - Introduce top-level navigation (Dashboard, PRs, Issues, Repositories) - Add onOpenRepositories hook and app logic to select or choose repo - Update icons, styles, and accessibility attributes for the nav
This commit is contained in:
@@ -5396,6 +5396,11 @@
|
||||
{isBusy}
|
||||
language={appLanguage}
|
||||
onOpenManagement={openRepoManagement}
|
||||
onOpenRepositories={() => {
|
||||
const path = repoTabs.find(tab => sameRepoPath(tab.path, activeRepoPath))?.path ?? repoTabs[0]?.path;
|
||||
if (path) return selectRepoTab(path);
|
||||
return chooseRepositoryFolder();
|
||||
}}
|
||||
onOpenReviewCenter={() => openReviewCenter()}
|
||||
onOpenIssues={() => { activeView = "issues"; }}
|
||||
isActive={(path) => activeView === "repository" && sameRepoPath(activeRepoPath, path)}
|
||||
|
||||
+43
-64
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { CircleDot, Folder, GitBranch, GitPullRequest, Plus, X } from "@lucide/svelte";
|
||||
import { Columns3, Database, Folder, House, GitPullRequest, Plus, X } from "@lucide/svelte";
|
||||
|
||||
interface RepositoryTabItem {
|
||||
path: string;
|
||||
@@ -12,6 +12,7 @@
|
||||
export let isBusy: boolean = false;
|
||||
export let language: "en" | "de" = "en";
|
||||
export let onOpenManagement: () => void = () => {};
|
||||
export let onOpenRepositories: () => void | Promise<void> = () => {};
|
||||
export let onOpenIssues: () => void = () => {};
|
||||
export let onOpenReviewCenter: () => void = () => {};
|
||||
export let isActive: (path: string) => boolean = () => false;
|
||||
@@ -21,70 +22,48 @@
|
||||
export let onAdd: () => void | Promise<void> = () => {};
|
||||
</script>
|
||||
|
||||
<header class="repo-tabbar" aria-label={language === "de" ? "Repository-Reiter" : "Repository tabs"}>
|
||||
<button
|
||||
class="repo-tab management"
|
||||
class:active={activeView === "management"}
|
||||
type="button"
|
||||
onclick={onOpenManagement}
|
||||
disabled={isBusy}
|
||||
title={language === "de" ? "Repository-Verwaltung" : "Repository Management"}
|
||||
aria-label={language === "de" ? "Repository-Verwaltung" : "Repository Management"}
|
||||
>
|
||||
<Folder size={15} aria-hidden="true" />
|
||||
</button>
|
||||
|
||||
<div class="repo-tabs-scroll">
|
||||
<div class="repo-tab-wrap review-center-tab" class:active={activeView === "review-center"} role="presentation">
|
||||
<button class="repo-tab" type="button" onclick={onOpenReviewCenter} disabled={isBusy} title="Review Center" aria-label="Review Center">
|
||||
<GitPullRequest size={13} aria-hidden="true" />
|
||||
<span>PR</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="repo-tab-wrap" class:active={activeView === "issues"} role="presentation">
|
||||
<button class="repo-tab" type="button" onclick={onOpenIssues} disabled={isBusy} title="Issues" aria-label="Issues">
|
||||
<CircleDot size={13} aria-hidden="true" /><span>Issues</span>
|
||||
</button>
|
||||
</div>
|
||||
<header class="workspace-navigation">
|
||||
<nav class="global-navigation" aria-label={language === "de" ? "Hauptnavigation" : "Main navigation"}>
|
||||
<button type="button" class:active={activeView === "management"} aria-current={activeView === "management" ? "page" : undefined} disabled={isBusy} onclick={onOpenManagement}><House size={17}/><span>Dashboard</span></button>
|
||||
<button type="button" class:active={activeView === "repository"} aria-current={activeView === "repository" ? "page" : undefined} disabled={isBusy} onclick={onOpenRepositories}><Database size={17}/><span>Repositories</span></button>
|
||||
<button type="button" class:active={activeView === "review-center"} aria-current={activeView === "review-center" ? "page" : undefined} disabled={isBusy} onclick={onOpenReviewCenter}><GitPullRequest size={17}/><span>Pull Requests</span></button>
|
||||
<button type="button" class:active={activeView === "issues"} aria-current={activeView === "issues" ? "page" : undefined} disabled={isBusy} onclick={onOpenIssues}><Columns3 size={17}/><span>Issues & Boards</span></button>
|
||||
</nav>
|
||||
{#if activeView === "repository"}
|
||||
<nav class="repository-navigation" aria-label={language === "de" ? "Geöffnete Repositories" : "Open repositories"}>
|
||||
{#each repoTabs as repo (repo.path)}
|
||||
<div
|
||||
class="repo-tab-wrap"
|
||||
class:active={isActive(repo.path)}
|
||||
role="presentation"
|
||||
oncontextmenu={(event) => onContextMenu(repo.path, event)}
|
||||
>
|
||||
<button
|
||||
class="repo-tab"
|
||||
type="button"
|
||||
onclick={() => onSelect(repo.path)}
|
||||
disabled={isBusy}
|
||||
title={repo.path}
|
||||
>
|
||||
<GitBranch size={13} aria-hidden="true" />
|
||||
<span>{repo.name}</span>
|
||||
</button>
|
||||
<button
|
||||
class="repo-tab-close"
|
||||
type="button"
|
||||
onclick={(event) => onClose(repo.path, event)}
|
||||
disabled={isBusy}
|
||||
aria-label={language === "de" ? `${repo.name} schließen` : `Close ${repo.name}`}
|
||||
title={language === "de" ? "Repository-Tab schließen" : "Close repository tab"}
|
||||
>
|
||||
<X size={11} aria-hidden="true" />
|
||||
</button>
|
||||
<div class="repository-tab" class:active={isActive(repo.path)} role="presentation" oncontextmenu={(event) => onContextMenu(repo.path, event)}>
|
||||
<button class="repository-select" type="button" onclick={() => onSelect(repo.path)} disabled={isBusy} title={repo.path} aria-current={isActive(repo.path) ? "page" : undefined}><Folder size={16}/><span>{repo.name}</span></button>
|
||||
<button class="repository-close" type="button" onclick={(event) => onClose(repo.path, event)} disabled={isBusy} aria-label={language === "de" ? `${repo.name} schließen` : `Close ${repo.name}`}><X size={13}/></button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="repo-tab-add"
|
||||
type="button"
|
||||
onclick={onAdd}
|
||||
disabled={isBusy}
|
||||
title={language === "de" ? "Repository-Ordner öffnen" : "Open repository folder"}
|
||||
aria-label={language === "de" ? "Repository-Ordner öffnen" : "Open repository folder"}
|
||||
>
|
||||
<Plus size={15} aria-hidden="true" />
|
||||
</button>
|
||||
<button class="repository-add" type="button" onclick={onAdd} disabled={isBusy} title={language === "de" ? "Repository-Ordner öffnen" : "Open repository folder"} aria-label={language === "de" ? "Repository-Ordner öffnen" : "Open repository folder"}><Plus size={18}/></button>
|
||||
</nav>
|
||||
{/if}
|
||||
</header>
|
||||
|
||||
<style>
|
||||
.workspace-navigation{flex:0 0 auto;min-width:0;background:var(--app-bg);color:var(--color-ink-muted);font-family:var(--font-sans);border-bottom:1px solid var(--color-border-subtle)}
|
||||
.global-navigation{display:flex;align-items:stretch;gap:2px;min-height:38px;padding:0 5px;overflow-x:auto;scrollbar-width:thin;border-bottom:1px solid var(--color-border-subtle)}
|
||||
button{font:inherit;cursor:pointer;color:inherit;background:transparent;border:0;box-shadow:none}
|
||||
button:disabled{opacity:.45;cursor:default}
|
||||
button:focus-visible{outline:2px solid var(--color-accent);outline-offset:-3px}
|
||||
.global-navigation button{position:relative;display:flex;flex:0 0 auto;align-items:center;gap:7px;padding:0 10px;min-height:38px;font-size:13px;white-space:nowrap}
|
||||
.global-navigation button:hover:not(:disabled){background:var(--color-surface-hover);color:var(--color-ink)}
|
||||
.global-navigation button.active{color:var(--color-ink);font-weight:600}
|
||||
.global-navigation button.active::after{position:absolute;content:"";height:2px;bottom:0;left:12px;right:12px;background:var(--color-accent)}
|
||||
.global-navigation button.active>:global(svg){color:var(--color-accent)}
|
||||
.repository-navigation{display:flex;align-items:stretch;gap:4px;min-height:34px;padding:4px 5px 0;overflow-x:auto;scrollbar-width:thin;background:color-mix(in srgb,var(--color-surface) 45%,var(--app-bg))}
|
||||
.repository-tab{display:flex;flex:0 0 auto;align-items:center;min-width:100px;max-width:250px;border:1px solid var(--color-border);border-bottom:0;border-radius:5px 5px 0 0;background:var(--app-bg)}
|
||||
.repository-tab.active{background:var(--color-surface-raised);border-color:var(--color-border-input);color:var(--color-ink)}
|
||||
.repository-tab:hover{background:var(--color-surface-hover)}
|
||||
.repository-select{display:flex;flex:1;min-width:0;align-items:center;gap:7px;min-height:29px;padding:0 9px;font-size:12px;text-align:left}
|
||||
.repository-select span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.repository-select>:global(svg){flex-shrink:0}
|
||||
.repository-tab.active .repository-select{font-weight:600}
|
||||
.repository-close{display:grid;place-items:center;flex:0 0 24px;height:24px;margin-right:2px;color:var(--color-ink-dim)}
|
||||
.repository-close:hover:not(:disabled){color:var(--color-ink);background:var(--color-surface-hover)}
|
||||
.repository-add{display:grid;place-items:center;flex:0 0 32px;min-height:29px;border:1px solid var(--color-border);border-bottom:0;border-radius:5px 5px 0 0}
|
||||
.repository-add:hover:not(:disabled){color:var(--color-accent);background:var(--color-surface-hover)}
|
||||
@media(max-width:640px){.global-navigation{gap:0;padding:0 4px}.global-navigation button{gap:7px;padding:0 10px;font-size:12px;min-height:38px}.global-navigation{min-height:38px}}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user