fix: restyle tab overflow chevrons to subtle ghost icons with fade masks

Replace prominent outlined chevron buttons with borderless ghost icons
and gradient fade masks for a cleaner overflow indicator. Reset shell-level
button custom properties to prevent global button styles from bleeding through.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-22 17:26:36 +01:00
parent 2d9ca44c26
commit 984d0430d3
2 changed files with 53 additions and 15 deletions

View File

@@ -30,47 +30,61 @@
border-bottom: 1px solid var(--tabs-border);
}
/* Chevron scroll buttons — styled like .outline.secondary.small */
/* Chevron scroll buttons — ghost icons, visible only on overflow.
Reset shell-level button custom properties so the global button
styles (app-shell.css) do not bleed through. */
.app-tabs-nav-wrap > .app-tabs-chevron {
--app-background-color: transparent;
--app-border-color: transparent;
--app-color: var(--tabs-muted);
--app-box-shadow: none;
flex: 0 0 auto;
display: none;
align-items: center;
justify-content: center;
border: 1px solid var(--app-border);
border-radius: var(--app-border-radius);
background-color: transparent;
color: var(--app-secondary);
font-size: var(--text-sm);
line-height: var(--leading-none);
border: none;
border-radius: 50%;
background: transparent;
color: var(--tabs-muted);
font-size: var(--text-xs);
line-height: 1;
width: 24px;
height: 24px;
padding: 0;
box-shadow: none;
cursor: pointer;
z-index: 1;
z-index: 2;
margin-block: auto;
transition:
background-color var(--app-transition),
border-color var(--app-transition),
color var(--app-transition);
color var(--app-transition),
opacity var(--app-transition);
}
.app-tabs-nav-wrap > .app-tabs-chevron:hover,
.app-tabs-nav-wrap > .app-tabs-chevron:focus-visible {
border-color: var(--app-secondary-hover-border);
color: var(--app-secondary-hover);
--app-background-color: color-mix(in srgb, var(--app-contrast) 8%, transparent);
--app-border-color: transparent;
--app-color: var(--app-contrast);
--app-box-shadow: none;
background: color-mix(in srgb, var(--app-contrast) 8%, transparent);
color: var(--app-contrast);
}
.app-tabs-nav-wrap > .app-tabs-chevron[disabled] {
opacity: 0.25;
opacity: 0;
cursor: default;
pointer-events: none;
}
.app-tabs-nav-wrap > .app-tabs-chevron--start {
order: -1;
margin-inline-end: 4px;
margin-inline-end: 2px;
}
.app-tabs-nav-wrap > .app-tabs-chevron--end {
order: 1;
margin-inline-start: 4px;
margin-inline-start: 2px;
}
/* Show chevrons when overflow is detected */
@@ -78,6 +92,28 @@
display: flex;
}
/* Gradient fade masks — only rendered when the corresponding chevron is visible */
.app-tabs-nav-wrap.has-overflow:not(.at-start)::before,
.app-tabs-nav-wrap.has-overflow:not(.at-end)::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
width: 32px;
pointer-events: none;
z-index: 1;
}
.app-tabs-nav-wrap.has-overflow:not(.at-start)::before {
left: 24px;
background: linear-gradient(to right, var(--app-card-background-color, var(--app-background-color)), transparent);
}
.app-tabs-nav-wrap.has-overflow:not(.at-end)::after {
right: 24px;
background: linear-gradient(to left, var(--app-card-background-color, var(--app-background-color)), transparent);
}
/* ------------------------------------------------------------------ */
/* The scrollable tab strip */
/* ------------------------------------------------------------------ */

View File

@@ -406,6 +406,8 @@ function initChevronScroll(nav) {
const atEnd = nav.scrollLeft + nav.clientWidth >= nav.scrollWidth - SCROLL_THRESHOLD;
btnStart.disabled = atStart;
btnEnd.disabled = atEnd;
wrap.classList.toggle('at-start', atStart);
wrap.classList.toggle('at-end', atEnd);
};
bind(nav, 'scroll', update, { passive: true });