feat(ui): refine history graph visuals and layout

Refines history panel visuals and layout, including min width handling.
Removes the old branch visibility select in favor of a dialog button.
It also adds a graph connector to show primary branches.
Adds branch chips, icons, and hover effects to commits for clarity.

- History panel visuals and min width updated to improve layout.
- Removed branch visibility select; added dialog to customize branches.
- Branch chips and graph connectors enhanced with icons and hover effects.
This commit is contained in:
Christoph Brandau
2026-08-13 18:01:10 +02:00
parent 608b3131d2
commit ca14fac90c
3 changed files with 226 additions and 104 deletions
+205 -78
View File
@@ -292,58 +292,21 @@
align-items: center;
flex: 0 0 auto;
justify-content: flex-end;
gap: 5px;
gap: 8px;
min-width: 0;
}
.graph-visibility-select {
position: relative;
display: inline-flex;
align-items: center;
gap: 5px;
min-height: 28px;
padding: 0 7px;
border: 1px solid rgba(94,110,156,0.2);
border-radius: 6px;
color: var(--color-ink-dim);
background: rgba(255,255,255,0.035);
}
.graph-visibility-select > svg:first-child { color: #76d995; }
.graph-visibility-select > svg:last-child { position: absolute; right: 6px; pointer-events: none; }
.graph-visibility-label {
color: var(--color-ink-faint);
font-size: 9px;
font-weight: 800;
letter-spacing: .05em;
text-transform: uppercase;
}
.graph-visibility-select select {
min-width: 62px;
height: 24px;
padding: 0 18px 0 2px;
border: 0;
outline: 0;
appearance: none;
color: var(--color-ink);
background: transparent;
box-shadow: none;
cursor: pointer;
font-size: 11px;
font-weight: 800;
}
.graph-visibility-select select:focus { box-shadow: none; }
.graph-branch-dialog-button {
display: inline-flex;
align-items: center;
gap: 0;
gap: 6px;
min-height: 26px;
padding: 0 5px;
border: 1px solid rgba(94,110,156,0.18);
border-radius: 6px;
color: var(--color-ink-dim);
background: rgba(255,255,255,0.03);
padding: 0 9px;
overflow: hidden;
border: 1px solid rgba(91,209,138,0.24);
border-radius: 999px;
color: #b6f1c4;
background: rgba(34,68,48,0.28);
font-size: 11px;
font-weight: 800;
white-space: nowrap;
@@ -351,16 +314,15 @@
}
.graph-branch-dialog-button:hover {
border-color: rgba(91,209,138,0.32);
color: var(--color-ink);
background: rgba(34,68,48,0.24);
border-color: rgba(91,209,138,0.42);
background: rgba(34,68,48,0.42);
}
.graph-branch-dialog-button span {
padding: 1px 4px;
border-radius: 4px;
color: #9fdcaf;
background: transparent;
padding: 1px 5px;
border-radius: 999px;
color: #061021;
background: #6ce18f;
font-size: 10px;
line-height: 1.2;
}
@@ -1544,7 +1506,7 @@
.workspace {
display: grid;
grid-template-columns: minmax(220px, var(--left-sidebar-width, 280px)) 8px minmax(0, 1fr) 8px minmax(560px, var(--history-aside-width, 620px));
grid-template-columns: minmax(220px, var(--left-sidebar-width, 280px)) 8px minmax(0, 1fr) 8px minmax(var(--history-aside-min-width, 420px), var(--history-aside-width, 620px));
flex: 1 1 0;
min-width: 0;
min-height: 0;
@@ -2537,13 +2499,19 @@
white-space: nowrap;
}
.commit-ref-area { display: grid; gap: 5px; min-width: 0; }
.commit-ref-area {
position: relative;
z-index: 3;
display: grid;
gap: 5px;
min-width: 0;
}
.commit-ref-strip {
display: flex;
align-items: center;
gap: 4px;
min-width: 0;
min-height: 19px;
min-height: 20px;
}
.compact-ref-chip {
display: inline-flex;
@@ -2564,12 +2532,37 @@
line-height: 1;
white-space: nowrap;
}
.compact-ref-chip.branch {
flex: 0 1 auto;
max-width: 22px;
height: 20px;
margin-left: -10px;
padding: 0 5px;
border-color: color-mix(in srgb, var(--ref-lane-color, #69a7ff) 34%, transparent);
border-left-width: 2px;
border-radius: 0 5px 5px 0 !important;
color: #dce9ff;
background:
linear-gradient(90deg, color-mix(in srgb, var(--ref-lane-color, #69a7ff) 14%, rgba(18,24,36,.96)), rgba(18,24,36,.82));
box-shadow: inset 2px 0 0 color-mix(in srgb, var(--ref-lane-color, #69a7ff) 72%, transparent);
transition:
max-width 190ms cubic-bezier(.2,.75,.25,1),
padding-right 190ms cubic-bezier(.2,.75,.25,1),
border-color 140ms ease,
background 140ms ease,
box-shadow 140ms ease;
}
.compact-ref-branch-icon {
flex: 0 0 auto;
color: var(--ref-lane-color, #69a7ff);
filter: drop-shadow(0 0 3px color-mix(in srgb, var(--ref-lane-color, #69a7ff) 28%, transparent));
transition: transform 190ms cubic-bezier(.2,.75,.25,1);
}
.compact-ref-chip > span {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
}
.compact-ref-chip.branch > i,
.commit-ref-detail-item > i {
flex: 0 0 auto;
width: 6px;
@@ -2579,20 +2572,56 @@
box-shadow: 0 0 0 2px color-mix(in srgb, var(--ref-lane-color, #69a7ff) 18%, transparent);
}
.compact-ref-chip.current {
border-color: color-mix(in srgb, var(--ref-lane-color, #69a7ff) 52%, transparent);
border-color: color-mix(in srgb, var(--ref-lane-color, #69a7ff) 62%, transparent);
color: #eaf2ff;
background: color-mix(in srgb, var(--ref-lane-color, #69a7ff) 16%, rgba(18,24,36,.92));
background:
linear-gradient(90deg, color-mix(in srgb, var(--ref-lane-color, #69a7ff) 25%, rgba(18,24,36,.96)), rgba(18,24,36,.9));
}
.compact-ref-chip.remote {
border-color: rgba(122,172,255,0.22);
border-color: color-mix(in srgb, var(--ref-lane-color, #69a7ff) 38%, transparent);
color: #bcd2ff;
background: rgba(31,43,72,0.52);
background:
linear-gradient(90deg, color-mix(in srgb, var(--ref-lane-color, #69a7ff) 14%, rgba(20,27,42,.94)), rgba(20,27,42,.84));
}
.compact-ref-chip.branch > span,
.compact-ref-chip.branch > small {
opacity: 0;
transition: opacity 80ms ease;
}
.graph-row:hover .compact-ref-chip.branch,
.graph-row.selected .compact-ref-chip.branch,
.graph-row:focus-within .compact-ref-chip.branch {
max-width: min(62%, 260px);
padding-right: 8px;
border-color: color-mix(in srgb, var(--ref-lane-color, #69a7ff) 64%, transparent);
background:
linear-gradient(90deg, color-mix(in srgb, var(--ref-lane-color, #69a7ff) 24%, rgba(18,24,36,.98)), rgba(18,24,36,.9));
box-shadow:
inset 2px 0 0 var(--ref-lane-color, #69a7ff),
0 3px 12px color-mix(in srgb, var(--ref-lane-color, #69a7ff) 12%, rgba(0,0,0,.24));
}
.graph-row:hover .compact-ref-branch-icon,
.graph-row.selected .compact-ref-branch-icon,
.graph-row:focus-within .compact-ref-branch-icon {
transform: translateX(1px);
}
.graph-row:hover .compact-ref-chip.branch > span,
.graph-row:hover .compact-ref-chip.branch > small,
.graph-row.selected .compact-ref-chip.branch > span,
.graph-row.selected .compact-ref-chip.branch > small,
.graph-row:focus-within .compact-ref-chip.branch > span,
.graph-row:focus-within .compact-ref-chip.branch > small {
opacity: 1;
transition-delay: 55ms;
transition-duration: 120ms;
}
.compact-ref-chip.tag {
flex: 0 1 auto;
border-color: rgba(224,180,92,0.22);
max-width: min(32%, 150px);
padding-inline: 4px;
border-color: transparent;
color: #dbc078;
background: rgba(224,180,92,0.075);
background: transparent;
}
.compact-ref-chip.tag svg { flex: 0 0 auto; }
.compact-ref-chip small {
@@ -2614,10 +2643,10 @@
min-height: 19px;
height: 19px;
padding: 0 5px;
border-color: rgba(94,110,156,0.2);
border-radius: 5px;
border-color: transparent;
border-radius: 4px;
color: var(--color-ink-dim);
background: rgba(255,255,255,0.035);
background: rgba(255,255,255,0.025);
font-family: var(--font-mono);
font-size: 9px;
font-weight: 800;
@@ -2832,6 +2861,10 @@
stroke-dasharray: 4 4;
filter: drop-shadow(0 0 3px rgba(122,172,255,0.2));
}
.graph-svg path.graph-ref-connector {
opacity: 0.35;
stroke-linecap: round;
}
.graph-dot {
position: absolute;
z-index: 2;
@@ -2871,6 +2904,7 @@
background: rgba(31,43,72,0.88);
}
.commit-body {
position: relative;
display: grid;
gap: 5px;
min-width: 0;
@@ -2878,6 +2912,39 @@
background: rgba(18,24,36,0.5);
transition: background 120ms ease;
}
.commit-body.has-branch-ref::before {
content: "";
position: absolute;
z-index: 2;
top: 24px;
bottom: calc(50% + 16px);
left: -16px;
width: 16px;
min-height: 14px;
border-top: 1.5px solid var(--ref-lane-color, #69a7ff);
border-left: 1.5px solid var(--ref-lane-color, #69a7ff);
border-top-left-radius: 14px;
opacity: .35;
pointer-events: none;
filter: drop-shadow(0 0 3px color-mix(in srgb, var(--ref-lane-color, #69a7ff) 12%, transparent));
transition: opacity 140ms ease, filter 140ms ease;
}
.commit-body.has-branch-ref::after {
content: "";
position: absolute;
z-index: 2;
top: calc(50% - 16px);
left: -32px;
width: 16px;
height: 16px;
border-right: 1.5px solid var(--ref-lane-color, #69a7ff);
border-bottom: 1.5px solid var(--ref-lane-color, #69a7ff);
border-bottom-right-radius: 14px;
opacity: .35;
pointer-events: none;
filter: drop-shadow(0 0 3px color-mix(in srgb, var(--ref-lane-color, #69a7ff) 12%, transparent));
transition: opacity 140ms ease, filter 140ms ease;
}
.graph-row + .graph-row .commit-body { border-top: 1px solid rgba(226,232,240,0.075); }
.graph-row.graph-ahead-row .commit-body {
box-shadow: inset 3px 0 0 rgba(224,160,64,0.72);
@@ -2887,6 +2954,18 @@
}
.graph-row:hover .commit-body { background: rgba(30,39,57,0.72); }
.graph-row:hover .graph-svg path { opacity: 1; stroke-width: 2.65; }
.graph-row:hover .graph-svg path.graph-ref-connector,
.graph-row.selected .graph-svg path.graph-ref-connector,
.graph-row:focus-within .graph-svg path.graph-ref-connector { opacity: .95; stroke-width: 1.8; }
.graph-row:hover .commit-body.has-branch-ref::before,
.graph-row:hover .commit-body.has-branch-ref::after,
.graph-row.selected .commit-body.has-branch-ref::before,
.graph-row.selected .commit-body.has-branch-ref::after,
.graph-row:focus-within .commit-body.has-branch-ref::before,
.graph-row:focus-within .commit-body.has-branch-ref::after {
opacity: .95;
filter: drop-shadow(0 0 4px color-mix(in srgb, var(--ref-lane-color, #69a7ff) 24%, transparent));
}
.graph-row:hover .graph-svg path.hidden-branch { opacity: 0.12; stroke-width: 2.2; }
.graph-row:hover .graph-dot { transform: translate(-50%, -50%) scale(1.12); }
.graph-row:hover .graph-dot.hidden-branch { transform: translate(-50%, -50%) scale(1); }
@@ -2899,6 +2978,28 @@
rgba(20,27,40,0.62);
}
@media (prefers-reduced-motion: reduce) {
.compact-ref-chip.branch,
.compact-ref-chip.branch > span,
.compact-ref-chip.branch > small,
.compact-ref-branch-icon,
.commit-body.has-branch-ref::before,
.commit-body.has-branch-ref::after {
transition: none;
}
}
@media (hover: none) {
.compact-ref-chip.branch {
max-width: min(62%, 260px);
padding-right: 8px;
}
.compact-ref-chip.branch > span,
.compact-ref-chip.branch > small {
opacity: 1;
}
}
/* --- Compare panel --- */
.compare-panel {
@@ -5621,7 +5722,7 @@ input:focus, textarea:focus, select:focus { box-shadow: 0 0 0 3px color-mix(in s
.repo-toolbar-divider { height: 34px; margin-inline: 6px; }
.workspace {
grid-template-columns: minmax(220px, var(--left-sidebar-width, 280px)) 7px minmax(360px, 1fr) 7px minmax(560px, var(--history-aside-width, 620px));
grid-template-columns: minmax(220px, var(--left-sidebar-width, 280px)) 7px minmax(360px, 1fr) 7px minmax(var(--history-aside-min-width, 420px), var(--history-aside-width, 620px));
flex: 1 1 0;
padding: 0;
background: var(--color-border-subtle);
@@ -5989,32 +6090,58 @@ input:focus, textarea:focus, select:focus { box-shadow: 0 0 0 3px color-mix(in s
}
:root[data-theme="light"] .compact-ref-chip.branch {
border-color: rgba(31,128,76,0.22);
color: #146b3b;
background: rgba(224,246,233,0.92);
border-color: color-mix(in srgb, var(--ref-lane-color, #315fd6) 48%, rgba(49,95,214,.16));
color: #18345f;
background:
linear-gradient(90deg, color-mix(in srgb, var(--ref-lane-color, #315fd6) 14%, #f7faff), #f7faff);
}
:root[data-theme="light"] .compact-ref-chip.current {
border-color: color-mix(in srgb, var(--ref-lane-color, #315fd6) 48%, rgba(49,95,214,.2));
border-color: color-mix(in srgb, var(--ref-lane-color, #315fd6) 58%, rgba(49,95,214,.2));
color: #18345f;
background: color-mix(in srgb, var(--ref-lane-color, #315fd6) 12%, #f7faff);
background:
linear-gradient(90deg, color-mix(in srgb, var(--ref-lane-color, #315fd6) 20%, #f7faff), #f7faff);
}
:root[data-theme="light"] .compact-ref-chip.remote,
:root[data-theme="light"] .branch-filter-option.remote {
border-color: rgba(49,95,214,0.22);
color: #315fd6;
background: rgba(231,237,255,0.92);
}
:root[data-theme="light"] .compact-ref-chip.remote {
border-color: color-mix(in srgb, var(--ref-lane-color, #315fd6) 42%, rgba(49,95,214,.16));
color: #315fd6;
background:
linear-gradient(90deg, color-mix(in srgb, var(--ref-lane-color, #315fd6) 12%, #f7faff), #f7faff);
}
:root[data-theme="light"] .graph-row:hover .compact-ref-chip.branch,
:root[data-theme="light"] .graph-row.selected .compact-ref-chip.branch,
:root[data-theme="light"] .graph-row:focus-within .compact-ref-chip.branch {
border-color: color-mix(in srgb, var(--ref-lane-color, #315fd6) 62%, rgba(49,95,214,.2));
background:
linear-gradient(90deg, color-mix(in srgb, var(--ref-lane-color, #315fd6) 22%, #f7faff), #ffffff);
box-shadow:
inset 2px 0 0 var(--ref-lane-color, #315fd6),
0 3px 12px color-mix(in srgb, var(--ref-lane-color, #315fd6) 10%, rgba(34,49,78,.16));
}
:root[data-theme="light"] .compact-ref-chip.tag,
:root[data-theme="light"] .commit-ref-detail-item.tag {
color: #8b5d0e;
background: rgba(255,244,224,.9);
}
:root[data-theme="light"] .compact-ref-overflow,
:root[data-theme="light"] .graph-visibility-select,
:root[data-theme="light"] .compact-ref-chip.tag {
background: transparent;
}
:root[data-theme="light"] .compact-ref-overflow {
color: #60708a;
border-color: transparent;
background: rgba(49,95,214,.035);
}
:root[data-theme="light"] .graph-branch-dialog-button {
color: #475873;
border-color: rgba(49,95,214,.16);
@@ -6236,16 +6363,16 @@ input:focus, textarea:focus, select:focus { box-shadow: 0 0 0 3px color-mix(in s
/* --- Responsive breakpoints --- */
@media (min-width: 1800px) {
.workspace { grid-template-columns: minmax(220px, var(--left-sidebar-width, 320px)) 8px minmax(0, 1fr) 8px minmax(560px, var(--history-aside-width, 680px)); }
.workspace { grid-template-columns: minmax(220px, var(--left-sidebar-width, 320px)) 8px minmax(0, 1fr) 8px minmax(var(--history-aside-min-width, 420px), var(--history-aside-width, 680px)); }
}
@media (max-width: 1400px) {
.workspace { grid-template-columns: minmax(200px, var(--left-sidebar-width, 265px)) 8px minmax(0, 1fr) 8px minmax(540px, var(--history-aside-width, 580px)); }
.workspace { grid-template-columns: minmax(200px, var(--left-sidebar-width, 265px)) 8px minmax(0, 1fr) 8px minmax(var(--history-aside-min-width, 420px), var(--history-aside-width, 580px)); }
}
/* Stack CommitPanel below StatusPanel; history panels stay side by side */
@media (max-width: 1100px) {
.workspace { grid-template-columns: minmax(185px, var(--left-sidebar-width, 220px)) 8px minmax(0, 1fr) 8px minmax(500px, var(--history-aside-width, 560px)); }
.workspace { grid-template-columns: minmax(185px, var(--left-sidebar-width, 220px)) 8px minmax(0, 1fr) 8px minmax(var(--history-aside-min-width, 420px), var(--history-aside-width, 560px)); }
.top-section { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) 14px var(--commit-panel-height, 190px); }
}