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>
192 lines
5.3 KiB
CSS
192 lines
5.3 KiB
CSS
@layer components {
|
|
/* Tab navigation — scrollable strip with chevron overflow, active/invalid states, no-JS fallback. */
|
|
.app-tabs {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--app-spacing);
|
|
}
|
|
|
|
/* No-JS fallback: show only first tab panel. */
|
|
html.no-js [data-tabs] [data-tab-panel] {
|
|
display: none;
|
|
}
|
|
|
|
html.no-js [data-tabs] [data-tab-panel]:first-of-type {
|
|
display: block;
|
|
}
|
|
|
|
/* JS mode: keep panels hidden until tab init completed (prevents flash). */
|
|
html.js [data-tabs]:not([data-tabs-ready="1"]) [data-tab-panel] {
|
|
display: none !important;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Tab nav wrapper — holds optional chevron buttons + scrollable nav */
|
|
/* ------------------------------------------------------------------ */
|
|
.app-tabs-nav-wrap {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: stretch;
|
|
border-bottom: 1px solid var(--tabs-border);
|
|
}
|
|
|
|
/* 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: 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: 2;
|
|
margin-block: auto;
|
|
transition:
|
|
background-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 {
|
|
--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;
|
|
cursor: default;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.app-tabs-nav-wrap > .app-tabs-chevron--start {
|
|
order: -1;
|
|
margin-inline-end: 2px;
|
|
}
|
|
|
|
.app-tabs-nav-wrap > .app-tabs-chevron--end {
|
|
order: 1;
|
|
margin-inline-start: 2px;
|
|
}
|
|
|
|
/* Show chevrons when overflow is detected */
|
|
.app-tabs-nav-wrap.has-overflow > .app-tabs-chevron {
|
|
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 */
|
|
/* ------------------------------------------------------------------ */
|
|
.app-tabs-nav {
|
|
display: flex;
|
|
border-bottom: 1px solid var(--tabs-border); /* No-JS fallback border */
|
|
overflow-x: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
padding-block-start: 2px;
|
|
padding-left: 2px;
|
|
white-space: nowrap;
|
|
flex: 1 1 0%;
|
|
scroll-behavior: smooth;
|
|
}
|
|
|
|
/* When wrapped by JS, the wrapper owns the border */
|
|
.app-tabs-nav-wrap > .app-tabs-nav {
|
|
border-bottom: none;
|
|
}
|
|
|
|
/* When JS is active: hide the native scrollbar (chevrons take over) */
|
|
html.js .app-tabs-nav {
|
|
scrollbar-width: none; /* Firefox */
|
|
}
|
|
|
|
html.js .app-tabs-nav::-webkit-scrollbar {
|
|
display: none; /* Chrome / Safari / Edge */
|
|
}
|
|
|
|
.app-tabs-nav button,
|
|
.app-tabs-nav a {
|
|
background: transparent;
|
|
border: 0;
|
|
padding: 5px 10px 5px 10px;
|
|
color: var(--tabs-muted) !important;
|
|
cursor: pointer;
|
|
border-bottom: 2px solid transparent;
|
|
text-decoration: none;
|
|
border-radius: 0;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.app-tabs-nav button:hover,
|
|
.app-tabs-nav button:focus-visible,
|
|
.app-tabs-nav a:hover,
|
|
.app-tabs-nav a:focus-visible {
|
|
--app-color: inherit;
|
|
color: var(--app-color) !important;
|
|
}
|
|
|
|
.app-tabs-nav button.is-active,
|
|
.app-tabs-nav a.is-active {
|
|
--app-color: inherit;
|
|
color: var(--app-color) !important;
|
|
border-color: var(--tabs-active);
|
|
}
|
|
|
|
.app-tabs-nav button.has-invalid,
|
|
.app-tabs-nav a.has-invalid {
|
|
color: var(--app-danger, #dc3545) !important;
|
|
}
|
|
|
|
[data-tab-panel][hidden] {
|
|
display: none;
|
|
}
|
|
|
|
html.js [data-tabs][data-tabs-ready="1"] [data-tab-panel]:not([hidden]) {
|
|
display: block;
|
|
}
|
|
|
|
/* Safety fallback when JS is available but the ready marker is missing. */
|
|
html:not(.no-js) [data-tabs] [data-tab-panel]:not([hidden]) {
|
|
display: block;
|
|
}
|
|
}
|