diff --git a/src/App.svelte b/src/App.svelte index 7505982..435115a 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -3604,8 +3604,11 @@ hasRepository={workspaceActive} {isBusy} {operation} + ahead={status?.ahead ?? 0} + behind={status?.behind ?? 0} {autoRefreshEnabled} {autoRefreshInFlight} + language={appLanguage} onFetch={fetchRepo} onPull={pullRepo} onPush={pushRepo} diff --git a/src/app.css b/src/app.css index aee954a..a396146 100644 --- a/src/app.css +++ b/src/app.css @@ -541,7 +541,7 @@ .shell { --app-titlebar-height: 42px; - --app-toolbar-height: 34px; + --app-toolbar-height: 58px; display: flex; flex-direction: column; height: 100%; @@ -648,22 +648,179 @@ height: 100%; } - /* Repo action toolbar: its own row under the repo tab bar (hidden in Repository - Management). Its own row means a narrow window can never push the window - controls out of the titlebar; overflow-x is the last-resort safety net. */ + /* Repository actions are ordered by workflow: sync, inspect/history, utilities. */ .repo-toolbar { display: flex; - align-items: stretch; + align-items: flex-end; + gap: 8px; height: var(--app-toolbar-height); + padding: 5px 8px; border: 1px solid var(--color-border-subtle); border-radius: 10px; background: rgba(16, 17, 29, 0.9); flex-shrink: 0; - overflow-x: auto; - scrollbar-width: none; + overflow: visible; user-select: none; } - .repo-toolbar::-webkit-scrollbar { display: none; } + + .repo-toolbar-sync { + display: grid; + grid-template-rows: 11px 34px; + gap: 2px; + align-self: stretch; + min-width: 0; + } + .repo-toolbar-group-label { + padding-left: 6px; + color: var(--color-ink-faint); + font-size: 8px; + font-weight: 850; + line-height: 11px; + letter-spacing: 0.12em; + text-transform: uppercase; + } + .repo-action-group { + display: flex; + align-items: stretch; + height: 34px; + min-width: 0; + border: 1px solid var(--color-border-subtle); + border-radius: 7px; + background: rgba(255,255,255,0.018); + } + .repo-action-group > .repo-action, + .repo-action-group > .repo-history-wrap > .repo-action { + border-right: 1px solid var(--color-border-subtle); + } + .repo-action-group > .repo-action:last-child, + .repo-action-group > .repo-history-wrap:last-child > .repo-action { + border-right: 0; + } + .repo-action { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + min-width: 38px; + height: 32px; + min-height: 32px; + padding: 0 12px; + border: 0; + border-radius: 0; + color: var(--color-ink-muted); + background: transparent; + font-size: 12px; + font-weight: 700; + white-space: nowrap; + cursor: pointer; + transition: color 120ms ease, background 120ms ease; + -webkit-app-region: no-drag; + } + .repo-action:first-child { border-radius: 6px 0 0 6px; } + .repo-action:last-child { border-radius: 0 6px 6px 0; } + .repo-action:only-child { border-radius: 6px; } + .repo-action:hover:not(:disabled), + .repo-action.active { + color: var(--color-ink); + background: var(--color-surface-hover); + } + .repo-action:disabled { opacity: 0.34; cursor: not-allowed; } + .repo-action.sync-primary { color: var(--color-accent); } + .repo-action.sync-primary:hover:not(:disabled) { background: rgba(90,140,248,0.1); } + .repo-action-label { font-size: 12px; font-weight: 750; } + .repo-action-count { + color: currentColor; + font-family: var(--font-mono); + font-size: 9.5px; + font-weight: 850; + } + .repo-action-count.behind { color: #7aacff; } + .repo-action-count.ahead { color: #e0a040; } + .repo-toolbar-divider { + width: 1px; + height: 30px; + margin: 0 1px 2px; + background: var(--color-border-subtle); + flex: 0 0 auto; + } + .repo-toolbar-spacer { flex: 1 1 auto; min-width: 6px; } + .repo-inspect-actions, + .repo-utility-actions { margin-bottom: 1px; } + .repo-history-wrap { position: relative; height: 32px; } + .history-trigger { border-radius: 0 6px 6px 0; } + .history-trigger .history-chevron { transition: transform 120ms ease; } + .history-trigger.active .history-chevron { transform: rotate(180deg); } + .repo-history-menu { + position: absolute; + z-index: 90; + top: calc(100% + 7px); + right: -1px; + display: grid; + width: 240px; + padding: 5px; + border: 1px solid var(--color-border); + border-radius: 9px; + background: var(--color-surface-raised); + box-shadow: 0 16px 42px rgba(0,0,0,0.36); + } + .repo-history-menu > button { + display: grid; + grid-template-columns: 24px minmax(0, 1fr); + align-items: center; + gap: 8px; + min-height: 48px; + padding: 7px 8px; + border: 0; + border-radius: 6px; + color: var(--color-ink-muted); + background: transparent; + text-align: left; + } + .repo-history-menu > button:hover { color: var(--color-ink); background: var(--color-surface-hover); } + .repo-history-menu > button > svg { color: var(--color-accent); } + .repo-history-menu > button > span { display: grid; gap: 2px; min-width: 0; } + .repo-history-menu strong { color: inherit; font-size: 11px; } + .repo-history-menu small { overflow: hidden; color: var(--color-ink-faint); font-size: 9.5px; text-overflow: ellipsis; white-space: nowrap; } + .repo-utility-actions { flex: 0 0 auto; } + .repo-action.icon-action { width: 36px; padding: 0; } + .repo-auto-toggle { + display: inline-flex; + align-items: center; + gap: 8px; + height: 32px; + min-height: 32px; + padding: 0 8px 0 10px; + border: 0; + border-radius: 0 6px 6px 0; + color: var(--color-ink-muted); + background: transparent; + font-size: 11.5px; + font-weight: 750; + } + .repo-auto-toggle:hover { color: var(--color-ink); background: var(--color-surface-hover); } + .repo-switch { + position: relative; + width: 27px; + height: 15px; + border-radius: 999px; + background: var(--color-border-input); + transition: background 140ms ease; + } + .repo-switch > span { + position: absolute; + top: 2px; + left: 2px; + width: 11px; + height: 11px; + border-radius: 50%; + background: #ffffff; + box-shadow: 0 1px 3px rgba(0,0,0,0.28); + transition: transform 140ms ease; + } + .repo-auto-toggle.active { color: #4eca76; } + .repo-auto-toggle.active .repo-switch { background: #26924f; } + .repo-auto-toggle.active .repo-switch > span { transform: translateX(12px); } + .repo-switch.busy { box-shadow: 0 0 0 3px rgba(78,202,118,0.12); } .tb-action { display: flex; @@ -5220,6 +5377,7 @@ .branch-actions { flex-direction: column; align-items: flex-end; gap: 4px; } .branch-actions button { width: 100%; } .tb-action-label { display: none; } + .repo-action-label.utility-label { display: none; } } /* Narrow: single column */ @@ -5293,4 +5451,9 @@ .dialog-files { border-right: none; border-bottom: 1px solid var(--color-border-subtle); } .branch-actions { flex-direction: row; justify-content: flex-start; } .tb-action-label { display: none; } + .repo-action-label { display: none; } + .repo-action { padding-inline: 8px; } + .repo-toolbar { gap: 5px; padding-inline: 6px; } + .repo-toolbar-divider { margin-inline: 0; } + .repo-auto-toggle { padding-left: 7px; gap: 6px; } } diff --git a/src/lib/RepoToolbar.svelte b/src/lib/RepoToolbar.svelte index 0b68148..e7062b4 100644 --- a/src/lib/RepoToolbar.svelte +++ b/src/lib/RepoToolbar.svelte @@ -1,11 +1,26 @@ -