Compare commits
3
Commits
44547f507a
...
2026.8.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4533f8aa38 | ||
|
|
f0bd74be4e | ||
|
|
79f4ec21e4 |
+5
-1
@@ -1179,7 +1179,8 @@
|
||||
root.dataset.appearance = next;
|
||||
const customProperties = [
|
||||
"--app-bg", "--app-button-bg", "--app-input-bg", "--app-dialog-bg", "--app-dialog-chrome",
|
||||
"--app-settings-row-bg", "--color-surface", "--color-surface-alt", "--color-surface-dim",
|
||||
"--app-dialog-backdrop", "--app-dialog-shadow", "--app-panel-shadow", "--app-settings-row-bg",
|
||||
"--color-surface", "--color-surface-alt", "--color-surface-dim",
|
||||
"--color-surface-hover", "--color-surface-raised", "--color-surface-solid", "--color-border",
|
||||
"--color-border-subtle", "--color-border-input", "--color-primary", "--color-primary-dark",
|
||||
"--color-accent", "--color-ink", "--color-ink-muted", "--color-ink-faint", "--color-ink-dim",
|
||||
@@ -1195,6 +1196,9 @@
|
||||
"--app-input-bg": `color-mix(in srgb, ${surface} 88%, white)`,
|
||||
"--app-dialog-bg": surface,
|
||||
"--app-dialog-chrome": `color-mix(in srgb, ${surface} 90%, ${background})`,
|
||||
"--app-dialog-backdrop": `color-mix(in srgb, ${background} 72%, transparent)`,
|
||||
"--app-dialog-shadow": `0 24px 68px color-mix(in srgb, ${text} 24%, transparent), 0 2px 12px color-mix(in srgb, ${text} 12%, transparent)`,
|
||||
"--app-panel-shadow": `0 18px 48px color-mix(in srgb, ${text} 18%, transparent), inset 0 1px 0 color-mix(in srgb, ${surface} 88%, white)`,
|
||||
"--app-settings-row-bg": `color-mix(in srgb, ${surface} 92%, ${background})`,
|
||||
"--color-surface": surface,
|
||||
"--color-surface-alt": `color-mix(in srgb, ${surface} 82%, ${background})`,
|
||||
|
||||
+149
@@ -8523,3 +8523,152 @@ input:focus, textarea:focus, select:focus { box-shadow: 0 0 0 3px color-mix(in s
|
||||
:root[data-appearance="custom"] .graph-gutter {
|
||||
background: var(--color-surface-dim);
|
||||
}
|
||||
|
||||
/* Branch visibility dialog ---------------------------------------------
|
||||
Local and remote branches share one visual and interaction language. */
|
||||
.branch-filter-backdrop,
|
||||
:root[data-theme="light"] .branch-filter-backdrop {
|
||||
padding: 24px;
|
||||
background: var(--app-dialog-backdrop);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.branch-filter-dialog,
|
||||
:root[data-theme="light"] .branch-filter-dialog {
|
||||
width: min(560px, 100%);
|
||||
max-height: min(680px, calc(100vh - 48px));
|
||||
border-color: var(--color-border);
|
||||
background: var(--app-dialog-bg);
|
||||
box-shadow: var(--app-dialog-shadow);
|
||||
}
|
||||
|
||||
.branch-filter-dialog-head {
|
||||
min-height: 64px;
|
||||
padding: 12px 14px;
|
||||
border-bottom-color: var(--color-border);
|
||||
background: var(--app-dialog-chrome);
|
||||
}
|
||||
|
||||
.branch-filter-dialog-head h3 {
|
||||
color: var(--color-ink);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.branch-filter-summary {
|
||||
min-height: 48px;
|
||||
padding: 8px 14px;
|
||||
border-bottom-color: var(--color-border);
|
||||
color: var(--color-ink-muted);
|
||||
background: var(--color-surface-dim);
|
||||
}
|
||||
|
||||
.branch-filter-actions button {
|
||||
min-height: 28px;
|
||||
border-color: var(--color-border);
|
||||
color: var(--color-ink-muted);
|
||||
background: var(--color-surface-raised);
|
||||
}
|
||||
|
||||
.branch-filter-actions button:hover:not(:disabled) {
|
||||
border-color: var(--color-border-input);
|
||||
color: var(--color-ink);
|
||||
background: var(--color-surface-hover);
|
||||
}
|
||||
|
||||
.branch-filter-dialog-list {
|
||||
gap: 8px;
|
||||
padding: 10px;
|
||||
background: var(--color-surface-alt);
|
||||
}
|
||||
|
||||
.branch-filter-group {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
}
|
||||
|
||||
.branch-filter-group-toggle {
|
||||
display: grid;
|
||||
grid-template-columns: 16px minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
min-height: 36px;
|
||||
padding: 0 10px;
|
||||
border: 0;
|
||||
color: var(--color-ink-muted);
|
||||
background: var(--color-surface-dim);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.branch-filter-group-toggle:hover:not(:disabled) {
|
||||
color: var(--color-ink);
|
||||
background: var(--color-surface-hover);
|
||||
}
|
||||
|
||||
.branch-filter-group-toggle > svg {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.branch-filter-group-toggle > span {
|
||||
font-size: 10px;
|
||||
font-weight: 850;
|
||||
letter-spacing: 0.09em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.branch-filter-group-toggle > em {
|
||||
min-width: 34px;
|
||||
padding: 2px 5px;
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
color: var(--color-ink-faint);
|
||||
background: var(--color-surface-raised);
|
||||
font-size: 9px;
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.branch-filter-group-list {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
padding: 6px;
|
||||
border-top: 1px solid var(--color-border-subtle);
|
||||
}
|
||||
|
||||
.branch-filter-option,
|
||||
:root[data-theme="light"] .branch-filter-option,
|
||||
:root[data-theme="light"] .branch-filter-option.remote {
|
||||
min-height: 34px;
|
||||
border-color: color-mix(in srgb, var(--color-accent) 32%, var(--color-border));
|
||||
color: var(--color-ink);
|
||||
background: color-mix(in srgb, var(--color-accent) 8%, var(--color-surface-raised));
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.branch-filter-option:hover,
|
||||
:root[data-theme="light"] .branch-filter-option:hover {
|
||||
border-color: color-mix(in srgb, var(--color-accent) 52%, var(--color-border));
|
||||
color: var(--color-ink);
|
||||
background: color-mix(in srgb, var(--color-accent) 13%, var(--color-surface-hover));
|
||||
}
|
||||
|
||||
.branch-filter-option.muted,
|
||||
:root[data-theme="light"] .branch-filter-option.muted {
|
||||
border-color: var(--color-border-subtle);
|
||||
color: var(--color-ink-faint);
|
||||
background: var(--color-surface-raised);
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.branch-filter-option input {
|
||||
accent-color: var(--color-accent);
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.branch-filter-backdrop { padding: 8px; }
|
||||
.branch-filter-summary { align-items: stretch; flex-direction: column; }
|
||||
.branch-filter-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||
}
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
let customVisibleBranches = $state<Set<string>>(new Set());
|
||||
let loadedVisibilityRepository = $state("");
|
||||
let branchDialogOpen = $state(false);
|
||||
let localBranchGroupOpen = $state(true);
|
||||
let remoteBranchGroupOpen = $state(false);
|
||||
let expandedRefsCommitHash = $state("");
|
||||
let panelElement = $state<HTMLElement | null>(null);
|
||||
let contextCommit = $state<GitCommit | null>(null);
|
||||
@@ -428,6 +430,8 @@
|
||||
}
|
||||
|
||||
function openBranchDialog() {
|
||||
localBranchGroupOpen = true;
|
||||
remoteBranchGroupOpen = false;
|
||||
branchDialogOpen = true;
|
||||
}
|
||||
|
||||
@@ -1202,32 +1206,62 @@
|
||||
|
||||
<div class="branch-filter-dialog-list">
|
||||
{#if localBranchNames.length > 0}
|
||||
<span class="branch-filter-group-label">Local</span>
|
||||
{#each localBranchNames as branch}
|
||||
<label class:muted={!branchIsVisible(branch)} class="branch-filter-option" title={branch}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={branchIsVisible(branch)}
|
||||
onchange={() => toggleGraphBranch(branch)}
|
||||
/>
|
||||
<GitBranch size={14} aria-hidden="true" />
|
||||
<span>{branch}</span>
|
||||
</label>
|
||||
{/each}
|
||||
<section class="branch-filter-group">
|
||||
<button
|
||||
class="branch-filter-group-toggle"
|
||||
type="button"
|
||||
aria-expanded={localBranchGroupOpen}
|
||||
onclick={() => { localBranchGroupOpen = !localBranchGroupOpen; }}
|
||||
>
|
||||
{#if localBranchGroupOpen}<ChevronDown size={14} aria-hidden="true" />{:else}<ChevronRight size={14} aria-hidden="true" />{/if}
|
||||
<span>Local</span>
|
||||
<em>{localBranchNames.filter(branchIsVisible).length}/{localBranchNames.length}</em>
|
||||
</button>
|
||||
{#if localBranchGroupOpen}
|
||||
<div class="branch-filter-group-list">
|
||||
{#each localBranchNames as branch}
|
||||
<label class:muted={!branchIsVisible(branch)} class="branch-filter-option" title={branch}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={branchIsVisible(branch)}
|
||||
onchange={() => toggleGraphBranch(branch)}
|
||||
/>
|
||||
<GitBranch size={14} aria-hidden="true" />
|
||||
<span>{branch}</span>
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
{/if}
|
||||
{#if remoteBranchNames.length > 0}
|
||||
<span class="branch-filter-group-label">Remote</span>
|
||||
{#each remoteBranchNames as branch}
|
||||
<label class:muted={!branchIsVisible(branch)} class="branch-filter-option remote" title={branch}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={branchIsVisible(branch)}
|
||||
onchange={() => toggleGraphBranch(branch)}
|
||||
/>
|
||||
<GitBranch size={14} aria-hidden="true" />
|
||||
<span>{branch}</span>
|
||||
</label>
|
||||
{/each}
|
||||
<section class="branch-filter-group">
|
||||
<button
|
||||
class="branch-filter-group-toggle"
|
||||
type="button"
|
||||
aria-expanded={remoteBranchGroupOpen}
|
||||
onclick={() => { remoteBranchGroupOpen = !remoteBranchGroupOpen; }}
|
||||
>
|
||||
{#if remoteBranchGroupOpen}<ChevronDown size={14} aria-hidden="true" />{:else}<ChevronRight size={14} aria-hidden="true" />{/if}
|
||||
<span>Remote</span>
|
||||
<em>{remoteBranchNames.filter(branchIsVisible).length}/{remoteBranchNames.length}</em>
|
||||
</button>
|
||||
{#if remoteBranchGroupOpen}
|
||||
<div class="branch-filter-group-list">
|
||||
{#each remoteBranchNames as branch}
|
||||
<label class:muted={!branchIsVisible(branch)} class="branch-filter-option" title={branch}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={branchIsVisible(branch)}
|
||||
onchange={() => toggleGraphBranch(branch)}
|
||||
/>
|
||||
<GitBranch size={14} aria-hidden="true" />
|
||||
<span>{branch}</span>
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -660,8 +660,12 @@
|
||||
display: grid;
|
||||
place-items: center;
|
||||
background:
|
||||
radial-gradient(circle at 50% 38%, rgba(111, 140, 255, 0.1), transparent 55%),
|
||||
rgba(7, 10, 16, 0.62);
|
||||
radial-gradient(
|
||||
circle at 50% 38%,
|
||||
color-mix(in srgb, var(--color-accent) 13%, transparent),
|
||||
transparent 55%
|
||||
),
|
||||
var(--app-dialog-backdrop);
|
||||
backdrop-filter: blur(4px);
|
||||
animation: status-panel-overlay-in 120ms ease;
|
||||
}
|
||||
@@ -673,13 +677,13 @@
|
||||
gap: 12px;
|
||||
width: min(300px, calc(100% - 32px));
|
||||
padding: 26px 28px 26px;
|
||||
border: 1px solid rgba(90, 111, 154, 0.28);
|
||||
border: 1px solid var(--color-border-input);
|
||||
border-radius: 16px;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(23, 29, 43, 0.92), rgba(12, 17, 27, 0.94)),
|
||||
var(--color-surface-raised);
|
||||
var(--app-panel-highlight),
|
||||
var(--app-dialog-bg);
|
||||
color: var(--color-ink);
|
||||
box-shadow: 0 18px 44px rgba(0, 0, 0, 0.34), inset 0 1px 0 rgba(255, 255, 255, 0.05);
|
||||
box-shadow: var(--app-dialog-shadow);
|
||||
}
|
||||
|
||||
.status-panel-overlay-mark {
|
||||
@@ -694,7 +698,7 @@
|
||||
.status-panel-overlay-halo {
|
||||
position: absolute;
|
||||
inset: 6px;
|
||||
border: 1px solid rgba(111, 140, 255, 0.22);
|
||||
border: 1px solid color-mix(in srgb, var(--color-primary) 34%, transparent);
|
||||
border-radius: 22px;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
@@ -703,7 +707,7 @@
|
||||
}
|
||||
.status-panel-overlay-halo.halo-two {
|
||||
inset: 16px;
|
||||
border-color: rgba(77, 182, 214, 0.24);
|
||||
border-color: color-mix(in srgb, var(--color-accent) 38%, transparent);
|
||||
animation: status-panel-overlay-halo-breathe 2.4s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
@@ -721,16 +725,16 @@
|
||||
stroke-linecap: round;
|
||||
stroke-dasharray: 165;
|
||||
stroke-dashoffset: 165;
|
||||
filter: drop-shadow(0 0 6px rgba(77, 182, 214, 0.32));
|
||||
filter: drop-shadow(0 0 6px color-mix(in srgb, var(--color-accent) 38%, transparent));
|
||||
animation: status-panel-overlay-trace-draw 2.6s ease-in-out infinite;
|
||||
}
|
||||
.status-panel-overlay-traces .trace-main { stroke: #6f8cff; }
|
||||
.status-panel-overlay-traces .trace-main { stroke: var(--color-primary); }
|
||||
.status-panel-overlay-traces .trace-branch {
|
||||
stroke: #4db6d6;
|
||||
stroke: var(--color-accent);
|
||||
animation-delay: 0.28s;
|
||||
}
|
||||
.status-panel-overlay-traces .trace-cut {
|
||||
stroke: rgba(177, 186, 208, 0.42);
|
||||
stroke: color-mix(in srgb, var(--color-ink-muted) 52%, transparent);
|
||||
stroke-dasharray: 128;
|
||||
stroke-dashoffset: 128;
|
||||
animation-delay: 0.55s;
|
||||
@@ -743,8 +747,8 @@
|
||||
height: 64px;
|
||||
object-fit: contain;
|
||||
filter:
|
||||
drop-shadow(0 8px 12px rgba(0, 0, 0, 0.5))
|
||||
drop-shadow(0 0 10px rgba(77, 182, 214, 0.2));
|
||||
drop-shadow(0 8px 12px color-mix(in srgb, var(--color-ink) 24%, transparent))
|
||||
drop-shadow(0 0 10px color-mix(in srgb, var(--color-accent) 24%, transparent));
|
||||
animation: status-panel-overlay-icon-float 2.4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@@ -765,15 +769,16 @@
|
||||
height: 4px;
|
||||
overflow: hidden;
|
||||
border-radius: 999px;
|
||||
background: rgba(111, 140, 255, 0.14);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
background: color-mix(in srgb, var(--color-primary) 12%, var(--color-surface-dim));
|
||||
}
|
||||
.status-panel-overlay-bar span {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 46%;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(90deg, transparent, #6f8cff 40%, #4db6d6 74%, transparent);
|
||||
box-shadow: 0 0 12px rgba(77, 182, 214, 0.26);
|
||||
background: linear-gradient(90deg, transparent, var(--color-primary) 40%, var(--color-accent) 74%, transparent);
|
||||
box-shadow: 0 0 12px color-mix(in srgb, var(--color-accent) 32%, transparent);
|
||||
animation: status-panel-overlay-bar-slide 1.35s ease-in-out infinite;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user