diff options
| -rw-r--r-- | assets/cgit.css | 36 | |
| -rw-r--r-- | assets/cgit.js | 46 |
2 files changed, 76 insertions, 6 deletions
diff --git a/assets/cgit.css b/assets/cgit.css index 540480c..8c6f7a4 100644 --- a/assets/cgit.css +++ b/assets/cgit.css @@ -263,16 +263,40 @@ div#cgit .tabs { div#cgit .tabs ul { display: flex; - flex-wrap: wrap; align-items: flex-end; flex: 1 1 auto; - gap: 0.1em 0.15em; + min-width: 0; + gap: 0.15em; list-style: none; margin: 0; padding: 0; + overflow-x: auto; + scrollbar-width: none; +} + +div#cgit .tabs ul::-webkit-scrollbar { + display: none; +} + +div#cgit .tabs ul.fade-start { + -webkit-mask-image: linear-gradient(to right, transparent, #000 1.5em); + mask-image: linear-gradient(to right, transparent, #000 1.5em); +} + +div#cgit .tabs ul.fade-end { + -webkit-mask-image: linear-gradient(to left, transparent, #000 1.5em); + mask-image: linear-gradient(to left, transparent, #000 1.5em); +} + +div#cgit .tabs ul.fade-start.fade-end { + -webkit-mask-image: linear-gradient(to right, transparent, #000 1.5em, + #000 calc(100% - 1.5em), transparent); + mask-image: linear-gradient(to right, transparent, #000 1.5em, + #000 calc(100% - 1.5em), transparent); } div#cgit .tabs li { + flex: none; margin: 0; } @@ -283,6 +307,10 @@ div#cgit .tabs a { border-radius: var(--radius) var(--radius) 0 0; } +div#cgit .tabs a:focus-visible { + outline-offset: -2px; +} + div#cgit .tabs a:hover { color: var(--fg); background-color: var(--surface); @@ -1310,6 +1338,10 @@ div#cgit table.ssdiff td.space { } @media (max-width: 640px) { + div#cgit .tabs a { + padding: 0.3em 0.4em; + } + div#cgit .col-desc, div#cgit .col-owner, div#cgit .col-links { diff --git a/assets/cgit.js b/assets/cgit.js index 807f15f..90f06c0 100644 --- a/assets/cgit.js +++ b/assets/cgit.js @@ -2,10 +2,11 @@ * The client side script that cgit serves with every page. Its main job is * to refresh the relative ages that cgit_print_age renders in * source/ui-shared.c, so the thresholds, suffixes and class names tabulated - * below mirror the constants there and the two have to move together. One - * smaller piece follows, the highlight laid over the source line a URL - * fragment names. Each piece is wrapped in a function of its own so that - * nothing is left behind in the global scope. + * below mirror the constants there and the two have to move together. Two + * smaller pieces follow, the highlight laid over the source line a URL + * fragment names, and the tabs kept in view on a window too narrow for them. + * Each piece is wrapped in a function of its own so that nothing is left + * behind in the global scope. */ (function () { @@ -166,3 +167,40 @@ window.cgit = window.cgit || {}; window.cgit.highlightLines = place_bar; })(); + +/* + * The tabs scroll sideways when the window is too narrow for them, so the + * active one is brought into view, and the edge past which more tabs are + * hidden is faded to show that the row goes on. + */ + +(function () { + +function fade_tabs(list) { + var hidden = list.scrollWidth - list.clientWidth; + + // A fractional scroll position can stop a pixel short of either end. + list.classList.toggle("fade-start", list.scrollLeft > 1); + list.classList.toggle("fade-end", list.scrollLeft < hidden - 1); +} + +function fit_tabs() { + var list = document.querySelector("nav.tabs ul"); + var active, list_box, tab_box; + + if (!list) + return; + active = list.querySelector("a.active"); + if (active && list.scrollWidth > list.clientWidth) { + list_box = list.getBoundingClientRect(); + tab_box = active.getBoundingClientRect(); + list.scrollLeft += tab_box.left - list_box.left - (list_box.width - tab_box.width) / 2; + } + fade_tabs(list); + list.addEventListener("scroll", function () { fade_tabs(list); }, { passive: true }); + window.addEventListener("resize", function () { fade_tabs(list); }, false); +} + +document.addEventListener("DOMContentLoaded", fit_tabs, false); + +})(); |
